summary refs log tree commit diff
path: root/nixos/modules/services/web-servers/phpfpm/default.nix
diff options
context:
space:
mode:
authorElis Hirwing <elis@hirwing.se>2019-06-27 19:13:53 +0200
committerGitHub <noreply@github.com>2019-06-27 19:13:53 +0200
commitb5478fd1a2ef442a54c36031bf3a27a96b5ea31c (patch)
treea898427ac474957a680888252c810e4bdfe37ecc /nixos/modules/services/web-servers/phpfpm/default.nix
parentdbb00bfcbfb291e79d4d2d512041656e6bcfcd9a (diff)
parenteee87b460ea9a5a9e122dcc313fa20b9962872a5 (diff)
downloadnixpkgs-b5478fd1a2ef442a54c36031bf3a27a96b5ea31c.tar
nixpkgs-b5478fd1a2ef442a54c36031bf3a27a96b5ea31c.tar.gz
nixpkgs-b5478fd1a2ef442a54c36031bf3a27a96b5ea31c.tar.bz2
nixpkgs-b5478fd1a2ef442a54c36031bf3a27a96b5ea31c.tar.lz
nixpkgs-b5478fd1a2ef442a54c36031bf3a27a96b5ea31c.tar.xz
nixpkgs-b5478fd1a2ef442a54c36031bf3a27a96b5ea31c.tar.zst
nixpkgs-b5478fd1a2ef442a54c36031bf3a27a96b5ea31c.zip
Merge pull request #63156 from Izorkin/phpfpm-rootless
phpfpm: do not run anything as root
Diffstat (limited to 'nixos/modules/services/web-servers/phpfpm/default.nix')
-rw-r--r--nixos/modules/services/web-servers/phpfpm/default.nix186
1 files changed, 97 insertions, 89 deletions
diff --git a/nixos/modules/services/web-servers/phpfpm/default.nix b/nixos/modules/services/web-servers/phpfpm/default.nix
index ffafbc5e92f..e424080ab1f 100644
--- a/nixos/modules/services/web-servers/phpfpm/default.nix
+++ b/nixos/modules/services/web-servers/phpfpm/default.nix
@@ -4,37 +4,26 @@ with lib;
 
 let
   cfg = config.services.phpfpm;
-  enabled = cfg.poolConfigs != {} || cfg.pools != {};
+  enabled = cfg.pools != {};
 
-  stateDir = "/run/phpfpm";
-
-  poolConfigs =
-    (mapAttrs mapPoolConfig cfg.poolConfigs) //
-    (mapAttrs mapPool cfg.pools);
-
-  mapPoolConfig = n: p: {
-    phpPackage = cfg.phpPackage;
-    phpOptions = cfg.phpOptions;
-    config = p;
-  };
+  poolConfigs = (mapAttrs mapPool cfg.pools);
 
   mapPool = n: p: {
     phpPackage = p.phpPackage;
     phpOptions = p.phpOptions;
-    config = ''
-      listen = ${p.listen}
-      ${p.extraConfig}
-    '';
+    userPool = p.user;
+    groupPool = p.group;
   };
 
   fpmCfgFile = pool: conf: pkgs.writeText "phpfpm-${pool}.conf" ''
     [global]
     error_log = syslog
     daemonize = no
-    ${cfg.extraConfig}
+    ${cfg.globalExtraConfig}
 
     [${pool}]
-    ${conf}
+    listen = /run/phpfpm-${pool}/${cfg.pools.${pool}.socketName}.sock
+    ${cfg.pools.${pool}.extraConfig}
   '';
 
   phpIni = pool: pkgs.runCommand "php.ini" {
@@ -49,87 +38,100 @@ let
   '';
 
 in {
-
   options = {
     services.phpfpm = {
-      extraConfig = mkOption {
+      globalExtraConfig = mkOption {
         type = types.lines;
         default = "";
         description = ''
-          Extra configuration that should be put in the global section of
+          Global extra configuration that should be put in the global section of
           the PHP-FPM configuration file. Do not specify the options
           <literal>error_log</literal> or
-          <literal>daemonize</literal> here, since they are generated by
-          NixOS.
-        '';
-      };
-
-      phpPackage = mkOption {
-        type = types.package;
-        default = pkgs.php;
-        defaultText = "pkgs.php";
-        description = ''
-          The PHP package to use for running the PHP-FPM service.
+          <literal>daemonize</literal> here, since they are generated by NixOS.
         '';
       };
 
-      phpOptions = mkOption {
-        type = types.lines;
-        default = "";
-        example =
-          ''
-            date.timezone = "CET"
-          '';
-        description =
-          "Options appended to the PHP configuration file <filename>php.ini</filename>.";
-      };
-
-      poolConfigs = mkOption {
+      pools = mkOption {
         default = {};
-        type = types.attrsOf types.lines;
+        type = types.attrsOf (types.submodule {
+          options = {
+            socketName = mkOption {
+              type = types.str;
+              example = "php-fpm";
+              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."
+              '';
+            };
+
+            user = mkOption {
+              type = types.string;
+              default = "phpfpm";
+              description = "User account under which phpfpm runs.";
+            };
+
+            group = mkOption {
+              type = types.string;
+              default = "phpfpm";
+              description = "Group account under which phpfpm runs.";
+            };
+
+            extraConfig = mkOption {
+              type = types.lines;
+              example = ''
+                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.
+              '';
+            };
+          };
+        });
+
         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
-            ''';
+          {
+            mypool = {
+              socketName = "example";
+              phpPackage = pkgs.php;
+              user = "phpfpm";
+              group = "phpfpm";
+              extraConfig = '''
+                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 = ''
-          A mapping between PHP-FPM pool names and their configurations.
-          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 {
-        type = types.attrsOf (types.submodule (import ./pool-options.nix {
-          inherit lib config;
-        }));
-        default = {};
-        example = literalExample ''
-         {
-           mypool = {
-             listen = "/path/to/unix/socket";
-             phpPackage = pkgs.php;
-             extraConfig = '''
-               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 = ''
           PHP-FPM pools. If no pools or poolConfigs are defined, the PHP-FPM
           service is disabled.
         '';
@@ -154,9 +156,6 @@ in {
         after = [ "network.target" ];
         wantedBy = [ "phpfpm.target" ];
         partOf = [ "phpfpm.target" ];
-        preStart = ''
-          mkdir -p ${stateDir}
-        '';
         serviceConfig = let
           cfgFile = fpmCfgFile pool poolConfig.config;
           iniFile = phpIni poolConfig;
@@ -166,10 +165,19 @@ in {
           ProtectSystem = "full";
           ProtectHome = true;
           # 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";
-          ExecStart = "${poolConfig.phpPackage}/bin/php-fpm -y ${cfgFile} -c ${iniFile}";
+          ExecStart = "${poolConfig.phpPackage}/bin/php-fpm -y '${cfgFile}' -c '${iniFile}'";
           ExecReload = "${pkgs.coreutils}/bin/kill -USR2 $MAINPID";
+          # User and group
+          User = "${poolConfig.userPool}";
+          Group = "${poolConfig.groupPool}";
+          # Runtime directory and mode
+          RuntimeDirectory = "phpfpm-${pool}";
+          RuntimeDirectoryMode = "0750";
+          # Capabilities
+          AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" "CAP_SETGID" "CAP_SETUID" "CAP_CHOWN" "CAP_SYS_RESOURCE" ];
+          CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" "CAP_SETGID" "CAP_SETUID" "CAP_CHOWN" "CAP_SYS_RESOURCE" ];
         };
       }
    );