{ pkgs, config, lib, ... }: let inherit (lib) optionalString mkDefault mkIf mkOption mkEnableOption literalExpression; inherit (lib.types) nullOr attrsOf oneOf str int bool path package enum submodule; inherit (lib.strings) concatLines removePrefix toShellVars removeSuffix hasSuffix; inherit (lib.attrsets) mapAttrsToList attrValues genAttrs filterAttrs mapAttrs' nameValuePair; inherit (builtins) isInt isString toString typeOf; cfg = config.services.firefly-iii; user = cfg.user; group = cfg.group; defaultUser = "firefly-iii"; defaultGroup = "firefly-iii"; artisan = "${cfg.package}/artisan"; env-file-values = mapAttrs' (n: v: nameValuePair (removeSuffix "_FILE" n) v) (filterAttrs (n: v: hasSuffix "_FILE" n) cfg.settings); env-nonfile-values = filterAttrs (n: v: ! hasSuffix "_FILE" n) cfg.settings; fileenv-func = '' set -a ${toShellVars env-nonfile-values} ${concatLines (mapAttrsToList (n: v: "${n}=\"$(< ${v})\"") env-file-values)} set +a ''; firefly-iii-maintenance = pkgs.writeShellScript "firefly-iii-maintenance.sh" '' ${fileenv-func} ${optionalString (cfg.settings.DB_CONNECTION == "sqlite") "touch ${cfg.dataDir}/storage/database/database.sqlite"} ${artisan} package:discover ${artisan} firefly-iii:upgrade-database ${artisan} firefly-iii:laravel-passport-keys ${artisan} cache:clear ${artisan} view:cache ${artisan} route:cache ${artisan} config:cache ''; commonServiceConfig = { Type = "oneshot"; User = user; Group = group; StateDirectory = "${removePrefix "/var/lib/" cfg.dataDir}"; WorkingDirectory = cfg.package; PrivateTmp = true; PrivateDevices = true; CapabilityBoundingSet = ""; AmbientCapabilities = ""; ProtectSystem = "strict"; ProtectKernelTunables = true; ProtectKernelModules = true; ProtectControlGroups = true; ProtectClock = true; ProtectHostname = true; ProtectHome = "tmpfs"; ProtectKernelLogs = true; ProtectProc = "invisible"; ProcSubset = "pid"; PrivateNetwork = false; RestrictAddressFamilies = "AF_INET AF_INET6 AF_UNIX"; SystemCallArchitectures = "native"; SystemCallFilter = [ "@system-service @resources" "~@obsolete @privileged" ]; RestrictSUIDSGID = true; RemoveIPC = true; NoNewPrivileges = true; RestrictRealtime = true; RestrictNamespaces = true; LockPersonality = true; PrivateUsers = true; }; in { options.services.firefly-iii = { enable = mkEnableOption "Firefly III: A free and open source personal finance manager"; user = mkOption { type = str; default = defaultUser; description = "User account under which firefly-iii runs."; }; group = mkOption { type = str; default = if cfg.enableNginx then "nginx" else defaultGroup; defaultText = "If `services.firefly-iii.enableNginx` is true then `nginx` else ${defaultGroup}"; description = '' Group under which firefly-iii runs. It is best to set this to the group of whatever webserver is being used as the frontend. ''; }; dataDir = mkOption { type = path; default = "/var/lib/firefly-iii"; description = '' The place where firefly-iii stores its state. ''; }; package = mkOption { type = package; default = pkgs.firefly-iii; defaultText = literalExpression "pkgs.firefly-iii"; description = '' The firefly-iii package served by php-fpm and the webserver of choice. This option can be used to point the webserver to the correct root. It may also be used to set the package to a different version, say a development version. ''; apply = firefly-iii : firefly-iii.override (prev: { dataDir = cfg.dataDir; }); }; enableNginx = mkOption { type = bool; default = false; description = '' Whether to enable nginx or not. If enabled, an nginx virtual host will be created for access to firefly-iii. If not enabled, then you may use `''${config.services.firefly-iii.package}` as your document root in whichever webserver you wish to setup. ''; }; virtualHost = mkOption { type = str; default = "localhost"; description = '' The hostname at which you wish firefly-iii to be served. If you have enabled nginx using `services.firefly-iii.enableNginx` then this will be used. ''; }; poolConfig = mkOption { type = attrsOf (oneOf [ str int bool ]); default = { "pm" = "dynamic"; "pm.max_children" = 32; "pm.start_servers" = 2; "pm.min_spare_servers" = 2; "pm.max_spare_servers" = 4; "pm.max_requests" = 500; }; description = '' Options for the Firefly III PHP pool. See the documentation on php-fpm.conf for details on configuration directives. ''; }; settings = mkOption { default = {}; description = '' Options for firefly-iii configuration. Refer to for details on supported values. All