at 25.11-pre 9.5 kB view raw
1{ 2 pkgs, 3 config, 4 lib, 5 ... 6}: 7 8let 9 cfg = config.services.firefly-iii-data-importer; 10 11 user = cfg.user; 12 group = cfg.group; 13 14 defaultUser = "firefly-iii-data-importer"; 15 defaultGroup = "firefly-iii-data-importer"; 16 17 artisan = "${cfg.package}/artisan"; 18 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; 23 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 rm ${cfg.dataDir}/cache/*.php 33 ${artisan} config:cache 34 ''; 35 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 }; 72 73in 74{ 75 76 options.services.firefly-iii-data-importer = { 77 enable = lib.mkEnableOption "Firefly III Data Importer"; 78 79 user = lib.mkOption { 80 type = lib.types.str; 81 default = defaultUser; 82 description = "User account under which firefly-iii-data-importer runs."; 83 }; 84 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 }; 94 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 }; 102 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 }; 119 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 }; 130 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 }; 140 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 }; 165 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. 173 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 }; 195 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 }; 215 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 }; 226 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 }; 253 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 }; 288 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 }; 301}