From 569940b9fd60ea40359a8d8f1bbffd5db31b19c8 Mon Sep 17 00:00:00 2001 From: Justin Humm Date: Fri, 12 Mar 2021 19:24:47 +0100 Subject: [PATCH] nixos/hledger-web: add stateDir, use own user, fix ExecStart This allows for shared hledger installations, where the web interface is available via network and multiple user share a SSH access to the hledger user. Also added `--serve` to the CLI options, as hledger-web tries to open a webbrowser otherwise: hledger-web: xdg-open: rawSystem: runInteractiveProcess: exec: does not exist (No such file or directory) Co-authored-by: Aaron Andersen --- .../modules/services/web-apps/hledger-web.nix | 78 +++++++++++++++---- nixos/tests/hledger-web.nix | 24 +++--- 2 files changed, 71 insertions(+), 31 deletions(-) diff --git a/nixos/modules/services/web-apps/hledger-web.nix b/nixos/modules/services/web-apps/hledger-web.nix index 43fc4daa177f..f0c9b2b6c4c7 100644 --- a/nixos/modules/services/web-apps/hledger-web.nix +++ b/nixos/modules/services/web-apps/hledger-web.nix @@ -34,11 +34,22 @@ in { ''; }; - journalFile = mkOption { + stateDir = mkOption { type = types.path; - example = "/home/hledger/.hledger.journal"; + default = "/var/lib/hledger-web"; description = '' - Input journal file. + Path the service has access to. If left as the default value this + directory will automatically be created before the hledger-web server + starts, otherwise the sysadmin is responsible for ensuring the + directory exists with appropriate ownership and permissions. + ''; + }; + + journalFiles = mkOption { + type = types.listOf types.str; + default = [ ".hledger.journal" ]; + description = '' + Paths to journal files relative to . ''; }; @@ -50,28 +61,61 @@ in { Base URL, when sharing over a network. ''; }; + + extraOptions = mkOption { + type = types.listOf types.str; + default = []; + example = [ "--forecast" ]; + description = '' + Extra command line arguments to pass to hledger-web. + ''; + }; + }; config = mkIf cfg.enable { - systemd.services.hledger-web = { + + users.users.hledger = { + name = "hledger"; + group = "hledger"; + isSystemUser = true; + home = cfg.stateDir; + useDefaultShell = true; + }; + + users.groups.hledger = {}; + + systemd.services.hledger-web = let + serverArgs = with cfg; escapeShellArgs ([ + "--serve" + "--host=${host}" + "--port=${toString port}" + "--capabilities=${capabilityString}" + (optionalString (cfg.baseUrl != null) "--base-url=${cfg.baseUrl}") + (optionalString (cfg.serveApi) "--serve-api") + ] ++ (map (f: "--file=${stateDir}/${f}") cfg.journalFiles) + ++ extraOptions); + in { description = "hledger-web - web-app for the hledger accounting tool."; documentation = [ https://hledger.org/hledger-web.html ]; wantedBy = [ "multi-user.target" ]; after = [ "networking.target" ]; - serviceConfig = { - ExecStart = '' - ${pkgs.hledger-web}/bin/hledger-web \ - --host=${cfg.host} \ - --port=${toString cfg.port} \ - --file=${cfg.journalFile} \ - "--capabilities=${cfg.capabilities}" \ - ${optionalString (cfg.baseUrl != null) "--base-url=${cfg.baseUrl}"} \ - ${optionalString (cfg.serveApi) "--serve-api"} - ''; - Restart = "always"; - }; + serviceConfig = mkMerge [ + { + ExecStart = "${pkgs.hledger-web}/bin/hledger-web ${serverArgs}"; + Restart = "always"; + WorkingDirectory = cfg.stateDir; + User = "hledger"; + Group = "hledger"; + PrivateTmp = true; + } + (mkIf (cfg.stateDir == "/var/lib/hledger-web") { + StateDirectory = "hledger-web"; + }) + ]; }; + }; - meta.maintainers = with lib.maintainers; [ marijanp ]; + meta.maintainers = with lib.maintainers; [ marijanp erictapen ]; } diff --git a/nixos/tests/hledger-web.nix b/nixos/tests/hledger-web.nix index 378d819437db..a359917edd73 100644 --- a/nixos/tests/hledger-web.nix +++ b/nixos/tests/hledger-web.nix @@ -13,25 +13,21 @@ rec { name = "hledger-web"; meta.maintainers = with lib.maintainers; [ marijanp ]; - nodes = { - server = { config, pkgs, ... }: rec { + nodes = rec { + server = { config, pkgs, ... }: { services.hledger-web = { host = "127.0.0.1"; port = 5000; enable = true; - journalFile = journal; }; - networking.firewall.allowedTCPPorts = [ services.hledger-web.port ]; + networking.firewall.allowedTCPPorts = [ config.services.hledger-web.port ]; + systemd.services.hledger-web.preStart = '' + ln -s ${journal} /var/lib/hledger-web/.hledger.journal + ''; }; - apiserver = { config, pkgs, ... }: rec { - services.hledger-web = { - host = "127.0.0.1"; - port = 5000; - enable = true; - serveApi = true; - journalFile = journal; - }; - networking.firewall.allowedTCPPorts = [ services.hledger-web.port ]; + apiserver = { ... }: { + imports = [ server ]; + services.hledger-web.serveApi = true; }; }; @@ -42,7 +38,7 @@ rec { server.wait_for_open_port(5000) with subtest("Check if web UI is accessible"): page = server.succeed("curl -L http://127.0.0.1:5000") - assert "test.journal" in page + assert ".hledger.journal" in page apiserver.wait_for_unit("hledger-web.service") apiserver.wait_for_open_port(5000)