-{ config, lib, pkgs, ... }:
-
-with lib;
-
-let
- cfg = config.services.myPhpfpm;
- enabled = cfg.poolConfigs != {} || cfg.pools != {};
-
- stateDir = "/run/phpfpm";
-
- poolConfigs = cfg.poolConfigs // mapAttrs mkPool cfg.pools;
-
- mkPool = n: p: ''
- listen = ${p.listen}
- ${p.extraConfig}
- '';
-
- fpmCfgFile = pool: poolConfig: pkgs.writeText "phpfpm-${pool}.conf" ''
- [global]
- error_log = syslog
- daemonize = no
- ${cfg.extraConfig}
-
- [${pool}]
- ${poolConfig}
- '';
-
- phpIni = poolPhpOptions: (pkgs.runCommand "php.ini" {
- inherit (cfg) phpPackage phpOptions;
- inherit poolPhpOptions;
- nixDefaults = ''
- sendmail_path = "/run/wrappers/bin/sendmail -t -i"
- '';
- passAsFile = [ "nixDefaults" "phpOptions" "poolPhpOptions" ];
- } ''
- cat $phpPackage/etc/php.ini $nixDefaultsPath $phpOptionsPath $poolPhpOptionsPath > $out
- '');
-
-in {
-
- options = {
- services.myPhpfpm = {
- extraConfig = mkOption {
- type = types.lines;
- default = "";
- description = ''
- 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.
- '';
- };
-
- phpOptions = mkOption {
- type = types.lines;
- default = "";
- example =
- ''
- date.timezone = "CET"
- '';
- description =
- "Options appended to the PHP configuration file <filename>php.ini</filename>.";
- };
-
- serviceDependencies = mkOption {
- default = {};
- type = types.attrsOf (types.listOf types.string);
- example = literalExample ''
- { mypool = ["postgresql.service"]; }
- '';
- description = ''
- Extra service dependencies specific to pool.
- '';
- };
-
- envFile = mkOption {
- default = {};
- type = types.attrsOf types.string;
- example = literalExample ''
- { mypool = "path/to/file";
- }
- '';
- description = ''
- Extra environment file go into the service script.
- '';
- };
-
- preStart = mkOption {
- default = {};
- type = types.attrsOf types.lines;
- example = literalExample ''
- { mypool = '''
- touch foo
- ''';
- }
- '';
- description = ''
- Extra lines that will go into the preStart systemd service
- '';
- };
-
- poolPhpConfigs = mkOption {
- default = {};
- type = types.attrsOf types.lines;
- example = literalExample ''
- { mypool = '''
- extension = some_extension.so
- ''';
- }
- '';
- description = ''
- Extra lines that go into the php configuration specific to pool.
- '';
- };
-
- 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 = ''
- 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;
- }));
- default = {};
- example = literalExample ''
- {
- mypool = {
- listen = "/path/to/unix/socket";
- 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.
- '';
- };
- };
- };
-
- config = mkIf enabled {
-
- systemd.slices.phpfpm = {
- description = "PHP FastCGI Process manager pools slice";
- };
-
- systemd.targets.phpfpm = {
- description = "PHP FastCGI Process manager pools target";
- wantedBy = [ "multi-user.target" ];
- };
-
- systemd.services = flip mapAttrs' poolConfigs (pool: poolConfig:
- nameValuePair "phpfpm-${pool}" {
- description = "PHP FastCGI Process Manager service for pool ${pool}";
- after = [ "network.target" ] ++ (cfg.serviceDependencies.${pool} or []);
- wants = cfg.serviceDependencies.${pool} or [];
- wantedBy = [ "phpfpm.target" ];
- partOf = [ "phpfpm.target" ];
- preStart = ''
- mkdir -p ${stateDir}
- '' + (cfg.preStart.${pool} or "");
- serviceConfig = let
- cfgFile = fpmCfgFile pool poolConfig;
- poolPhpIni = cfg.poolPhpConfigs.${pool} or "";
- in {
- EnvironmentFile = if builtins.hasAttr pool cfg.envFile then [cfg.envFile.${pool}] else [];
- Slice = "phpfpm.slice";
- PrivateDevices = true;
- 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";
- Type = "notify";
- ExecStart = "${cfg.phpPackage}/bin/php-fpm -y ${cfgFile} -c ${phpIni poolPhpIni}";
- ExecReload = "${pkgs.coreutils}/bin/kill -USR2 $MAINPID";
- };
- }
- );
- };
-}