at 25.11-pre 6.5 kB view raw
1{ 2 lib, 3 pkgs, 4 config, 5 ... 6}: 7 8let 9 cfg = config.services.prefect; 10 inherit (lib.types) 11 bool 12 str 13 enum 14 path 15 attrsOf 16 nullOr 17 submodule 18 port 19 ; 20 21in 22{ 23 options.services.prefect = { 24 enable = lib.mkOption { 25 type = bool; 26 default = false; 27 description = "enable prefect server and worker services"; 28 }; 29 30 package = lib.mkPackageOption pkgs "prefect" { }; 31 32 host = lib.mkOption { 33 type = str; 34 default = "127.0.0.1"; 35 example = "0.0.0.0"; 36 description = "Prefect server host"; 37 }; 38 39 port = lib.mkOption { 40 type = port; 41 default = 4200; 42 description = "Prefect server port"; 43 }; 44 45 dataDir = lib.mkOption { 46 type = path; 47 default = "/var/lib/prefect-server"; 48 description = '' 49 Specify the directory for Prefect. 50 ''; 51 }; 52 53 database = lib.mkOption { 54 type = enum [ 55 "sqlite" 56 "postgres" 57 ]; 58 default = "sqlite"; 59 description = "which database to use for prefect server: sqlite or postgres"; 60 }; 61 62 databaseHost = lib.mkOption { 63 type = str; 64 default = "localhost"; 65 description = "database host for postgres only"; 66 }; 67 68 databasePort = lib.mkOption { 69 type = str; 70 default = "5432"; 71 description = "database port for postgres only"; 72 }; 73 74 databaseName = lib.mkOption { 75 type = str; 76 default = "prefect"; 77 description = "database name for postgres only"; 78 }; 79 80 databaseUser = lib.mkOption { 81 type = str; 82 default = "postgres"; 83 description = "database user for postgres only"; 84 }; 85 86 databasePasswordFile = lib.mkOption { 87 type = nullOr str; 88 default = null; 89 description = '' 90 path to a file containing e.g.: 91 DBPASSWORD=supersecret 92 93 stored outside the nix store, read by systemd as EnvironmentFile. 94 ''; 95 }; 96 97 # now define workerPools as an attribute set of submodules, 98 # each key is the pool name, and the submodule has an installPolicy 99 workerPools = lib.mkOption { 100 type = attrsOf (submodule { 101 options = { 102 installPolicy = lib.mkOption { 103 type = enum [ 104 "always" 105 "if-not-present" 106 "never" 107 "prompt" 108 ]; 109 default = "always"; 110 description = "install policy for the worker (always, if-not-present, never, prompt)"; 111 }; 112 }; 113 }); 114 default = { }; 115 description = '' 116 define a set of worker pools with submodule config. example: 117 workerPools.my-pool = { 118 installPolicy = "never"; 119 }; 120 ''; 121 }; 122 123 baseUrl = lib.mkOption { 124 type = nullOr str; 125 default = null; 126 description = "external url when served by a reverse proxy, e.g. https://example.com/prefect"; 127 }; 128 }; 129 130 config = lib.mkIf cfg.enable { 131 # define systemd.services as the server plus any worker definitions 132 systemd.services = 133 { 134 "prefect-server" = { 135 description = "prefect server"; 136 wantedBy = [ "multi-user.target" ]; 137 after = [ "network.target" ]; 138 139 serviceConfig = { 140 DynamicUser = true; 141 StateDirectory = "prefect-server"; 142 # TODO all my efforts to setup the database url 143 # have failed with some unable to open file 144 Environment = [ 145 "PREFECT_HOME=%S/prefect-server" 146 "PREFECT_UI_STATIC_DIRECTORY=%S/prefect-server" 147 "PREFECT_SERVER_ANALYTICS_ENABLED=off" 148 "PREFECT_UI_API_URL=${cfg.baseUrl}/api" 149 "PREFECT_UI_URL=${cfg.baseUrl}" 150 ]; 151 EnvironmentFile = 152 if cfg.database == "postgres" && cfg.databasePasswordFile != null then 153 [ cfg.databasePasswordFile ] 154 else 155 [ ]; 156 157 # ReadWritePaths = [ cfg.dataDir ]; 158 ProtectSystem = "strict"; 159 ProtectHome = true; 160 PrivateTmp = true; 161 NoNewPrivileges = true; 162 MemoryDenyWriteExecute = true; 163 LockPersonality = true; 164 CapabilityBoundingSet = [ ]; 165 AmbientCapabilities = [ ]; 166 RestrictSUIDSGID = true; 167 RestrictAddressFamilies = [ 168 "AF_INET" 169 "AF_INET6" 170 "AF_UNIX" 171 ]; 172 ProtectKernelTunables = true; 173 ProtectKernelModules = true; 174 ProtectKernelLogs = true; 175 ProtectControlGroups = true; 176 MemoryAccounting = true; 177 CPUAccounting = true; 178 179 ExecStart = "${pkgs.prefect}/bin/prefect server start --host ${cfg.host} --port ${toString cfg.port}"; 180 Restart = "always"; 181 WorkingDirectory = cfg.dataDir; 182 }; 183 }; 184 } 185 // lib.concatMapAttrs (poolName: poolCfg: { 186 # return a partial attr set with one key: "prefect-worker-..." 187 "prefect-worker-${poolName}" = { 188 description = "prefect worker for pool '${poolName}'"; 189 wantedBy = [ "multi-user.target" ]; 190 after = [ "network.target" ]; 191 192 environment.systemPackages = cfg.package; 193 194 serviceConfig = { 195 DynamicUser = true; 196 StateDirectory = "prefect-worker-${poolName}"; 197 Environment = [ 198 "PREFECT_HOME=%S/prefect-worker-${poolName}" 199 "PREFECT_API_URL=${cfg.baseUrl}/api" 200 ]; 201 ProtectSystem = "strict"; 202 ProtectHome = true; 203 PrivateTmp = true; 204 NoNewPrivileges = true; 205 MemoryDenyWriteExecute = true; 206 LockPersonality = true; 207 CapabilityBoundingSet = [ ]; 208 AmbientCapabilities = [ ]; 209 RestrictSUIDSGID = true; 210 RestrictAddressFamilies = [ 211 "AF_INET" 212 "AF_INET6" 213 "AF_UNIX" 214 ]; 215 ProtectKernelTunables = true; 216 ProtectKernelModules = true; 217 ProtectKernelLogs = true; 218 ProtectControlGroups = true; 219 MemoryAccounting = true; 220 CPUAccounting = true; 221 ExecStart = '' 222 ${pkgs.prefect}/bin/prefect worker start \ 223 --pool ${poolName} \ 224 --type process \ 225 --install-policy ${poolCfg.installPolicy} 226 ''; 227 Restart = "always"; 228 }; 229 }; 230 }) cfg.workerPools; 231 }; 232}