From 02abf4ed0131237c25e0a10db50fa4c41a902a50 Mon Sep 17 00:00:00 2001 From: Alejandro Soto Date: Sun, 14 Jul 2024 17:53:13 -0600 Subject: sys: final merge of dmz, hv into sys --- sys/web/php-fpm.nix | 152 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 sys/web/php-fpm.nix (limited to 'sys/web/php-fpm.nix') diff --git a/sys/web/php-fpm.nix b/sys/web/php-fpm.nix new file mode 100644 index 0000000..65276ba --- /dev/null +++ b/sys/web/php-fpm.nix @@ -0,0 +1,152 @@ +# Based on +# See also: +# - +# - + +{ config, lib, pkgs, ... }: +with lib; let + cfg = config.services.php-fpm-isolated; + + configFile = { pool, poolOpts, runtimeDir, sockFile, pidFile }: + let + config = { + global = { + daemonize = false; + error_log = "syslog"; + pid = pidFile; + }; + + "${pool}" = + let + enforced = { + inherit (poolOpts) user group; + listen = sockFile; + }; + + defaults = { + "pm" = "dynamic"; + "pm.max_children" = 16; + "pm.min_spare_servers" = 1; + "pm.max_spare_servers" = 4; + "pm.start_servers" = 1; + "catch_workers_output" = true; + "php_admin_flag[log_errors]" = true; + "env[PATH]" = makeBinPath [ pkgs.php ]; + }; + + env = mapAttrs' + (name: value: { + name = "env[${name}]"; + value = "\"${escape [ "\"" ] value}\""; + }) + poolOpts.env; + in + defaults // poolOpts.config // env // enforced; + }; + in + (pkgs.formats.ini { }).generate "php-fpm-pool-${pool}.conf" config; +in +{ + options.services.php-fpm-isolated.pools = mkOption { + default = { }; + + type = with types; attrsOf (submodule { + options = { + enable = mkEnableOption "PHP-FPM pool"; + + user = mkOption { + type = str; + }; + + group = mkOption { + type = str; + }; + + unveil = mkOption { + type = listOf (either package str); + }; + + env = mkOption { + type = attrsOf str; + default = { }; + }; + + config = mkOption { + type = attrsOf (oneOf [ int str bool ]); + default = { }; + }; + }; + }); + }; + + config.systemd = + let + php-fpm = "${pkgs.php}/bin/php-fpm"; + + unitsFor = pool: poolOpts: + let + runtimeBase = "php-fpm-isolated/${pool}"; + runtimeDir = "/run/${runtimeBase}"; + pidFile = "${runtimeDir}/${pool}.pid"; + sockFile = "${runtimeDir}/${pool}.sock"; + in + { + name = "php-fpm-pool-${pool}"; + + value.service = { + description = "PHP-FPM process manager for pool '${pool}'"; + after = [ "network.target" ]; + + confinement.enable = true; + + serviceConfig = { + Type = "notify"; + ExecReload = "${pkgs.coreutils}/bin/kill -USR2 $MAINPID"; + PIDFile = pidFile; + + Environment = "FPM_SOCKETS=${sockFile}=3"; + + ExecStart = + let + fpmConfig = configFile { + inherit pool poolOpts runtimeDir sockFile pidFile; + }; + in + "${php-fpm} --nodaemonize --fpm-config ${fpmConfig} --pid ${pidFile}"; + + PrivateTmp = true; + PrivateNetwork = true; + PrivateDevices = true; + # XXX: We need AF_NETLINK to make the sendmail SUID binary from postfix work + RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6 AF_NETLINK"; + + User = poolOpts.user; + Group = poolOpts.group; + RuntimeDirectory = runtimeBase; + + BindReadOnlyPaths = + let + unveiled = map builtins.toString poolOpts.unveil; + in + [ "/run/systemd/journal/socket" ] ++ unveiled; + }; + }; + + value.socket = { + description = "PHP-FPM socket for pool '${pool}'"; + listenStreams = [ sockFile ]; + + socketConfig = { + User = poolOpts.user; + Group = poolOpts.group; + }; + }; + }; + + units = mapAttrs' unitsFor (filterAttrs (_: pool: pool.enable) cfg.pools); + in + { + sockets = mapAttrs (_: unit: unit.socket) units; + services = mapAttrs (_: unit: unit.service) units; + }; +} -- cgit v1.2.3