diff options
Diffstat (limited to 'nixos/modules/services/web-servers')
-rw-r--r-- | nixos/modules/services/web-servers/caddy.nix | 2 | ||||
-rw-r--r-- | nixos/modules/services/web-servers/darkhttpd.nix | 77 | ||||
-rw-r--r-- | nixos/modules/services/web-servers/nginx/default.nix | 33 | ||||
-rw-r--r-- | nixos/modules/services/web-servers/phpfpm/default.nix | 252 | ||||
-rw-r--r-- | nixos/modules/services/web-servers/phpfpm/pool-options.nix | 57 |
5 files changed, 286 insertions, 135 deletions
diff --git a/nixos/modules/services/web-servers/caddy.nix b/nixos/modules/services/web-servers/caddy.nix index d0b936cb019fd..6a1db6087840a 100644 --- a/nixos/modules/services/web-servers/caddy.nix +++ b/nixos/modules/services/web-servers/caddy.nix @@ -70,7 +70,7 @@ in { { CADDYPATH = cfg.dataDir; }; serviceConfig = { ExecStart = '' - ${cfg.package.bin}/bin/caddy -root=/var/tmp -conf=${configFile} \ + ${cfg.package}/bin/caddy -root=/var/tmp -conf=${configFile} \ -ca=${cfg.ca} -email=${cfg.email} ${optionalString cfg.agree "-agree"} ''; ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; diff --git a/nixos/modules/services/web-servers/darkhttpd.nix b/nixos/modules/services/web-servers/darkhttpd.nix new file mode 100644 index 0000000000000..80870118c334b --- /dev/null +++ b/nixos/modules/services/web-servers/darkhttpd.nix @@ -0,0 +1,77 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.darkhttpd; + + args = concatStringsSep " " ([ + cfg.rootDir + "--port ${toString cfg.port}" + "--addr ${cfg.address}" + ] ++ cfg.extraArgs + ++ optional cfg.hideServerId "--no-server-id" + ++ optional config.networking.enableIPv6 "--ipv6"); + +in { + options.services.darkhttpd = with types; { + enable = mkEnableOption "DarkHTTPd web server"; + + port = mkOption { + default = 80; + type = ints.u16; + description = '' + Port to listen on. + Pass 0 to let the system choose any free port for you. + ''; + }; + + address = mkOption { + default = "127.0.0.1"; + type = str; + description = '' + Address to listen on. + Pass `all` to listen on all interfaces. + ''; + }; + + rootDir = mkOption { + type = path; + description = '' + Path from which to serve files. + ''; + }; + + hideServerId = mkOption { + type = bool; + default = true; + description = '' + Don't identify the server type in headers or directory listings. + ''; + }; + + extraArgs = mkOption { + type = listOf str; + default = []; + description = '' + Additional configuration passed to the executable. + ''; + }; + }; + + config = mkIf cfg.enable { + systemd.services.darkhttpd = { + description = "Dark HTTPd"; + wants = [ "network.target" ]; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + DynamicUser = true; + ExecStart = "${cfg.package}/bin/darkhttpd ${args}"; + AmbientCapabilities = lib.mkIf (cfg.port < 1024) [ "CAP_NET_BIND_SERVICE" ]; + Restart = "on-failure"; + RestartSec = "2s"; + }; + }; + }; +} diff --git a/nixos/modules/services/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix index 2b7fcb3140417..c1a51fbf8b425 100644 --- a/nixos/modules/services/web-servers/nginx/default.nix +++ b/nixos/modules/services/web-servers/nginx/default.nix @@ -162,6 +162,10 @@ let ${cfg.appendConfig} ''; + configPath = if cfg.enableReload + then "/etc/nginx/nginx.conf" + else configFile; + vhosts = concatStringsSep "\n" (mapAttrsToList (vhostName: vhost: let onlySSL = vhost.onlySSL || vhost.enableSSL; @@ -431,6 +435,16 @@ in "; }; + enableReload = mkOption { + default = false; + type = types.bool; + description = '' + Reload nginx when configuration file changes (instead of restart). + The configuration file is exposed at <filename>/etc/nginx/nginx.conf</filename>. + See also <literal>systemd.services.*.restartIfChanged</literal>. + ''; + }; + stateDir = mkOption { default = "/var/spool/nginx"; description = " @@ -638,10 +652,10 @@ in preStart = '' ${cfg.preStart} - ${cfg.package}/bin/nginx -c ${configFile} -p ${cfg.stateDir} -t + ${cfg.package}/bin/nginx -c ${configPath} -p ${cfg.stateDir} -t ''; serviceConfig = { - ExecStart = "${cfg.package}/bin/nginx -c ${configFile} -p ${cfg.stateDir}"; + ExecStart = "${cfg.package}/bin/nginx -c ${configPath} -p ${cfg.stateDir}"; ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; Restart = "always"; RestartSec = "10s"; @@ -649,6 +663,21 @@ in }; }; + environment.etc."nginx/nginx.conf" = mkIf cfg.enableReload { + source = configFile; + }; + + systemd.services.nginx-config-reload = mkIf cfg.enableReload { + wantedBy = [ "nginx.service" ]; + restartTriggers = [ configFile ]; + script = '' + if ${pkgs.systemd}/bin/systemctl -q is-active nginx.service ; then + ${pkgs.systemd}/bin/systemctl reload nginx.service + fi + ''; + serviceConfig.RemainAfterExit = true; + }; + security.acme.certs = filterAttrs (n: v: v != {}) ( let vhostsConfigs = mapAttrsToList (vhostName: vhostConfig: vhostConfig) virtualHosts; diff --git a/nixos/modules/services/web-servers/phpfpm/default.nix b/nixos/modules/services/web-servers/phpfpm/default.nix index ffafbc5e92f21..e95e71e0d997e 100644 --- a/nixos/modules/services/web-servers/phpfpm/default.nix +++ b/nixos/modules/services/web-servers/phpfpm/default.nix @@ -4,41 +4,27 @@ with lib; let cfg = config.services.phpfpm; - enabled = cfg.poolConfigs != {} || cfg.pools != {}; - stateDir = "/run/phpfpm"; + runtimeDir = "/run/phpfpm"; - poolConfigs = - (mapAttrs mapPoolConfig cfg.poolConfigs) // - (mapAttrs mapPool cfg.pools); + toStr = value: + if true == value then "yes" + else if false == value then "no" + else toString value; - mapPoolConfig = n: p: { - 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" '' + fpmCfgFile = pool: poolOpts: pkgs.writeText "phpfpm-${pool}.conf" '' [global] - error_log = syslog - daemonize = no - ${cfg.extraConfig} + ${concatStringsSep "\n" (mapAttrsToList (n: v: "${n} = ${toStr v}") cfg.settings)} + ${optionalString (cfg.extraConfig != null) cfg.extraConfig} [${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" { - inherit (pool) phpPackage phpOptions; + phpIni = poolOpts: pkgs.runCommand "php.ini" { + inherit (poolOpts) phpPackage phpOptions; preferLocalBuild = true; nixDefaults = '' sendmail_path = "/run/wrappers/bin/sendmail -t -i" @@ -48,13 +34,138 @@ let 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 { options = { 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 { - type = types.lines; - default = ""; + type = with types; nullOr lines; + default = null; description = '' Extra configuration that should be put in the global section of the PHP-FPM configuration file. Do not specify the options @@ -80,64 +191,56 @@ in { '' 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 = '' - 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. + Options appended to the PHP configuration file <filename>php.ini</filename>. ''; }; pools = mkOption { - type = types.attrsOf (types.submodule (import ./pool-options.nix { - inherit lib config; - })); + type = types.attrsOf (types.submodule poolOpts); default = {}; example = literalExample '' { mypool = { - listen = "/path/to/unix/socket"; + user = "php"; + group = "php"; 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 + settings = ''' + "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 + PHP-FPM pools. If no pools are defined, the PHP-FPM 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 = { description = "PHP FastCGI Process manager pools slice"; @@ -148,18 +251,15 @@ in { wantedBy = [ "multi-user.target" ]; }; - systemd.services = flip mapAttrs' poolConfigs (pool: poolConfig: + systemd.services = mapAttrs' (pool: poolOpts: nameValuePair "phpfpm-${pool}" { description = "PHP FastCGI Process Manager service for pool ${pool}"; after = [ "network.target" ]; wantedBy = [ "phpfpm.target" ]; partOf = [ "phpfpm.target" ]; - preStart = '' - mkdir -p ${stateDir} - ''; serviceConfig = let - cfgFile = fpmCfgFile pool poolConfig.config; - iniFile = phpIni poolConfig; + cfgFile = fpmCfgFile pool poolOpts; + iniFile = phpIni poolOpts; in { Slice = "phpfpm.slice"; PrivateDevices = true; @@ -168,10 +268,12 @@ in { # 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 = "${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"; + RuntimeDirectory = "phpfpm"; + RuntimeDirectoryPreserve = true; # Relevant when multiple processes are running }; } - ); + ) cfg.pools; }; } diff --git a/nixos/modules/services/web-servers/phpfpm/pool-options.nix b/nixos/modules/services/web-servers/phpfpm/pool-options.nix deleted file mode 100644 index d9ad7eff71f2c..0000000000000 --- a/nixos/modules/services/web-servers/phpfpm/pool-options.nix +++ /dev/null @@ -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. - ''; - }; - }; -} - |