at 22.05-pre 9.5 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 cfg = config.services.phpfpm; 7 8 runtimeDir = "/run/phpfpm"; 9 10 toStr = value: 11 if true == value then "yes" 12 else if false == value then "no" 13 else toString value; 14 15 fpmCfgFile = pool: poolOpts: pkgs.writeText "phpfpm-${pool}.conf" '' 16 [global] 17 ${concatStringsSep "\n" (mapAttrsToList (n: v: "${n} = ${toStr v}") cfg.settings)} 18 ${optionalString (cfg.extraConfig != null) cfg.extraConfig} 19 20 [${pool}] 21 ${concatStringsSep "\n" (mapAttrsToList (n: v: "${n} = ${toStr v}") poolOpts.settings)} 22 ${concatStringsSep "\n" (mapAttrsToList (n: v: "env[${n}] = ${toStr v}") poolOpts.phpEnv)} 23 ${optionalString (poolOpts.extraConfig != null) poolOpts.extraConfig} 24 ''; 25 26 phpIni = poolOpts: pkgs.runCommand "php.ini" { 27 inherit (poolOpts) phpPackage phpOptions; 28 preferLocalBuild = true; 29 passAsFile = [ "phpOptions" ]; 30 } '' 31 cat ${poolOpts.phpPackage}/etc/php.ini $phpOptionsPath > $out 32 ''; 33 34 poolOpts = { name, ... }: 35 let 36 poolOpts = cfg.pools.${name}; 37 in 38 { 39 options = { 40 socket = mkOption { 41 type = types.str; 42 readOnly = true; 43 description = '' 44 Path to the unix socket file on which to accept FastCGI requests. 45 <note><para>This option is read-only and managed by NixOS.</para></note> 46 ''; 47 example = "${runtimeDir}/<name>.sock"; 48 }; 49 50 listen = mkOption { 51 type = types.str; 52 default = ""; 53 example = "/path/to/unix/socket"; 54 description = '' 55 The address on which to accept FastCGI requests. 56 ''; 57 }; 58 59 phpPackage = mkOption { 60 type = types.package; 61 default = cfg.phpPackage; 62 defaultText = literalExpression "config.services.phpfpm.phpPackage"; 63 description = '' 64 The PHP package to use for running this PHP-FPM pool. 65 ''; 66 }; 67 68 phpOptions = mkOption { 69 type = types.lines; 70 description = '' 71 "Options appended to the PHP configuration file <filename>php.ini</filename> used for this PHP-FPM pool." 72 ''; 73 }; 74 75 phpEnv = lib.mkOption { 76 type = with types; attrsOf str; 77 default = {}; 78 description = '' 79 Environment variables used for this PHP-FPM pool. 80 ''; 81 example = literalExpression '' 82 { 83 HOSTNAME = "$HOSTNAME"; 84 TMP = "/tmp"; 85 TMPDIR = "/tmp"; 86 TEMP = "/tmp"; 87 } 88 ''; 89 }; 90 91 user = mkOption { 92 type = types.str; 93 description = "User account under which this pool runs."; 94 }; 95 96 group = mkOption { 97 type = types.str; 98 description = "Group account under which this pool runs."; 99 }; 100 101 settings = mkOption { 102 type = with types; attrsOf (oneOf [ str int bool ]); 103 default = {}; 104 description = '' 105 PHP-FPM pool directives. Refer to the "List of pool directives" section of 106 <link xlink:href="https://www.php.net/manual/en/install.fpm.configuration.php"/> 107 for details. Note that settings names must be enclosed in quotes (e.g. 108 <literal>"pm.max_children"</literal> instead of <literal>pm.max_children</literal>). 109 ''; 110 example = literalExpression '' 111 { 112 "pm" = "dynamic"; 113 "pm.max_children" = 75; 114 "pm.start_servers" = 10; 115 "pm.min_spare_servers" = 5; 116 "pm.max_spare_servers" = 20; 117 "pm.max_requests" = 500; 118 } 119 ''; 120 }; 121 122 extraConfig = mkOption { 123 type = with types; nullOr lines; 124 default = null; 125 description = '' 126 Extra lines that go into the pool configuration. 127 See the documentation on <literal>php-fpm.conf</literal> for 128 details on configuration directives. 129 ''; 130 }; 131 }; 132 133 config = { 134 socket = if poolOpts.listen == "" then "${runtimeDir}/${name}.sock" else poolOpts.listen; 135 group = mkDefault poolOpts.user; 136 phpOptions = mkBefore cfg.phpOptions; 137 138 settings = mapAttrs (name: mkDefault){ 139 listen = poolOpts.socket; 140 user = poolOpts.user; 141 group = poolOpts.group; 142 }; 143 }; 144 }; 145 146in { 147 imports = [ 148 (mkRemovedOptionModule [ "services" "phpfpm" "poolConfigs" ] "Use services.phpfpm.pools instead.") 149 (mkRemovedOptionModule [ "services" "phpfpm" "phpIni" ] "") 150 ]; 151 152 options = { 153 services.phpfpm = { 154 settings = mkOption { 155 type = with types; attrsOf (oneOf [ str int bool ]); 156 default = {}; 157 description = '' 158 PHP-FPM global directives. Refer to the "List of global php-fpm.conf directives" section of 159 <link xlink:href="https://www.php.net/manual/en/install.fpm.configuration.php"/> 160 for details. Note that settings names must be enclosed in quotes (e.g. 161 <literal>"pm.max_children"</literal> instead of <literal>pm.max_children</literal>). 162 You need not specify the options <literal>error_log</literal> or 163 <literal>daemonize</literal> here, since they are generated by NixOS. 164 ''; 165 }; 166 167 extraConfig = mkOption { 168 type = with types; nullOr lines; 169 default = null; 170 description = '' 171 Extra configuration that should be put in the global section of 172 the PHP-FPM configuration file. Do not specify the options 173 <literal>error_log</literal> or 174 <literal>daemonize</literal> here, since they are generated by 175 NixOS. 176 ''; 177 }; 178 179 phpPackage = mkOption { 180 type = types.package; 181 default = pkgs.php; 182 defaultText = literalExpression "pkgs.php"; 183 description = '' 184 The PHP package to use for running the PHP-FPM service. 185 ''; 186 }; 187 188 phpOptions = mkOption { 189 type = types.lines; 190 default = ""; 191 example = 192 '' 193 date.timezone = "CET" 194 ''; 195 description = '' 196 Options appended to the PHP configuration file <filename>php.ini</filename>. 197 ''; 198 }; 199 200 pools = mkOption { 201 type = types.attrsOf (types.submodule poolOpts); 202 default = {}; 203 example = literalExpression '' 204 { 205 mypool = { 206 user = "php"; 207 group = "php"; 208 phpPackage = pkgs.php; 209 settings = { 210 "pm" = "dynamic"; 211 "pm.max_children" = 75; 212 "pm.start_servers" = 10; 213 "pm.min_spare_servers" = 5; 214 "pm.max_spare_servers" = 20; 215 "pm.max_requests" = 500; 216 }; 217 } 218 }''; 219 description = '' 220 PHP-FPM pools. If no pools are defined, the PHP-FPM 221 service is disabled. 222 ''; 223 }; 224 }; 225 }; 226 227 config = mkIf (cfg.pools != {}) { 228 229 warnings = 230 mapAttrsToList (pool: poolOpts: '' 231 Using config.services.phpfpm.pools.${pool}.listen is deprecated and will become unsupported in a future release. Please reference the read-only option config.services.phpfpm.pools.${pool}.socket to access the path of your socket. 232 '') (filterAttrs (pool: poolOpts: poolOpts.listen != "") cfg.pools) ++ 233 mapAttrsToList (pool: poolOpts: '' 234 Using config.services.phpfpm.pools.${pool}.extraConfig is deprecated and will become unsupported in a future release. Please migrate your configuration to config.services.phpfpm.pools.${pool}.settings. 235 '') (filterAttrs (pool: poolOpts: poolOpts.extraConfig != null) cfg.pools) ++ 236 optional (cfg.extraConfig != null) '' 237 Using config.services.phpfpm.extraConfig is deprecated and will become unsupported in a future release. Please migrate your configuration to config.services.phpfpm.settings. 238 '' 239 ; 240 241 services.phpfpm.settings = { 242 error_log = "syslog"; 243 daemonize = false; 244 }; 245 246 systemd.slices.phpfpm = { 247 description = "PHP FastCGI Process manager pools slice"; 248 }; 249 250 systemd.targets.phpfpm = { 251 description = "PHP FastCGI Process manager pools target"; 252 wantedBy = [ "multi-user.target" ]; 253 }; 254 255 systemd.services = mapAttrs' (pool: poolOpts: 256 nameValuePair "phpfpm-${pool}" { 257 description = "PHP FastCGI Process Manager service for pool ${pool}"; 258 after = [ "network.target" ]; 259 wantedBy = [ "phpfpm.target" ]; 260 partOf = [ "phpfpm.target" ]; 261 serviceConfig = let 262 cfgFile = fpmCfgFile pool poolOpts; 263 iniFile = phpIni poolOpts; 264 in { 265 Slice = "phpfpm.slice"; 266 PrivateDevices = true; 267 PrivateTmp = true; 268 ProtectSystem = "full"; 269 ProtectHome = true; 270 # XXX: We need AF_NETLINK to make the sendmail SUID binary from postfix work 271 RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6 AF_NETLINK"; 272 Type = "notify"; 273 ExecStart = "${poolOpts.phpPackage}/bin/php-fpm -y ${cfgFile} -c ${iniFile}"; 274 ExecReload = "${pkgs.coreutils}/bin/kill -USR2 $MAINPID"; 275 RuntimeDirectory = "phpfpm"; 276 RuntimeDirectoryPreserve = true; # Relevant when multiple processes are running 277 Restart = "always"; 278 }; 279 } 280 ) cfg.pools; 281 }; 282}