grafana-alloy: don't build the frontend twice
[NixPkgs.git] / nixos / modules / services / web-apps / firefly-iii-data-importer.nix
blob5d1712a506d817106670631fba030323ba94dce4
2   pkgs,
3   config,
4   lib,
5   ...
6 }:
8 let
9   cfg = config.services.firefly-iii-data-importer;
11   user = cfg.user;
12   group = cfg.group;
14   defaultUser = "firefly-iii-data-importer";
15   defaultGroup = "firefly-iii-data-importer";
17   artisan = "${cfg.package}/artisan";
19   env-file-values = lib.attrsets.mapAttrs' (
20     n: v: lib.attrsets.nameValuePair (lib.strings.removeSuffix "_FILE" n) v
21   ) (lib.attrsets.filterAttrs (n: v: lib.strings.hasSuffix "_FILE" n) cfg.settings);
22   env-nonfile-values = lib.attrsets.filterAttrs (n: v: !lib.strings.hasSuffix "_FILE" n) cfg.settings;
24   data-importer-maintenance = pkgs.writeShellScript "data-importer-maintenance.sh" ''
25     set -a
26     ${lib.strings.toShellVars env-nonfile-values}
27     ${lib.strings.concatLines (
28       lib.attrsets.mapAttrsToList (n: v: "${n}=\"$(< ${v})\"") env-file-values
29     )}
30     set +a
31     ${artisan} package:discover
32     ${artisan} cache:clear
33     ${artisan} config:cache
34   '';
36   commonServiceConfig = {
37     Type = "oneshot";
38     User = user;
39     Group = group;
40     StateDirectory = "firefly-iii-data-importer";
41     ReadWritePaths = [ cfg.dataDir ];
42     WorkingDirectory = cfg.package;
43     PrivateTmp = true;
44     PrivateDevices = true;
45     CapabilityBoundingSet = "";
46     AmbientCapabilities = "";
47     ProtectSystem = "strict";
48     ProtectKernelTunables = true;
49     ProtectKernelModules = true;
50     ProtectControlGroups = true;
51     ProtectClock = true;
52     ProtectHostname = true;
53     ProtectHome = "tmpfs";
54     ProtectKernelLogs = true;
55     ProtectProc = "invisible";
56     ProcSubset = "pid";
57     PrivateNetwork = false;
58     RestrictAddressFamilies = "AF_INET AF_INET6 AF_UNIX";
59     SystemCallArchitectures = "native";
60     SystemCallFilter = [
61       "@system-service @resources"
62       "~@obsolete @privileged"
63     ];
64     RestrictSUIDSGID = true;
65     RemoveIPC = true;
66     NoNewPrivileges = true;
67     RestrictRealtime = true;
68     RestrictNamespaces = true;
69     LockPersonality = true;
70     PrivateUsers = true;
71   };
76   options.services.firefly-iii-data-importer = {
77     enable = lib.mkEnableOption "Firefly III Data Importer";
79     user = lib.mkOption {
80       type = lib.types.str;
81       default = defaultUser;
82       description = "User account under which firefly-iii-data-importer runs.";
83     };
85     group = lib.mkOption {
86       type = lib.types.str;
87       default = if cfg.enableNginx then "nginx" else defaultGroup;
88       defaultText = "If `services.firefly-iii-data-importer.enableNginx` is true then `nginx` else ${defaultGroup}";
89       description = ''
90         Group under which firefly-iii-data-importer runs. It is best to set this to the group
91         of whatever webserver is being used as the frontend.
92       '';
93     };
95     dataDir = lib.mkOption {
96       type = lib.types.path;
97       default = "/var/lib/firefly-iii-data-importer";
98       description = ''
99         The place where firefly-iii data importer stores its state.
100       '';
101     };
103     package = lib.mkOption {
104       type = lib.types.package;
105       default = pkgs.firefly-iii-data-importer;
106       defaultText = lib.literalExpression "pkgs.firefly-iii-data-importer";
107       description = ''
108         The firefly-iii-data-importer package served by php-fpm and the webserver of choice.
109         This option can be used to point the webserver to the correct root. It
110         may also be used to set the package to a different version, say a
111         development version.
112       '';
113       apply =
114         firefly-iii-data-importer:
115         firefly-iii-data-importer.override (prev: {
116           dataDir = cfg.dataDir;
117         });
118     };
120     enableNginx = lib.mkOption {
121       type = lib.types.bool;
122       default = false;
123       description = ''
124         Whether to enable nginx or not. If enabled, an nginx virtual host will
125         be created for access to firefly-iii data importer. If not enabled, then you may use
126         `''${config.services.firefly-iii-data-importer.package}` as your document root in
127         whichever webserver you wish to setup.
128       '';
129     };
131     virtualHost = lib.mkOption {
132       type = lib.types.str;
133       default = "localhost";
134       description = ''
135         The hostname at which you wish firefly-iii-data-importer to be served. If you have
136         enabled nginx using `services.firefly-iii-data-importer.enableNginx` then this will
137         be used.
138       '';
139     };
141     poolConfig = lib.mkOption {
142       type = lib.types.attrsOf (
143         lib.types.oneOf [
144           lib.types.str
145           lib.types.int
146           lib.types.bool
147         ]
148       );
149       default = { };
150       defaultText = lib.literalExpression ''
151         {
152           "pm" = "dynamic";
153           "pm.max_children" = 32;
154           "pm.start_servers" = 2;
155           "pm.min_spare_servers" = 2;
156           "pm.max_spare_servers" = 4;
157           "pm.max_requests" = 500;
158         }
159       '';
160       description = ''
161         Options for the Firefly III Data Importer PHP pool. See the documentation on <literal>php-fpm.conf</literal>
162         for details on configuration directives.
163       '';
164     };
166     settings = lib.mkOption {
167       default = { };
168       description = ''
169         Options for firefly-iii data importer configuration. Refer to
170         <https://github.com/firefly-iii/data-importer/blob/main/.env.example> for
171         details on supported values. All <option>_FILE values supported by
172         upstream are supported here.
174         APP_URL will be the same as `services.firefly-iii-data-importer.virtualHost` if the
175         former is unset in `services.firefly-iii-data-importer.settings`.
176       '';
177       example = lib.literalExpression ''
178         {
179           APP_ENV = "local";
180           LOG_CHANNEL = "syslog";
181           FIREFLY_III_ACCESS_TOKEN= = "/var/secrets/firefly-iii-access-token.txt";
182         }
183       '';
184       type = lib.types.submodule {
185         freeformType = lib.types.attrsOf (
186           lib.types.oneOf [
187             lib.types.str
188             lib.types.int
189             lib.types.bool
190           ]
191         );
192       };
193     };
194   };
196   config = lib.mkIf cfg.enable {
197     services.phpfpm.pools.firefly-iii-data-importer = {
198       inherit user group;
199       phpPackage = cfg.package.phpPackage;
200       phpOptions = ''
201         log_errors = on
202       '';
203       settings = {
204         "listen.mode" = "0660";
205         "listen.owner" = user;
206         "listen.group" = group;
207         "pm" = lib.mkDefault "dynamic";
208         "pm.max_children" = lib.mkDefault 32;
209         "pm.start_servers" = lib.mkDefault 2;
210         "pm.min_spare_servers" = lib.mkDefault 2;
211         "pm.max_spare_servers" = lib.mkDefault 4;
212         "pm.max_requests" = lib.mkDefault 500;
213       } // cfg.poolConfig;
214     };
216     systemd.services.firefly-iii-data-importer-setup = {
217       requiredBy = [ "phpfpm-firefly-iii-data-importer.service" ];
218       before = [ "phpfpm-firefly-iii-data-importer.service" ];
219       serviceConfig = {
220         ExecStart = data-importer-maintenance;
221         RemainAfterExit = true;
222       } // commonServiceConfig;
223       unitConfig.JoinsNamespaceOf = "phpfpm-firefly-iii-data-importer.service";
224       restartTriggers = [ cfg.package ];
225     };
227     services.nginx = lib.mkIf cfg.enableNginx {
228       enable = true;
229       recommendedTlsSettings = lib.mkDefault true;
230       recommendedOptimisation = lib.mkDefault true;
231       recommendedGzipSettings = lib.mkDefault true;
232       virtualHosts.${cfg.virtualHost} = {
233         root = "${cfg.package}/public";
234         locations = {
235           "/" = {
236             tryFiles = "$uri $uri/ /index.php?$query_string";
237             index = "index.php";
238             extraConfig = ''
239               sendfile off;
240             '';
241           };
242           "~ \.php$" = {
243             extraConfig = ''
244               include ${config.services.nginx.package}/conf/fastcgi_params ;
245               fastcgi_param SCRIPT_FILENAME $request_filename;
246               fastcgi_param modHeadersAvailable true;
247               fastcgi_pass unix:${config.services.phpfpm.pools.firefly-iii-data-importer.socket};
248             '';
249           };
250         };
251       };
252     };
254     systemd.tmpfiles.settings."10-firefly-iii-data-importer" =
255       lib.attrsets.genAttrs
256         [
257           "${cfg.dataDir}/storage"
258           "${cfg.dataDir}/storage/app"
259           "${cfg.dataDir}/storage/app/public"
260           "${cfg.dataDir}/storage/configurations"
261           "${cfg.dataDir}/storage/conversion-routines"
262           "${cfg.dataDir}/storage/debugbar"
263           "${cfg.dataDir}/storage/framework"
264           "${cfg.dataDir}/storage/framework/cache"
265           "${cfg.dataDir}/storage/framework/sessions"
266           "${cfg.dataDir}/storage/framework/testing"
267           "${cfg.dataDir}/storage/framework/views"
268           "${cfg.dataDir}/storage/jobs"
269           "${cfg.dataDir}/storage/logs"
270           "${cfg.dataDir}/storage/submission-routines"
271           "${cfg.dataDir}/storage/uploads"
272           "${cfg.dataDir}/cache"
273         ]
274         (n: {
275           d = {
276             group = group;
277             mode = "0710";
278             user = user;
279           };
280         })
281       // {
282         "${cfg.dataDir}".d = {
283           group = group;
284           mode = "0700";
285           user = user;
286         };
287       };
289     users = {
290       users = lib.mkIf (user == defaultUser) {
291         ${defaultUser} = {
292           description = "Firefly-iii Data Importer service user";
293           inherit group;
294           isSystemUser = true;
295           home = cfg.dataDir;
296         };
297       };
298       groups = lib.mkIf (group == defaultGroup) { ${defaultGroup} = { }; };
299     };
300   };