at master 7.1 kB view raw
1{ 2 pkgs, 3 config, 4 lib, 5 ... 6}: 7let 8 cfg = config.services.part-db; 9 pkg = cfg.package; 10 11 inherit (lib) 12 mkEnableOption 13 mkPackageOption 14 mkOption 15 types 16 mkIf 17 ; 18in 19{ 20 meta.maintainers = with lib.maintainers; [ felbinger ]; 21 22 options.services.part-db = { 23 enable = mkEnableOption "PartDB"; 24 25 package = mkPackageOption pkgs "part-db" { }; 26 27 phpPackage = mkPackageOption pkgs "php" { } // { 28 apply = 29 pkg: 30 pkg.buildEnv { 31 extraConfig = '' 32 memory_limit = 256M; 33 ''; 34 }; 35 }; 36 37 enableNginx = mkOption { 38 type = types.bool; 39 default = true; 40 description = '' 41 Whether to enable nginx or not. If enabled, an nginx virtual host will 42 be created for access to part-db. If not enabled, then you may use 43 `''${config.services.part-db.package}/public` as your document root in 44 whichever webserver you wish to setup. 45 ''; 46 }; 47 48 enablePostgresql = mkOption { 49 type = types.bool; 50 default = true; 51 description = '' 52 Whether to configure the postgresql database for part-db. If enabled, 53 a database and user will be created for part-db. 54 ''; 55 }; 56 57 virtualHost = mkOption { 58 type = types.str; 59 default = "localhost"; 60 description = '' 61 The virtualHost at which you wish part-db to be served. 62 ''; 63 }; 64 65 poolConfig = lib.mkOption { 66 type = lib.types.attrsOf ( 67 lib.types.oneOf [ 68 lib.types.str 69 lib.types.int 70 lib.types.bool 71 ] 72 ); 73 default = { }; 74 defaultText = '' 75 { 76 "pm" = "dynamic"; 77 "pm.max_children" = 32; 78 "pm.start_servers" = 2; 79 "pm.min_spare_servers" = 2; 80 "pm.max_spare_servers" = 4; 81 "pm.max_requests" = 500; 82 } 83 ''; 84 description = '' 85 Options for the PartDB PHP pool. See the documentation on <literal>php-fpm.conf</literal> 86 for details on configuration directives. 87 ''; 88 }; 89 90 settings = lib.mkOption { 91 default = { }; 92 description = '' 93 Options for part-db configuration. Refer to 94 <https://github.com/Part-DB/Part-DB-server/blob/master/.env> for 95 details on supported values. All <option>_FILE values supported by 96 upstream are supported here. 97 ''; 98 example = lib.literalExpression '' 99 { 100 DATABASE_URL = "postgresql://db_user@localhost/db_name?serverVersion=16.6&charset=utf8&host=/var/run/postgresql"; 101 } 102 ''; 103 type = lib.types.submodule { 104 freeformType = lib.types.attrsOf ( 105 with lib.types; 106 oneOf [ 107 str 108 int 109 bool 110 ] 111 ); 112 options = { 113 DATABASE_URL = lib.mkOption { 114 type = lib.types.str; 115 default = "postgresql://part-db@localhost/part-db?serverVersion=${config.services.postgresql.package.version}&host=/run/postgresql"; 116 defaultText = "postgresql://part-db@localhost/part-db?serverVersion=\${config.services.postgresql.package.version}&host=/run/postgresql"; 117 description = '' 118 The postgresql database server to connect to. 119 Defauls to local postgresql unix socket 120 ''; 121 }; 122 }; 123 }; 124 }; 125 }; 126 127 config = mkIf cfg.enable { 128 users.groups.part-db = { }; 129 users.users.part-db = { 130 group = "part-db"; 131 isSystemUser = true; 132 }; 133 134 services = { 135 phpfpm.pools.part-db = { 136 user = "part-db"; 137 group = "part-db"; 138 phpPackage = cfg.phpPackage; 139 phpOptions = '' 140 log_errors = on 141 ''; 142 settings = { 143 "listen.mode" = lib.mkDefault "0660"; 144 "listen.owner" = lib.mkDefault "part-db"; 145 "listen.group" = lib.mkDefault "part-db"; 146 "pm" = lib.mkDefault "dynamic"; 147 "pm.max_children" = lib.mkDefault 32; 148 "pm.start_servers" = lib.mkDefault 2; 149 "pm.min_spare_servers" = lib.mkDefault 2; 150 "pm.max_spare_servers" = lib.mkDefault 4; 151 "pm.max_requests" = lib.mkDefault 500; 152 } 153 // cfg.poolConfig; 154 }; 155 156 postgresql = mkIf cfg.enablePostgresql { 157 enable = true; 158 ensureUsers = [ 159 { 160 name = "part-db"; 161 ensureDBOwnership = true; 162 } 163 ]; 164 ensureDatabases = [ "part-db" ]; 165 }; 166 167 nginx = mkIf cfg.enableNginx { 168 enable = true; 169 recommendedTlsSettings = lib.mkDefault true; 170 recommendedOptimisation = lib.mkDefault true; 171 recommendedGzipSettings = lib.mkDefault true; 172 virtualHosts.${cfg.virtualHost} = { 173 root = "${pkg}/public"; 174 locations = { 175 "/" = { 176 tryFiles = "$uri $uri/ /index.php"; 177 index = "index.php"; 178 extraConfig = '' 179 sendfile off; 180 ''; 181 }; 182 "~ \.php$" = { 183 extraConfig = '' 184 include ${config.services.nginx.package}/conf/fastcgi_params ; 185 fastcgi_param SCRIPT_FILENAME $request_filename; 186 fastcgi_param modHeadersAvailable true; #Avoid sending the security headers twice 187 fastcgi_pass unix:${config.services.phpfpm.pools.part-db.socket}; 188 ''; 189 }; 190 }; 191 }; 192 }; 193 }; 194 195 systemd = { 196 services = { 197 part-db-migrate = { 198 before = [ "phpfpm-part-db.service" ]; 199 after = [ "postgresql.target" ]; 200 requires = [ "postgresql.target" ]; 201 wantedBy = [ "multi-user.target" ]; 202 serviceConfig = { 203 Type = "oneshot"; 204 RemainAfterExit = true; 205 User = "part-db"; 206 }; 207 restartTriggers = [ 208 cfg.package 209 ]; 210 script = '' 211 set -euo pipefail 212 ${lib.getExe cfg.phpPackage} ${lib.getExe' cfg.package "console"} doctrine:migrations:migrate --no-interaction 213 ''; 214 }; 215 216 phpfpm-part-db = { 217 after = [ "part-db-migrate.service" ]; 218 requires = [ 219 "part-db-migrate.service" 220 "postgresql.target" 221 ]; 222 # ensure nginx can access the php-fpm socket 223 postStart = '' 224 ${lib.getExe' pkgs.acl "setfacl"} -m 'u:${config.services.nginx.user}:rw' ${config.services.phpfpm.pools.part-db.socket} 225 ''; 226 }; 227 }; 228 229 tmpfiles.settings."part-db" = { 230 "/var/cache/part-db/".d = { 231 mode = "0750"; 232 user = "part-db"; 233 group = "part-db"; 234 }; 235 "/var/lib/part-db/env.local"."L+" = { 236 argument = "${pkgs.writeText "part-db-env" ( 237 lib.concatStringsSep "\n" (lib.mapAttrsToList (key: value: "${key}=\"${value}\"") cfg.settings) 238 )}"; 239 }; 240 "/var/log/part-db/".d = { 241 mode = "0750"; 242 user = "part-db"; 243 group = "part-db"; 244 }; 245 }; 246 }; 247 }; 248}