1{ lib, pkgs, config, ... }:
2with lib;
3let
4 cfg = config.services.hledger-web;
5in {
6 options.services.hledger-web = {
7
8 enable = mkEnableOption (lib.mdDoc "hledger-web service");
9
10 serveApi = mkEnableOption (lib.mdDoc "Serve only the JSON web API, without the web UI");
11
12 host = mkOption {
13 type = types.str;
14 default = "127.0.0.1";
15 description = lib.mdDoc ''
16 Address to listen on.
17 '';
18 };
19
20 port = mkOption {
21 type = types.port;
22 default = 5000;
23 example = 80;
24 description = lib.mdDoc ''
25 Port to listen on.
26 '';
27 };
28
29 capabilities = {
30 view = mkOption {
31 type = types.bool;
32 default = true;
33 description = lib.mdDoc ''
34 Enable the view capability.
35 '';
36 };
37 add = mkOption {
38 type = types.bool;
39 default = false;
40 description = lib.mdDoc ''
41 Enable the add capability.
42 '';
43 };
44 manage = mkOption {
45 type = types.bool;
46 default = false;
47 description = lib.mdDoc ''
48 Enable the manage capability.
49 '';
50 };
51 };
52
53 stateDir = mkOption {
54 type = types.path;
55 default = "/var/lib/hledger-web";
56 description = lib.mdDoc ''
57 Path the service has access to. If left as the default value this
58 directory will automatically be created before the hledger-web server
59 starts, otherwise the sysadmin is responsible for ensuring the
60 directory exists with appropriate ownership and permissions.
61 '';
62 };
63
64 journalFiles = mkOption {
65 type = types.listOf types.str;
66 default = [ ".hledger.journal" ];
67 description = lib.mdDoc ''
68 Paths to journal files relative to {option}`services.hledger-web.stateDir`.
69 '';
70 };
71
72 baseUrl = mkOption {
73 type = with types; nullOr str;
74 default = null;
75 example = "https://example.org";
76 description = lib.mdDoc ''
77 Base URL, when sharing over a network.
78 '';
79 };
80
81 extraOptions = mkOption {
82 type = types.listOf types.str;
83 default = [];
84 example = [ "--forecast" ];
85 description = lib.mdDoc ''
86 Extra command line arguments to pass to hledger-web.
87 '';
88 };
89
90 };
91
92 config = mkIf cfg.enable {
93
94 users.users.hledger = {
95 name = "hledger";
96 group = "hledger";
97 isSystemUser = true;
98 home = cfg.stateDir;
99 useDefaultShell = true;
100 };
101
102 users.groups.hledger = {};
103
104 systemd.services.hledger-web = let
105 capabilityString = with cfg.capabilities; concatStringsSep "," (
106 (optional view "view")
107 ++ (optional add "add")
108 ++ (optional manage "manage")
109 );
110 serverArgs = with cfg; escapeShellArgs ([
111 "--serve"
112 "--host=${host}"
113 "--port=${toString port}"
114 "--capabilities=${capabilityString}"
115 (optionalString (cfg.baseUrl != null) "--base-url=${cfg.baseUrl}")
116 (optionalString (cfg.serveApi) "--serve-api")
117 ] ++ (map (f: "--file=${stateDir}/${f}") cfg.journalFiles)
118 ++ extraOptions);
119 in {
120 description = "hledger-web - web-app for the hledger accounting tool.";
121 documentation = [ "https://hledger.org/hledger-web.html" ];
122 wantedBy = [ "multi-user.target" ];
123 after = [ "networking.target" ];
124 serviceConfig = mkMerge [
125 {
126 ExecStart = "${pkgs.hledger-web}/bin/hledger-web ${serverArgs}";
127 Restart = "always";
128 WorkingDirectory = cfg.stateDir;
129 User = "hledger";
130 Group = "hledger";
131 PrivateTmp = true;
132 }
133 (mkIf (cfg.stateDir == "/var/lib/hledger-web") {
134 StateDirectory = "hledger-web";
135 })
136 ];
137 };
138
139 };
140
141 meta.maintainers = with lib.maintainers; [ marijanp erictapen ];
142}