Merge pull request #65706 from aanderse/phpfpm

nixos/phpfpm: module cleanup
This commit is contained in:
Aaron Andersen 2019-08-24 08:25:24 -04:00 committed by GitHub
commit 825d023c8a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 375 additions and 349 deletions

View File

@ -178,6 +178,9 @@ with lib;
The starting time can be configured via <literal>services.postgresqlBackup.startAt</literal>. The starting time can be configured via <literal>services.postgresqlBackup.startAt</literal>.
'') '')
# phpfpm
(mkRemovedOptionModule [ "services" "phpfpm" "poolConfigs" ] "Use services.phpfpm.pools instead.")
# zabbixServer # zabbixServer
(mkRenamedOptionModule [ "services" "zabbixServer" "dbServer" ] [ "services" "zabbixServer" "database" "host" ]) (mkRenamedOptionModule [ "services" "zabbixServer" "dbServer" ] [ "services" "zabbixServer" "database" "host" ])

View File

@ -4,6 +4,7 @@ with lib;
let let
cfg = config.services.roundcube; cfg = config.services.roundcube;
fpm = config.services.phpfpm.pools.roundcube;
in in
{ {
options.services.roundcube = { options.services.roundcube = {
@ -105,7 +106,7 @@ in
extraConfig = '' extraConfig = ''
location ~* \.php$ { location ~* \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/run/phpfpm/roundcube; fastcgi_pass unix:${fpm.socket};
include ${pkgs.nginx}/conf/fastcgi_params; include ${pkgs.nginx}/conf/fastcgi_params;
include ${pkgs.nginx}/conf/fastcgi.conf; include ${pkgs.nginx}/conf/fastcgi.conf;
} }
@ -119,24 +120,27 @@ in
enable = true; enable = true;
}; };
services.phpfpm.poolConfigs.roundcube = '' services.phpfpm.pools.roundcube = {
listen = /run/phpfpm/roundcube user = "nginx";
listen.owner = nginx phpOptions = ''
listen.group = nginx error_log = 'stderr'
listen.mode = 0660 log_errors = on
user = nginx post_max_size = 25M
pm = dynamic upload_max_filesize = 25M
pm.max_children = 75 '';
pm.start_servers = 2 settings = mapAttrs (name: mkDefault) {
pm.min_spare_servers = 1 "listen.owner" = "nginx";
pm.max_spare_servers = 20 "listen.group" = "nginx";
pm.max_requests = 500 "listen.mode" = "0660";
php_admin_value[error_log] = 'stderr' "pm" = "dynamic";
php_admin_flag[log_errors] = on "pm.max_children" = 75;
php_admin_value[post_max_size] = 25M "pm.start_servers" = 2;
php_admin_value[upload_max_filesize] = 25M "pm.min_spare_servers" = 1;
catch_workers_output = yes "pm.max_spare_servers" = 20;
''; "pm.max_requests" = 500;
"catch_workers_output" = true;
};
};
systemd.services.phpfpm-roundcube.after = [ "roundcube-setup.service" ]; systemd.services.phpfpm-roundcube.after = [ "roundcube-setup.service" ];
systemd.services.roundcube-setup = let systemd.services.roundcube-setup = let

View File

@ -2,6 +2,7 @@
let let
cfg = config.services.zoneminder; cfg = config.services.zoneminder;
fpm = config.services.phpfpm.pools.zoneminder;
pkg = pkgs.zoneminder; pkg = pkgs.zoneminder;
dirName = pkg.dirName; dirName = pkg.dirName;
@ -19,8 +20,6 @@ let
useCustomDir = cfg.storageDir != null; useCustomDir = cfg.storageDir != null;
socket = "/run/phpfpm/${dirName}.sock";
zms = "/cgi-bin/zms"; zms = "/cgi-bin/zms";
dirs = dirList: [ dirName ] ++ map (e: "${dirName}/${e}") dirList; dirs = dirList: [ dirName ] ++ map (e: "${dirName}/${e}") dirList;
@ -274,7 +273,7 @@ in {
fastcgi_param SCRIPT_FILENAME $request_filename; fastcgi_param SCRIPT_FILENAME $request_filename;
fastcgi_param HTTP_PROXY ""; fastcgi_param HTTP_PROXY "";
fastcgi_pass unix:${socket}; fastcgi_pass unix:${fpm.socket};
} }
} }
''; '';
@ -284,30 +283,27 @@ in {
phpfpm = lib.mkIf useNginx { phpfpm = lib.mkIf useNginx {
pools.zoneminder = { pools.zoneminder = {
listen = socket; inherit user group;
phpOptions = '' phpOptions = ''
date.timezone = "${config.time.timeZone}" date.timezone = "${config.time.timeZone}"
${lib.concatStringsSep "\n" (map (e: ${lib.concatStringsSep "\n" (map (e:
"extension=${e.pkg}/lib/php/extensions/${e.name}.so") phpExtensions)} "extension=${e.pkg}/lib/php/extensions/${e.name}.so") phpExtensions)}
''; '';
extraConfig = '' settings = lib.mapAttrs (name: lib.mkDefault) {
user = ${user} "listen.owner" = user;
group = ${group} "listen.group" = group;
"listen.mode" = "0660";
listen.owner = ${user} "pm" = "dynamic";
listen.group = ${group} "pm.start_servers" = 1;
listen.mode = 0660 "pm.min_spare_servers" = 1;
"pm.max_spare_servers" = 2;
pm = dynamic "pm.max_requests" = 500;
pm.start_servers = 1 "pm.max_children" = 5;
pm.min_spare_servers = 1 "pm.status_path" = "/$pool-status";
pm.max_spare_servers = 2 "ping.path" = "/$pool-ping";
pm.max_requests = 500 };
pm.max_children = 5
pm.status_path = /$pool-status
ping.path = /$pool-ping
'';
}; };
}; };
}; };

