diff --git a/flake.nix b/flake.nix index a57f5c9..aac6f4a 100644 --- a/flake.nix +++ b/flake.nix @@ -18,17 +18,18 @@ "x86_64-linux" ]; + flake = { + nixosModules.default = import ./nix/module.nix; + nixosModules.personal-backlog = import ./nix/module.nix; + }; + perSystem = { system, + pkgs, ... }: let - pkgs = import nixpkgs { - inherit system; - config.allowUnfree = true; - }; - pre-commit-check = git-hooks.lib.${system}.run { src = ./.; hooks = { @@ -39,6 +40,11 @@ { formatter = pkgs.nixfmt-tree; + packages = { + default = pkgs.callPackage ./nix/package.nix { }; + personal-backlog = pkgs.callPackage ./nix/package.nix { }; + }; + checks = { inherit pre-commit-check; }; diff --git a/nix/module.nix b/nix/module.nix new file mode 100644 index 0000000..9e83abf --- /dev/null +++ b/nix/module.nix @@ -0,0 +1,91 @@ +{ + config, + lib, + pkgs, + ... +}: + +let + cfg = config.services.personal-backlog; + package = pkgs.callPackage ./package.nix { }; +in +{ + options.services.personal-backlog = { + enable = lib.mkEnableOption "Personal Backlog task manager"; + + package = lib.mkOption { + type = lib.types.package; + default = package; + defaultText = lib.literalExpression "pkgs.personal-backlog"; + description = "The personal-backlog package to use."; + }; + + port = lib.mkOption { + type = lib.types.port; + default = 8080; + description = "Port to listen on."; + }; + + dataDir = lib.mkOption { + type = lib.types.path; + default = "/var/lib/personal-backlog"; + description = "Directory to store backlog data."; + }; + + user = lib.mkOption { + type = lib.types.str; + default = "backlog"; + description = "User account under which the service runs."; + }; + + group = lib.mkOption { + type = lib.types.str; + default = "backlog"; + description = "Group under which the service runs."; + }; + + openFirewall = lib.mkOption { + type = lib.types.bool; + default = false; + description = "Whether to open the firewall for the service port."; + }; + }; + + config = lib.mkIf cfg.enable { + users.users.${cfg.user} = { + isSystemUser = true; + group = cfg.group; + home = cfg.dataDir; + createHome = true; + }; + + users.groups.${cfg.group} = { }; + + systemd.services.personal-backlog = { + description = "Personal Backlog Task Manager"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + + serviceConfig = { + Type = "simple"; + User = cfg.user; + Group = cfg.group; + WorkingDirectory = cfg.dataDir; + ExecStart = "${cfg.package}/bin/personal-backlog --port ${toString cfg.port} --dir ${cfg.dataDir}"; + Restart = "on-failure"; + RestartSec = 5; + + StateDirectory = "personal-backlog"; + StateDirectoryMode = "0750"; + + NoNewPrivileges = true; + ProtectSystem = "strict"; + ProtectHome = true; + PrivateTmp = true; + ReadWritePaths = [ cfg.dataDir ]; + }; + }; + + networking.firewall.allowedTCPPorts = lib.mkIf cfg.openFirewall [ cfg.port ]; + }; +} diff --git a/nix/package.nix b/nix/package.nix new file mode 100644 index 0000000..946496c --- /dev/null +++ b/nix/package.nix @@ -0,0 +1,42 @@ +{ + lib, + stdenv, + python3, + makeWrapper, +}: + +stdenv.mkDerivation { + pname = "personal-backlog"; + version = "0.1.0"; + + src = ./..; + + nativeBuildInputs = [ makeWrapper ]; + + buildInputs = [ python3 ]; + + dontBuild = true; + + installPhase = '' + runHook preInstall + + mkdir -p $out/bin $out/share/personal-backlog + + cp server/server.py $out/share/personal-backlog/ + cp -r webapp $out/share/personal-backlog/ + + makeWrapper ${python3}/bin/python3 $out/bin/personal-backlog \ + --add-flags "$out/share/personal-backlog/server.py" + + runHook postInstall + ''; + + meta = with lib; { + description = "A minimalist, single-user task manager where a Markdown file is your database"; + homepage = "https://github.com/alfishe/personal-backlog"; + license = licenses.mit; + maintainers = [ ]; + platforms = platforms.unix; + mainProgram = "personal-backlog"; + }; +}