at master 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 } 214 // cfg.poolConfig; 215 }; 216 217 systemd.services.firefly-iii-data-importer-setup = { 218 requiredBy = [ "phpfpm-firefly-iii-data-importer.service" ]; 219 before = [ "phpfpm-firefly-iii-data-importer.service" ]; 220 serviceConfig = { 221 ExecStart = data-importer-maintenance; 222 RemainAfterExit = true; 223 } 224 // commonServiceConfig; 225 unitConfig.JoinsNamespaceOf = "phpfpm-firefly-iii-data-importer.service"; 226 restartTriggers = [ cfg.package ]; 227 }; 228 229 services.nginx = lib.mkIf cfg.enableNginx { 230 enable = true; 231 recommendedTlsSettings = lib.mkDefault true; 232 recommendedOptimisation = lib.mkDefault true; 233 recommendedGzipSettings = lib.mkDefault true; 234 virtualHosts.${cfg.virtualHost} = { 235 root = "${cfg.package}/public"; 236 locations = { 237 "/" = { 238 tryFiles = "$uri $uri/ /index.php?$query_string"; 239 index = "index.php"; 240 extraConfig = '' 241 sendfile off; 242 ''; 243 }; 244 "~ \\.php$" = { 245 extraConfig = '' 246 include ${config.services.nginx.package}/conf/fastcgi_params ; 247 fastcgi_param SCRIPT_FILENAME $request_filename; 248 fastcgi_param modHeadersAvailable true; 249 fastcgi_pass unix:${config.services.phpfpm.pools.firefly-iii-data-importer.socket}; 250 ''; 251 }; 252 }; 253 }; 254 }; 255 256 systemd.tmpfiles.settings."10-firefly-iii-data-importer" = 257 lib.attrsets.genAttrs 258 [ 259 "${cfg.dataDir}/storage" 260 "${cfg.dataDir}/storage/app" 261 "${cfg.dataDir}/storage/app/public" 262 "${cfg.dataDir}/storage/configurations" 263 "${cfg.dataDir}/storage/conversion-routines" 264 "${cfg.dataDir}/storage/debugbar" 265 "${cfg.dataDir}/storage/framework" 266 "${cfg.dataDir}/storage/framework/cache" 267 "${cfg.dataDir}/storage/framework/sessions" 268 "${cfg.dataDir}/storage/framework/testing" 269 "${cfg.dataDir}/storage/framework/views" 270 "${cfg.dataDir}/storage/jobs" 271 "${cfg.dataDir}/storage/logs" 272 "${cfg.dataDir}/storage/submission-routines" 273 "${cfg.dataDir}/storage/uploads" 274 "${cfg.dataDir}/cache" 275 ] 276 (n: { 277 d = { 278 group = group; 279 mode = "0710"; 280 user = user; 281 }; 282 }) 283 // { 284 "${cfg.dataDir}".d = { 285 group = group; 286 mode = "0700"; 287 user = user; 288 }; 289 }; 290 291 users = { 292 users = lib.mkIf (user == defaultUser) { 293 ${defaultUser} = { 294 description = "Firefly-iii Data Importer service user"; 295 inherit group; 296 isSystemUser = true; 297 home = cfg.dataDir; 298 }; 299 }; 300 groups = lib.mkIf (group == defaultGroup) { ${defaultGroup} = { }; }; 301 }; 302 }; 303}