View File

@ -1,7 +1,7 @@
{ config, lib, pkgs, ... }: with lib; let { config, lib, pkgs, ... }: with lib; let
cfg = config.services.icingaweb2; cfg = config.services.icingaweb2;
fpm = config.services.phpfpm.pools.${poolName};
poolName = "icingaweb2"; poolName = "icingaweb2";
phpfpmSocketName = "/var/run/phpfpm/${poolName}.sock";
defaultConfig = { defaultConfig = {
global = { global = {
@ -164,27 +164,26 @@ in {
}; };
config = mkIf cfg.enable { config = mkIf cfg.enable {
services.phpfpm.poolConfigs = mkIf (cfg.pool == "${poolName}") { services.phpfpm.pools = mkIf (cfg.pool == "${poolName}") {
"${poolName}" = '' "${poolName}" = {
listen = "${phpfpmSocketName}" user = "icingaweb2";
listen.owner = nginx phpOptions = ''
listen.group = nginx extension = ${pkgs.phpPackages.imagick}/lib/php/extensions/imagick.so
listen.mode = 0600 date.timezone = "${cfg.timezone}"
user = icingaweb2 '';
pm = dynamic settings = mapAttrs (name: mkDefault) {
pm.max_children = 75 "listen.owner" = "nginx";
pm.start_servers = 2 "listen.group" = "nginx";
pm.min_spare_servers = 2 "listen.mode" = "0600";
pm.max_spare_servers = 10 "pm" = "dynamic";
''; "pm.max_children" = 75;
"pm.start_servers" = 2;
"pm.min_spare_servers" = 2;
"pm.max_spare_servers" = 10;
};
};
}; };
services.phpfpm.phpOptions = mkIf (cfg.pool == "${poolName}")
''
extension = ${pkgs.phpPackages.imagick}/lib/php/extensions/imagick.so
date.timezone = "${cfg.timezone}"
'';
systemd.services."phpfpm-${poolName}".serviceConfig.ReadWritePaths = [ "/etc/icingaweb2" ]; systemd.services."phpfpm-${poolName}".serviceConfig.ReadWritePaths = [ "/etc/icingaweb2" ];
services.nginx = { services.nginx = {
@ -208,7 +207,7 @@ in {
include ${config.services.nginx.package}/conf/fastcgi.conf; include ${config.services.nginx.package}/conf/fastcgi.conf;
try_files $uri =404; try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:${phpfpmSocketName}; fastcgi_pass unix:${fpm.socket};
fastcgi_param SCRIPT_FILENAME ${pkgs.icingaweb2}/public/index.php; fastcgi_param SCRIPT_FILENAME ${pkgs.icingaweb2}/public/index.php;
''; '';
}; };

View File

@ -120,15 +120,15 @@ in
}; };
poolConfig = mkOption { poolConfig = mkOption {
type = types.lines; type = with types; attrsOf (oneOf [ str int bool ]);
default = '' default = {
pm = dynamic "pm" = "dynamic";
pm.max_children = 32 "pm.max_children" = 32;
pm.start_servers = 2 "pm.start_servers" = 2;
pm.min_spare_servers = 2 "pm.min_spare_servers" = 2;
pm.max_spare_servers = 4 "pm.max_spare_servers" = 4;
pm.max_requests = 500 "pm.max_requests" = 500;
''; };
description = '' description = ''
Options for the LimeSurvey PHP pool. See the documentation on <literal>php-fpm.conf</literal> Options for the LimeSurvey PHP pool. See the documentation on <literal>php-fpm.conf</literal>
for details on configuration directives. for details on configuration directives.
@ -203,17 +203,12 @@ in
}; };
services.phpfpm.pools.limesurvey = { services.phpfpm.pools.limesurvey = {
listen = "/run/phpfpm/limesurvey.sock"; inherit user group;
extraConfig = '' phpEnv.LIMESURVEY_CONFIG = "${limesurveyConfig}";
listen.owner = ${config.services.httpd.user}; settings = {
listen.group = ${config.services.httpd.group}; "listen.owner" = config.services.httpd.user;
user = ${user}; "listen.group" = config.services.httpd.group;
group = ${group}; } // cfg.poolConfig;
env[LIMESURVEY_CONFIG] = ${limesurveyConfig}
${cfg.poolConfig}
'';
}; };
services.httpd = { services.httpd = {
@ -241,7 +236,7 @@ in
<Directory "${pkg}/share/limesurvey"> <Directory "${pkg}/share/limesurvey">
<FilesMatch "\.php$"> <FilesMatch "\.php$">
<If "-f %{REQUEST_FILENAME}"> <If "-f %{REQUEST_FILENAME}">
SetHandler "proxy:unix:${fpm.listen}|fcgi://localhost/" SetHandler "proxy:unix:${fpm.socket}|fcgi://localhost/"
</If> </If>
</FilesMatch> </FilesMatch>

View File

@ -225,22 +225,24 @@ in {
serviceConfig.UMask = "0007"; serviceConfig.UMask = "0007";
}; };
services.phpfpm.poolConfigs = let services.phpfpm.pools = let
# workaround for when both are null and need to generate a string, # workaround for when both are null and need to generate a string,
# which is illegal, but as assertions apparently are being triggered *after* config generation, # which is illegal, but as assertions apparently are being triggered *after* config generation,
# we have to avoid already throwing errors at this previous stage. # we have to avoid already throwing errors at this previous stage.
socketOwner = if (cfg.nginx != null) then config.services.nginx.user socketOwner = if (cfg.nginx != null) then config.services.nginx.user
else if (cfg.webServerUser != null) then cfg.webServerUser else ""; else if (cfg.webServerUser != null) then cfg.webServerUser else "";
in { in {
${pool} = '' ${pool} = {
listen = "${phpSocket}" listen = phpSocket;
listen.owner = ${socketOwner} extraConfig = ''
listen.group = root listen.owner = ${socketOwner}
listen.mode = 0600 listen.group = root
user = ${user} listen.mode = 0600
env[PIWIK_USER_PATH] = ${dataDir} user = ${user}
${cfg.phpfpmProcessManagerConfig} env[PIWIK_USER_PATH] = ${dataDir}
''; ${cfg.phpfpmProcessManagerConfig}
'';
};
}; };

View File

@ -312,17 +312,17 @@ in
}; };
poolConfig = mkOption { poolConfig = mkOption {
type = types.lines; type = with types; attrsOf (oneOf [ str int bool ]);
default = '' default = {
pm = dynamic "pm" = "dynamic";
pm.max_children = 32 "pm.max_children" = 32;
pm.start_servers = 2 "pm.start_servers" = 2;
pm.min_spare_servers = 2 "pm.min_spare_servers" = 2;
pm.max_spare_servers = 4 "pm.max_spare_servers" = 4;
pm.max_requests = 500 "pm.max_requests" = 500;
''; };
description = '' description = ''
Options for MediaWiki's PHP pool. See the documentation on <literal>php-fpm.conf</literal> Options for the MediaWiki PHP pool. See the documentation on <literal>php-fpm.conf</literal>
for details on configuration directives. for details on configuration directives.
''; '';
}; };
@ -379,17 +379,12 @@ in
}; };
services.phpfpm.pools.mediawiki = { services.phpfpm.pools.mediawiki = {
listen = "/run/phpfpm/mediawiki.sock"; inherit user group;
extraConfig = '' phpEnv.MEDIAWIKI_CONFIG = "${mediawikiConfig}";
listen.owner = ${config.services.httpd.user} settings = {
listen.group = ${config.services.httpd.group} "listen.owner" = config.services.httpd.user;
user = ${user} "listen.group" = config.services.httpd.group;
group = ${group} } // cfg.poolConfig;
env[MEDIAWIKI_CONFIG] = ${mediawikiConfig}
${cfg.poolConfig}
'';
}; };
services.httpd = { services.httpd = {
@ -403,7 +398,7 @@ in
<Directory "${pkg}/share/mediawiki"> <Directory "${pkg}/share/mediawiki">
<FilesMatch "\.php$"> <FilesMatch "\.php$">
<If "-f %{REQUEST_FILENAME}"> <If "-f %{REQUEST_FILENAME}">
SetHandler "proxy:unix:${fpm.listen}|fcgi://localhost/" SetHandler "proxy:unix:${fpm.socket}|fcgi://localhost/"
</If> </If>
</FilesMatch> </FilesMatch>

View File

@ -4,6 +4,7 @@ with lib;
let let
cfg = config.services.nextcloud; cfg = config.services.nextcloud;
fpm = config.services.phpfpm.pools.nextcloud;
phpPackage = pkgs.php73; phpPackage = pkgs.php73;
phpPackages = pkgs.php73Packages; phpPackages = pkgs.php73Packages;
@ -410,25 +411,20 @@ in {
}; };
services.phpfpm = { services.phpfpm = {
pools.nextcloud = let pools.nextcloud = {
phpAdminValues = (toKeyValue user = "nextcloud";
(foldr (a: b: a // b) {} group = "nginx";
(mapAttrsToList (k: v: { "php_admin_value[${k}]" = v; }) phpOptions = phpOptionsExtensions + phpOptionsStr;
phpOptions)));
in {
phpOptions = phpOptionsExtensions;
phpPackage = phpPackage; phpPackage = phpPackage;
listen = "/run/phpfpm/nextcloud"; phpEnv = {
extraConfig = '' NEXTCLOUD_CONFIG_DIR = "${cfg.home}/config";
listen.owner = nginx PATH = "/run/wrappers/bin:/nix/var/nix/profiles/default/bin:/run/current-system/sw/bin:/usr/bin:/bin";
listen.group = nginx };
user = nextcloud settings = mapAttrs (name: mkDefault) {
group = nginx "listen.owner" = "nginx";
${cfg.poolConfig} "listen.group" = "nginx";
env[NEXTCLOUD_CONFIG_DIR] = ${cfg.home}/config };
env[PATH] = /run/wrappers/bin:/nix/var/nix/profiles/default/bin:/run/current-system/sw/bin:/usr/bin:/bin extraConfig = cfg.poolConfig;
${phpAdminValues}
'';
}; };
}; };
@ -489,7 +485,7 @@ in {
fastcgi_param HTTPS ${if cfg.https then "on" else "off"}; fastcgi_param HTTPS ${if cfg.https then "on" else "off"};
fastcgi_param modHeadersAvailable true; fastcgi_param modHeadersAvailable true;
fastcgi_param front_controller_active true; fastcgi_param front_controller_active true;
fastcgi_pass unix:/run/phpfpm/nextcloud; fastcgi_pass unix:${fpm.socket};
fastcgi_intercept_errors on; fastcgi_intercept_errors on;
fastcgi_request_buffering off; fastcgi_request_buffering off;
fastcgi_read_timeout 120s; fastcgi_read_timeout 120s;

View File

@ -9,11 +9,11 @@ with lib;
let let
cfg = config.services.restya-board; cfg = config.services.restya-board;
fpm = config.services.phpfpm.pools.${poolName};
runDir = "/run/restya-board"; runDir = "/run/restya-board";
poolName = "restya-board"; poolName = "restya-board";
phpfpmSocketName = "/run/phpfpm/${poolName}.sock";
in in
@ -180,7 +180,7 @@ in
services.phpfpm.pools = { services.phpfpm.pools = {
"${poolName}" = { "${poolName}" = {
listen = phpfpmSocketName; inherit (cfg) user group;
phpOptions = '' phpOptions = ''
date.timezone = "CET" date.timezone = "CET"
@ -191,20 +191,18 @@ in
auth_password = ${cfg.email.password} auth_password = ${cfg.email.password}
''} ''}
''; '';
extraConfig = '' settings = mapAttrs (name: mkDefault) {
listen.owner = nginx "listen.owner" = "nginx";
listen.group = nginx "listen.group" = "nginx";
listen.mode = 0600 "listen.mode" = "0600";
user = ${cfg.user} "pm" = "dynamic";
group = ${cfg.group} "pm.max_children" = 75;
pm = dynamic "pm.start_servers" = 10;
pm.max_children = 75 "pm.min_spare_servers" = 5;
pm.start_servers = 10 "pm.max_spare_servers" = 20;
pm.min_spare_servers = 5 "pm.max_requests" = 500;
pm.max_spare_servers = 20 "catch_workers_output" = 1;
pm.max_requests = 500 };
catch_workers_output = 1
'';
}; };
}; };
@ -241,7 +239,7 @@ in
tryFiles = "$uri =404"; tryFiles = "$uri =404";
extraConfig = '' extraConfig = ''
include ${pkgs.nginx}/conf/fastcgi_params; include ${pkgs.nginx}/conf/fastcgi_params;
fastcgi_pass unix:${phpfpmSocketName}; fastcgi_pass unix:${fpm.socket};
fastcgi_index index.php; fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PHP_VALUE "upload_max_filesize=9G \n post_max_size=9G \n max_execution_time=200 \n max_input_time=200 \n memory_limit=256M"; fastcgi_param PHP_VALUE "upload_max_filesize=9G \n post_max_size=9G \n max_execution_time=200 \n max_input_time=200 \n memory_limit=256M";

View File

@ -4,7 +4,6 @@ let
cfg = config.services.selfoss; cfg = config.services.selfoss;
poolName = "selfoss_pool"; poolName = "selfoss_pool";
phpfpmSocketName = "/run/phpfpm/${poolName}.sock";
dataDir = "/var/lib/selfoss"; dataDir = "/var/lib/selfoss";
@ -116,21 +115,22 @@ in
config = mkIf cfg.enable { config = mkIf cfg.enable {
services.phpfpm.poolConfigs = mkIf (cfg.pool == "${poolName}") { services.phpfpm.pools = mkIf (cfg.pool == "${poolName}") {
"${poolName}" = '' "${poolName}" = {
listen = "${phpfpmSocketName}"; user = "nginx";
listen.owner = nginx settings = mapAttrs (name: mkDefault) {
listen.group = nginx "listen.owner" = "nginx";
listen.mode = 0600 "listen.group" = "nginx";
user = nginx "listen.mode" = "0600";
pm = dynamic "pm" = "dynamic";
pm.max_children = 75 "pm.max_children" = 75;
pm.start_servers = 10 "pm.start_servers" = 10;
pm.min_spare_servers = 5 "pm.min_spare_servers" = 5;
pm.max_spare_servers = 20 "pm.max_spare_servers" = 20;
pm.max_requests = 500 "pm.max_requests" = 500;
catch_workers_output = 1 "catch_workers_output" = 1;
''; };
};
}; };
systemd.services.selfoss-config = { systemd.services.selfoss-config = {

View File

@ -521,20 +521,19 @@ let
services.phpfpm.pools = mkIf (cfg.pool == "${poolName}") { services.phpfpm.pools = mkIf (cfg.pool == "${poolName}") {
"${poolName}" = { "${poolName}" = {
listen = "/var/run/phpfpm/${poolName}.sock"; inherit (cfg) user;
extraConfig = '' settings = mapAttrs (name: mkDefault) {
listen.owner = nginx "listen.owner" = "nginx";
listen.group = nginx "listen.group" = "nginx";
listen.mode = 0600 "listen.mode" = "0600";
user = ${cfg.user} "pm" = "dynamic";
pm = dynamic "pm.max_children" = 75;
pm.max_children = 75 "pm.start_servers" = 10;
pm.start_servers = 10 "pm.min_spare_servers" = 5;
pm.min_spare_servers = 5 "pm.max_spare_servers" = 20;
pm.max_spare_servers = 20 "pm.max_requests" = 500;
pm.max_requests = 500 "catch_workers_output" = 1;
catch_workers_output = 1 };
'';
}; };
}; };
@ -552,7 +551,7 @@ let
locations."~ \.php$" = { locations."~ \.php$" = {
extraConfig = '' extraConfig = ''
fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:${config.services.phpfpm.pools.${cfg.pool}.listen}; fastcgi_pass unix:${config.services.phpfpm.pools.${cfg.pool}.socket};
fastcgi_index index.php; fastcgi_index index.php;
''; '';
}; };

View File

@ -216,15 +216,15 @@ let
}; };
poolConfig = mkOption { poolConfig = mkOption {
type = types.lines; type = with types; attrsOf (oneOf [ str int bool ]);
default = '' default = {
pm = dynamic "pm" = "dynamic";
pm.max_children = 32 "pm.max_children" = 32;
pm.start_servers = 2 "pm.start_servers" = 2;
pm.min_spare_servers = 2 "pm.min_spare_servers" = 2;
pm.max_spare_servers = 4 "pm.max_spare_servers" = 4;
pm.max_requests = 500 "pm.max_requests" = 500;
''; };
description = '' description = ''
Options for the WordPress PHP pool. See the documentation on <literal>php-fpm.conf</literal> Options for the WordPress PHP pool. See the documentation on <literal>php-fpm.conf</literal>
for details on configuration directives. for details on configuration directives.
@ -280,15 +280,11 @@ in
services.phpfpm.pools = mapAttrs' (hostName: cfg: ( services.phpfpm.pools = mapAttrs' (hostName: cfg: (
nameValuePair "wordpress-${hostName}" { nameValuePair "wordpress-${hostName}" {
listen = "/run/phpfpm/wordpress-${hostName}.sock"; inherit user group;
extraConfig = '' settings = {
listen.owner = ${config.services.httpd.user} "listen.owner" = config.services.httpd.user;
listen.group = ${config.services.httpd.group} "listen.group" = config.services.httpd.group;
user = ${user} } // cfg.poolConfig;
group = ${group}
${cfg.poolConfig}
'';
} }
)) eachSite; )) eachSite;
@ -303,7 +299,7 @@ in
<Directory "${pkg hostName cfg}/share/wordpress"> <Directory "${pkg hostName cfg}/share/wordpress">
<FilesMatch "\.php$"> <FilesMatch "\.php$">
<If "-f %{REQUEST_FILENAME}"> <If "-f %{REQUEST_FILENAME}">
SetHandler "proxy:unix:/run/phpfpm/wordpress-${hostName}.sock|fcgi://localhost/" SetHandler "proxy:unix:${config.services.phpfpm.pools."wordpress-${hostName}".socket}|fcgi://localhost/"
</If> </If>
</FilesMatch> </FilesMatch>

View File

@ -133,15 +133,15 @@ in
}; };
poolConfig = mkOption { poolConfig = mkOption {
type = types.lines; type = with types; attrsOf (oneOf [ str int bool ]);
default = '' default = {
pm = dynamic "pm" = "dynamic";
pm.max_children = 32 "pm.max_children" = 32;
pm.start_servers = 2 "pm.start_servers" = 2;
pm.min_spare_servers = 2 "pm.min_spare_servers" = 2;
pm.max_spare_servers = 4 "pm.max_spare_servers" = 4;
pm.max_requests = 500 "pm.max_requests" = 500;
''; };
description = '' description = ''
Options for the Zabbix PHP pool. See the documentation on <literal>php-fpm.conf</literal> for details on configuration directives. Options for the Zabbix PHP pool. See the documentation on <literal>php-fpm.conf</literal> for details on configuration directives.
''; '';
@ -160,6 +160,8 @@ in
]; ];
services.phpfpm.pools.zabbix = { services.phpfpm.pools.zabbix = {
inherit user;
group = config.services.httpd.group;
phpOptions = '' phpOptions = ''
# https://www.zabbix.com/documentation/current/manual/installation/install # https://www.zabbix.com/documentation/current/manual/installation/install
memory_limit = 128M memory_limit = 128M
@ -177,15 +179,11 @@ in
'' + optionalString (cfg.database.type == "oracle") '' '' + optionalString (cfg.database.type == "oracle") ''
extension=${pkgs.phpPackages.oci8}/lib/php/extensions/oci8.so extension=${pkgs.phpPackages.oci8}/lib/php/extensions/oci8.so
''; '';
listen = "/run/phpfpm/zabbix.sock"; phpEnv.ZABBIX_CONFIG = zabbixConfig;
extraConfig = '' settings = {
listen.owner = ${config.services.httpd.user}; "listen.owner" = config.services.httpd.user;
listen.group = ${config.services.httpd.group}; "listen.group" = config.services.httpd.group;
user = ${user}; } // cfg.poolConfig;
group = ${config.services.httpd.group};
env[ZABBIX_CONFIG] = ${zabbixConfig}
${cfg.poolConfig}
'';
}; };
services.httpd = { services.httpd = {

View File

@ -4,41 +4,27 @@ with lib;
let let
cfg = config.services.phpfpm; cfg = config.services.phpfpm;
enabled = cfg.poolConfigs != {} || cfg.pools != {};
stateDir = "/run/phpfpm"; runtimeDir = "/run/phpfpm";
poolConfigs = toStr = value:
(mapAttrs mapPoolConfig cfg.poolConfigs) // if true == value then "yes"
(mapAttrs mapPool cfg.pools); else if false == value then "no"
else toString value;
mapPoolConfig = n: p: { fpmCfgFile = pool: poolOpts: pkgs.writeText "phpfpm-${pool}.conf" ''
phpPackage = cfg.phpPackage;
phpOptions = cfg.phpOptions;
config = p;
};
mapPool = n: p: {
phpPackage = p.phpPackage;
phpOptions = p.phpOptions;
config = ''
listen = ${p.listen}
${p.extraConfig}
'';
};
fpmCfgFile = pool: conf: pkgs.writeText "phpfpm-${pool}.conf" ''
[global] [global]
error_log = syslog ${concatStringsSep "\n" (mapAttrsToList (n: v: "${n} = ${toStr v}") cfg.settings)}
daemonize = no ${optionalString (cfg.extraConfig != null) cfg.extraConfig}
${cfg.extraConfig}
[${pool}] [${pool}]
${conf} ${concatStringsSep "\n" (mapAttrsToList (n: v: "${n} = ${toStr v}") poolOpts.settings)}
${concatStringsSep "\n" (mapAttrsToList (n: v: "env[${n}] = ${toStr v}") poolOpts.phpEnv)}
${optionalString (poolOpts.extraConfig != null) poolOpts.extraConfig}
''; '';
phpIni = pool: pkgs.runCommand "php.ini" { phpIni = poolOpts: pkgs.runCommand "php.ini" {
inherit (pool) phpPackage phpOptions; inherit (poolOpts) phpPackage phpOptions;
preferLocalBuild = true; preferLocalBuild = true;
nixDefaults = '' nixDefaults = ''
sendmail_path = "/run/wrappers/bin/sendmail -t -i" sendmail_path = "/run/wrappers/bin/sendmail -t -i"
@ -48,13 +34,138 @@ let
cat $phpPackage/etc/php.ini $nixDefaultsPath $phpOptionsPath > $out cat $phpPackage/etc/php.ini $nixDefaultsPath $phpOptionsPath > $out
''; '';
poolOpts = { name, ... }:
let
poolOpts = cfg.pools."${name}";
in
{
options = {
socket = mkOption {
type = types.str;
readOnly = true;
description = ''
Path to the unix socket file on which to accept FastCGI requests.
<note><para>This option is read-only and managed by NixOS.</para></note>
'';
};
listen = mkOption {
type = types.str;
default = "";
example = "/path/to/unix/socket";
description = ''
The address on which to accept FastCGI requests.
'';
};
phpPackage = mkOption {
type = types.package;
default = cfg.phpPackage;
defaultText = "config.services.phpfpm.phpPackage";
description = ''
The PHP package to use for running this PHP-FPM pool.
'';
};
phpOptions = mkOption {
type = types.lines;
default = cfg.phpOptions;
defaultText = "config.services.phpfpm.phpOptions";
description = ''
"Options appended to the PHP configuration file <filename>php.ini</filename> used for this PHP-FPM pool."
'';
};
phpEnv = lib.mkOption {
type = with types; attrsOf str;
default = {};
description = ''
Environment variables used for this PHP-FPM pool.
'';
example = literalExample ''
{
HOSTNAME = "$HOSTNAME";
TMP = "/tmp";
TMPDIR = "/tmp";
TEMP = "/tmp";
}
'';
};
user = mkOption {
type = types.str;
description = "User account under which this pool runs.";
};
group = mkOption {
type = types.str;
description = "Group account under which this pool runs.";
};
settings = mkOption {
type = with types; attrsOf (oneOf [ str int bool ]);
default = {};
description = ''
PHP-FPM pool directives. Refer to the "List of pool directives" section of
<link xlink:href="https://www.php.net/manual/en/install.fpm.configuration.php"/>
for details. Note that settings names must be enclosed in quotes (e.g.
<literal>"pm.max_children"</literal> instead of <literal>pm.max_children</literal>).
'';
example = literalExample ''
{
"pm" = "dynamic";
"pm.max_children" = 75;
"pm.start_servers" = 10;
"pm.min_spare_servers" = 5;
"pm.max_spare_servers" = 20;
"pm.max_requests" = 500;
}
'';
};
extraConfig = mkOption {
type = with types; nullOr lines;
default = null;
description = ''
Extra lines that go into the pool configuration.
See the documentation on <literal>php-fpm.conf</literal> for
details on configuration directives.
'';
};
};
config = {
socket = if poolOpts.listen == "" then "${runtimeDir}/${name}.sock" else poolOpts.listen;
group = mkDefault poolOpts.user;
settings = mapAttrs (name: mkDefault){
listen = poolOpts.socket;
user = poolOpts.user;
group = poolOpts.group;
};
};
};
in { in {
options = { options = {
services.phpfpm = { services.phpfpm = {
settings = mkOption {
type = with types; attrsOf (oneOf [ str int bool ]);
default = {};
description = ''
PHP-FPM global directives. Refer to the "List of global php-fpm.conf directives" section of
<link xlink:href="https://www.php.net/manual/en/install.fpm.configuration.php"/>
for details. Note that settings names must be enclosed in quotes (e.g.
<literal>"pm.max_children"</literal> instead of <literal>pm.max_children</literal>).
You need not specify the options <literal>error_log</literal> or
<literal>daemonize</literal> here, since they are generated by NixOS.
'';
};
extraConfig = mkOption { extraConfig = mkOption {
type = types.lines; type = with types; nullOr lines;
default = ""; default = null;
description = '' description = ''
Extra configuration that should be put in the global section of Extra configuration that should be put in the global section of
the PHP-FPM configuration file. Do not specify the options the PHP-FPM configuration file. Do not specify the options
@ -80,64 +191,56 @@ in {
'' ''
date.timezone = "CET" date.timezone = "CET"
''; '';
description =
"Options appended to the PHP configuration file <filename>php.ini</filename>.";
};
poolConfigs = mkOption {
default = {};
type = types.attrsOf types.lines;
example = literalExample ''
{ mypool = '''
listen = /run/phpfpm/mypool
user = nobody
pm = dynamic
pm.max_children = 75
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20
pm.max_requests = 500
''';
}
'';
description = '' description = ''
A mapping between PHP-FPM pool names and their configurations. Options appended to the PHP configuration file <filename>php.ini</filename>.
See the documentation on <literal>php-fpm.conf</literal> for
details on configuration directives. If no pools are defined,
the phpfpm service is disabled.
''; '';
}; };
pools = mkOption { pools = mkOption {
type = types.attrsOf (types.submodule (import ./pool-options.nix { type = types.attrsOf (types.submodule poolOpts);
inherit lib config;
}));
default = {}; default = {};
example = literalExample '' example = literalExample ''
{ {
mypool = { mypool = {
listen = "/path/to/unix/socket"; user = "php";
group = "php";
phpPackage = pkgs.php; phpPackage = pkgs.php;
extraConfig = ''' settings = '''
user = nobody "pm" = "dynamic";
pm = dynamic "pm.max_children" = 75;
pm.max_children = 75 "pm.start_servers" = 10;
pm.start_servers = 10 "pm.min_spare_servers" = 5;
pm.min_spare_servers = 5 "pm.max_spare_servers" = 20;
pm.max_spare_servers = 20 "pm.max_requests" = 500;
pm.max_requests = 500
'''; ''';
} }
}''; }'';
description = '' description = ''
PHP-FPM pools. If no pools or poolConfigs are defined, the PHP-FPM PHP-FPM pools. If no pools are defined, the PHP-FPM
service is disabled. service is disabled.
''; '';
}; };
}; };
}; };
config = mkIf enabled { config = mkIf (cfg.pools != {}) {
warnings =
mapAttrsToList (pool: poolOpts: ''
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.
'') (filterAttrs (pool: poolOpts: poolOpts.listen != "") cfg.pools) ++
mapAttrsToList (pool: poolOpts: ''
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.
'') (filterAttrs (pool: poolOpts: poolOpts.extraConfig != null) cfg.pools) ++
optional (cfg.extraConfig != null) ''
Using config.services.phpfpm.extraConfig is deprecated and will become unsupported in a future release. Please migrate your configuration to config.services.phpfpm.settings.
''
;
services.phpfpm.settings = {
error_log = "syslog";
daemonize = false;
};
systemd.slices.phpfpm = { systemd.slices.phpfpm = {
description = "PHP FastCGI Process manager pools slice"; description = "PHP FastCGI Process manager pools slice";
@ -148,18 +251,15 @@ in {
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
}; };
systemd.services = flip mapAttrs' poolConfigs (pool: poolConfig: systemd.services = mapAttrs' (pool: poolOpts:
nameValuePair "phpfpm-${pool}" { nameValuePair "phpfpm-${pool}" {
description = "PHP FastCGI Process Manager service for pool ${pool}"; description = "PHP FastCGI Process Manager service for pool ${pool}";
after = [ "network.target" ]; after = [ "network.target" ];
wantedBy = [ "phpfpm.target" ]; wantedBy = [ "phpfpm.target" ];
partOf = [ "phpfpm.target" ]; partOf = [ "phpfpm.target" ];
preStart = ''
mkdir -p ${stateDir}
'';
serviceConfig = let serviceConfig = let
cfgFile = fpmCfgFile pool poolConfig.config; cfgFile = fpmCfgFile pool poolOpts;
iniFile = phpIni poolConfig; iniFile = phpIni poolOpts;
in { in {
Slice = "phpfpm.slice"; Slice = "phpfpm.slice";
PrivateDevices = true; PrivateDevices = true;
@ -168,10 +268,12 @@ in {
# XXX: We need AF_NETLINK to make the sendmail SUID binary from postfix work # XXX: We need AF_NETLINK to make the sendmail SUID binary from postfix work
RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6 AF_NETLINK"; RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6 AF_NETLINK";
Type = "notify"; Type = "notify";
ExecStart = "${poolConfig.phpPackage}/bin/php-fpm -y ${cfgFile} -c ${iniFile}"; ExecStart = "${poolOpts.phpPackage}/bin/php-fpm -y ${cfgFile} -c ${iniFile}";
ExecReload = "${pkgs.coreutils}/bin/kill -USR2 $MAINPID"; ExecReload = "${pkgs.coreutils}/bin/kill -USR2 $MAINPID";
RuntimeDirectory = "phpfpm";
RuntimeDirectoryPreserve = true; # Relevant when multiple processes are running
}; };
} }
); ) cfg.pools;
}; };
} }

View File

@ -1,57 +0,0 @@
{ lib, config }:
let
fpmCfg = config.services.phpfpm;
in
with lib; {
options = {
listen = mkOption {
type = types.str;
example = "/path/to/unix/socket";
description = ''
The address on which to accept FastCGI requests.
'';
};
phpPackage = mkOption {
type = types.package;
default = fpmCfg.phpPackage;
defaultText = "config.services.phpfpm.phpPackage";
description = ''
The PHP package to use for running this PHP-FPM pool.
'';
};
phpOptions = mkOption {
type = types.lines;
default = fpmCfg.phpOptions;
defaultText = "config.services.phpfpm.phpOptions";
description = ''
"Options appended to the PHP configuration file <filename>php.ini</filename> used for this PHP-FPM pool."
'';
};
extraConfig = mkOption {
type = types.lines;
example = ''
user = nobody
pm = dynamic
pm.max_children = 75
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20
pm.max_requests = 500
'';
description = ''
Extra lines that go into the pool configuration.
See the documentation on <literal>php-fpm.conf</literal> for
details on configuration directives.
'';
};
};
}