diff --git a/nixos/modules/services/monitoring/nagios.nix b/nixos/modules/services/monitoring/nagios.nix index 3ca79dddaf5..9ac6869068f 100644 --- a/nixos/modules/services/monitoring/nagios.nix +++ b/nixos/modules/services/monitoring/nagios.nix @@ -154,7 +154,7 @@ in }; virtualHost = mkOption { - type = types.submodule (import ../web-servers/apache-httpd/per-server-options.nix); + type = types.submodule (import ../web-servers/apache-httpd/vhost-options.nix); example = literalExample '' { hostName = "example.org"; adminAddr = "webmaster@example.org"; diff --git a/nixos/modules/services/web-apps/limesurvey.nix b/nixos/modules/services/web-apps/limesurvey.nix index e00a47191c6..56265e80957 100644 --- a/nixos/modules/services/web-apps/limesurvey.nix +++ b/nixos/modules/services/web-apps/limesurvey.nix @@ -100,7 +100,7 @@ in }; virtualHost = mkOption { - type = types.submodule (import ../web-servers/apache-httpd/per-server-options.nix); + type = types.submodule (import ../web-servers/apache-httpd/vhost-options.nix); example = literalExample '' { hostName = "survey.example.org"; diff --git a/nixos/modules/services/web-apps/mediawiki.nix b/nixos/modules/services/web-apps/mediawiki.nix index 8a109b39bb5..e9ed53857d8 100644 --- a/nixos/modules/services/web-apps/mediawiki.nix +++ b/nixos/modules/services/web-apps/mediawiki.nix @@ -290,7 +290,7 @@ in }; virtualHost = mkOption { - type = types.submodule (import ../web-servers/apache-httpd/per-server-options.nix); + type = types.submodule (import ../web-servers/apache-httpd/vhost-options.nix); example = literalExample '' { hostName = "mediawiki.example.org"; diff --git a/nixos/modules/services/web-apps/moodle.nix b/nixos/modules/services/web-apps/moodle.nix index 595d070d940..1196780cf6e 100644 --- a/nixos/modules/services/web-apps/moodle.nix +++ b/nixos/modules/services/web-apps/moodle.nix @@ -140,7 +140,7 @@ in }; virtualHost = mkOption { - type = types.submodule (import ../web-servers/apache-httpd/per-server-options.nix); + type = types.submodule (import ../web-servers/apache-httpd/vhost-options.nix); example = literalExample '' { hostName = "moodle.example.org"; diff --git a/nixos/modules/services/web-apps/wordpress.nix b/nixos/modules/services/web-apps/wordpress.nix index ad4f39fbf52..c48a4409737 100644 --- a/nixos/modules/services/web-apps/wordpress.nix +++ b/nixos/modules/services/web-apps/wordpress.nix @@ -209,7 +209,7 @@ let }; virtualHost = mkOption { - type = types.submodule (import ../web-servers/apache-httpd/per-server-options.nix); + type = types.submodule (import ../web-servers/apache-httpd/vhost-options.nix); example = literalExample '' { adminAddr = "webmaster@example.org"; diff --git a/nixos/modules/services/web-apps/zabbix.nix b/nixos/modules/services/web-apps/zabbix.nix index ee8447810c6..00719512834 100644 --- a/nixos/modules/services/web-apps/zabbix.nix +++ b/nixos/modules/services/web-apps/zabbix.nix @@ -113,7 +113,7 @@ in }; virtualHost = mkOption { - type = types.submodule (import ../web-servers/apache-httpd/per-server-options.nix); + type = types.submodule (import ../web-servers/apache-httpd/vhost-options.nix); example = literalExample '' { hostName = "zabbix.example.org"; diff --git a/nixos/modules/services/web-servers/apache-httpd/default.nix b/nixos/modules/services/web-servers/apache-httpd/default.nix index 9942c63acce..2452ca20b05 100644 --- a/nixos/modules/services/web-servers/apache-httpd/default.nix +++ b/nixos/modules/services/web-servers/apache-httpd/default.nix @@ -4,21 +4,21 @@ with lib; let - mainCfg = config.services.httpd; + cfg = config.services.httpd; runtimeDir = "/run/httpd"; - httpd = mainCfg.package.out; + pkg = cfg.package.out; - httpdConf = mainCfg.configFile; + httpdConf = cfg.configFile; - php = mainCfg.phpPackage.override { apacheHttpd = httpd.dev; /* otherwise it only gets .out */ }; + php = cfg.phpPackage.override { apacheHttpd = pkg.dev; /* otherwise it only gets .out */ }; phpMajorVersion = lib.versions.major (lib.getVersion php); - mod_perl = pkgs.apacheHttpdPackages.mod_perl.override { apacheHttpd = httpd; }; + mod_perl = pkgs.apacheHttpdPackages.mod_perl.override { apacheHttpd = pkg; }; - vhosts = attrValues mainCfg.virtualHosts; + vhosts = attrValues cfg.virtualHosts; mkListenInfo = hostOpts: if hostOpts.listen != [] then hostOpts.listen @@ -41,23 +41,18 @@ let "mime" "autoindex" "negotiation" "dir" "alias" "rewrite" "unixd" "slotmem_shm" "socache_shmcb" - "mpm_${mainCfg.multiProcessingModule}" + "mpm_${cfg.multiProcessingModule}" ] - ++ (if mainCfg.multiProcessingModule == "prefork" then [ "cgi" ] else [ "cgid" ]) + ++ (if cfg.multiProcessingModule == "prefork" then [ "cgi" ] else [ "cgid" ]) ++ optional enableSSL "ssl" ++ optional enableUserDir "userdir" - ++ optional mainCfg.enableMellon { name = "auth_mellon"; path = "${pkgs.apacheHttpdPackages.mod_auth_mellon}/modules/mod_auth_mellon.so"; } - ++ optional mainCfg.enablePHP { name = "php${phpMajorVersion}"; path = "${php}/modules/libphp${phpMajorVersion}.so"; } - ++ optional mainCfg.enablePerl { name = "perl"; path = "${mod_perl}/modules/mod_perl.so"; } - ++ mainCfg.extraModules; + ++ optional cfg.enableMellon { name = "auth_mellon"; path = "${pkgs.apacheHttpdPackages.mod_auth_mellon}/modules/mod_auth_mellon.so"; } + ++ optional cfg.enablePHP { name = "php${phpMajorVersion}"; path = "${php}/modules/libphp${phpMajorVersion}.so"; } + ++ optional cfg.enablePerl { name = "perl"; path = "${mod_perl}/modules/mod_perl.so"; } + ++ cfg.extraModules; - - allDenied = "Require all denied"; - allGranted = "Require all granted"; - - - loggingConf = (if mainCfg.logFormat != "none" then '' - ErrorLog ${mainCfg.logDir}/error.log + loggingConf = (if cfg.logFormat != "none" then '' + ErrorLog ${cfg.logDir}/error.log LogLevel notice @@ -66,7 +61,7 @@ let LogFormat "%{Referer}i -> %U" referer LogFormat "%{User-agent}i" agent - CustomLog ${mainCfg.logDir}/access.log ${mainCfg.logFormat} + CustomLog ${cfg.logDir}/access.log ${cfg.logFormat} '' else '' ErrorLog /dev/null ''); @@ -88,34 +83,36 @@ let sslConf = '' - SSLSessionCache shmcb:${runtimeDir}/ssl_scache(512000) + + SSLSessionCache shmcb:${runtimeDir}/ssl_scache(512000) - Mutex posixsem + Mutex posixsem - SSLRandomSeed startup builtin - SSLRandomSeed connect builtin + SSLRandomSeed startup builtin + SSLRandomSeed connect builtin - SSLProtocol ${mainCfg.sslProtocols} - SSLCipherSuite ${mainCfg.sslCiphers} - SSLHonorCipherOrder on + SSLProtocol ${cfg.sslProtocols} + SSLCipherSuite ${cfg.sslCiphers} + SSLHonorCipherOrder on + ''; mimeConf = '' - TypesConfig ${httpd}/conf/mime.types + TypesConfig ${pkg}/conf/mime.types AddType application/x-x509-ca-cert .crt AddType application/x-pkcs7-crl .crl AddType application/x-httpd-php .php .phtml - MIMEMagicFile ${httpd}/conf/magic + MIMEMagicFile ${pkg}/conf/magic ''; mkVHostConf = hostOpts: let - adminAddr = if hostOpts.adminAddr != null then hostOpts.adminAddr else mainCfg.adminAddr; + adminAddr = if hostOpts.adminAddr != null then hostOpts.adminAddr else cfg.adminAddr; listen = filter (listen: !listen.ssl) (mkListenInfo hostOpts); listenSSL = filter (listen: listen.ssl) (mkListenInfo hostOpts); @@ -203,9 +200,9 @@ let '') (sortProperties (mapAttrsToList (k: v: v // { location = k; }) locations))); in '' - ${optionalString mainCfg.logPerVirtualHost '' - ErrorLog ${mainCfg.logDir}/error-${hostOpts.hostName}.log - CustomLog ${mainCfg.logDir}/access-${hostOpts.hostName}.log ${hostOpts.logFormat} + ${optionalString cfg.logPerVirtualHost '' + ErrorLog ${cfg.logDir}/error-${hostOpts.hostName}.log + CustomLog ${cfg.logDir}/access-${hostOpts.hostName}.log ${hostOpts.logFormat} ''} ${optionalString (hostOpts.robotsEntries != "") '' @@ -217,7 +214,7 @@ let Options Indexes FollowSymLinks AllowOverride None - ${allGranted} + Require all granted ${optionalString hostOpts.enableUserDir '' @@ -244,7 +241,7 @@ let Alias ${elem.urlPath} ${elem.dir}/ Options +Indexes - ${allGranted} + Require all granted AllowOverride All ''; @@ -259,20 +256,20 @@ let confFile = pkgs.writeText "httpd.conf" '' - ServerRoot ${httpd} + ServerRoot ${pkg} ServerName ${config.networking.hostName} DefaultRuntimeDir ${runtimeDir}/runtime PidFile ${runtimeDir}/httpd.pid - ${optionalString (mainCfg.multiProcessingModule != "prefork") '' + ${optionalString (cfg.multiProcessingModule != "prefork") '' # mod_cgid requires this. ScriptSock ${runtimeDir}/cgisock ''} - MaxClients ${toString mainCfg.maxClients} - MaxRequestsPerChild ${toString mainCfg.maxRequestsPerChild} + MaxClients ${toString cfg.maxClients} + MaxRequestsPerChild ${toString cfg.maxRequestsPerChild} ${let @@ -281,12 +278,12 @@ let in concatStringsSep "\n" uniqueListen } - User ${mainCfg.user} - Group ${mainCfg.group} + User ${cfg.user} + Group ${cfg.group} ${let mkModule = module: - if isString module then { name = module; path = "${httpd}/modules/mod_${module}.so"; } + if isString module then { name = module; path = "${pkg}/modules/mod_${module}.so"; } else if isAttrs module then { inherit (module) name path; } else throw "Expecting either a string or attribute set including a name and path."; in @@ -296,37 +293,37 @@ let AddHandler type-map var - ${allDenied} + Require all denied ${mimeConf} ${loggingConf} ${browserHacks} - Include ${httpd}/conf/extra/httpd-default.conf - Include ${httpd}/conf/extra/httpd-autoindex.conf - Include ${httpd}/conf/extra/httpd-multilang-errordoc.conf - Include ${httpd}/conf/extra/httpd-languages.conf + Include ${pkg}/conf/extra/httpd-default.conf + Include ${pkg}/conf/extra/httpd-autoindex.conf + Include ${pkg}/conf/extra/httpd-multilang-errordoc.conf + Include ${pkg}/conf/extra/httpd-languages.conf TraceEnable off - ${if enableSSL then sslConf else ""} + ${sslConf} # Fascist default - deny access to everything. Options FollowSymLinks AllowOverride None - ${allDenied} + Require all denied # But do allow access to files in the store so that we don't have # to generate clauses for every generated file that we # want to serve. - ${allGranted} + Require all granted - ${mainCfg.extraConfig} + ${cfg.extraConfig} ${concatMapStringsSep "\n" mkVHostConf vhosts} ''; @@ -334,7 +331,7 @@ let # Generate the PHP configuration file. Should probably be factored # out into a separate module. phpIni = pkgs.runCommand "php.ini" - { options = mainCfg.phpOptions; + { options = cfg.phpOptions; preferLocalBuild = true; } '' @@ -367,17 +364,13 @@ in (mkRemovedOptionModule [ "services" "httpd" "sslServerKey" ] "Please define a virtual host using `services.httpd.virtualHosts`.") ]; - ###### interface + # interface options = { services.httpd = { - enable = mkOption { - type = types.bool; - default = false; - description = "Whether to enable the Apache HTTP Server."; - }; + enable = mkEnableOption "the Apache HTTP Server"; package = mkOption { type = types.package; @@ -404,7 +397,7 @@ in default = ""; description = '' Configuration lines appended to the generated Apache - configuration file. Note that this mechanism may not work + configuration file. Note that this mechanism will not work when is overridden. ''; }; @@ -419,7 +412,7 @@ in ] ''; description = '' - Additional Apache modules to be used. These can be + Additional Apache modules to be used. These can be specified as a string in the case of modules distributed with Apache, or as an attribute set specifying the name and path of the @@ -458,8 +451,7 @@ in type = types.str; default = "wwwrun"; description = '' - User account under which httpd runs. The account is created - automatically if it doesn't exist. + User account under which httpd runs. ''; }; @@ -467,8 +459,7 @@ in type = types.str; default = "wwwrun"; description = '' - Group under which httpd runs. The account is created - automatically if it doesn't exist. + Group under which httpd runs. ''; }; @@ -476,15 +467,15 @@ in type = types.path; default = "/var/log/httpd"; description = '' - Directory for Apache's log files. It is created automatically. + Directory for Apache's log files. It is created automatically. ''; }; virtualHosts = mkOption { - type = with types; attrsOf (submodule (import ./per-server-options.nix)); + type = with types; attrsOf (submodule (import ./vhost-options.nix)); default = { localhost = { - documentRoot = "${httpd}/htdocs"; + documentRoot = "${pkg}/htdocs"; }; }; example = literalExample '' @@ -540,17 +531,18 @@ in '' date.timezone = "CET" ''; - description = - "Options appended to the PHP configuration file php.ini."; + description = '' + Options appended to the PHP configuration file php.ini. + ''; }; multiProcessingModule = mkOption { - type = types.str; + type = types.enum [ "event" "prefork" "worker" ]; default = "prefork"; example = "worker"; description = '' - Multi-processing module to be used by Apache. Available + Multi-processing module to be used by Apache. Available modules are prefork (the default; handles each request in a separate child process), worker (hybrid approach that starts a @@ -572,8 +564,9 @@ in type = types.int; default = 0; example = 500; - description = - "Maximum number of httpd requests answered per httpd child (prefork), 0 means unlimited"; + description = '' + Maximum number of httpd requests answered per httpd child (prefork), 0 means unlimited. + ''; }; sslCiphers = mkOption { @@ -592,10 +585,9 @@ in }; + # implementation - ###### implementation - - config = mkIf config.services.httpd.enable { + config = mkIf cfg.enable { assertions = [ { @@ -626,30 +618,30 @@ in warnings = mapAttrsToList (name: hostOpts: '' Using config.services.httpd.virtualHosts."${name}".servedFiles is deprecated and will become unsupported in a future release. Your configuration will continue to work as is but please migrate your configuration to config.services.httpd.virtualHosts."${name}".locations before the 20.09 release of NixOS. - '') (filterAttrs (name: hostOpts: hostOpts.servedFiles != []) mainCfg.virtualHosts); + '') (filterAttrs (name: hostOpts: hostOpts.servedFiles != []) cfg.virtualHosts); - users.users = optionalAttrs (mainCfg.user == "wwwrun") { + users.users = optionalAttrs (cfg.user == "wwwrun") { wwwrun = { - group = mainCfg.group; + group = cfg.group; description = "Apache httpd user"; uid = config.ids.uids.wwwrun; }; }; - users.groups = optionalAttrs (mainCfg.group == "wwwrun") { + users.groups = optionalAttrs (cfg.group == "wwwrun") { wwwrun.gid = config.ids.gids.wwwrun; }; security.acme.certs = mapAttrs (name: hostOpts: { - user = mainCfg.user; - group = mkDefault mainCfg.group; - email = if hostOpts.adminAddr != null then hostOpts.adminAddr else mainCfg.adminAddr; + user = cfg.user; + group = mkDefault cfg.group; + email = if hostOpts.adminAddr != null then hostOpts.adminAddr else cfg.adminAddr; webroot = hostOpts.acmeRoot; extraDomains = genAttrs hostOpts.serverAliases (alias: null); postRun = "systemctl reload httpd.service"; - }) (filterAttrs (name: hostOpts: hostOpts.enableACME) mainCfg.virtualHosts); + }) (filterAttrs (name: hostOpts: hostOpts.enableACME) cfg.virtualHosts); - environment.systemPackages = [httpd]; + environment.systemPackages = [ pkg ]; # required for "apachectl configtest" environment.etc."httpd/httpd.conf".source = httpdConf; @@ -700,35 +692,37 @@ in after = [ "network.target" "fs.target" ] ++ map (hostOpts: "acme-selfsigned-${hostOpts.hostName}.service") vhostsACME; path = - [ httpd pkgs.coreutils pkgs.gnugrep ] - ++ optional mainCfg.enablePHP pkgs.system-sendmail; # Needed for PHP's mail() function. + [ pkg pkgs.coreutils pkgs.gnugrep ] + ++ optional cfg.enablePHP pkgs.system-sendmail; # Needed for PHP's mail() function. environment = - optionalAttrs mainCfg.enablePHP { PHPRC = phpIni; } - // optionalAttrs mainCfg.enableMellon { LD_LIBRARY_PATH = "${pkgs.xmlsec}/lib"; }; + optionalAttrs cfg.enablePHP { PHPRC = phpIni; } + // optionalAttrs cfg.enableMellon { LD_LIBRARY_PATH = "${pkgs.xmlsec}/lib"; }; preStart = '' - mkdir -m 0700 -p ${mainCfg.logDir} + mkdir -m 0700 -p ${cfg.logDir} # Get rid of old semaphores. These tend to accumulate across # server restarts, eventually preventing it from restarting # successfully. - for i in $(${pkgs.utillinux}/bin/ipcs -s | grep ' ${mainCfg.user} ' | cut -f2 -d ' '); do + for i in $(${pkgs.utillinux}/bin/ipcs -s | grep ' ${cfg.user} ' | cut -f2 -d ' '); do ${pkgs.utillinux}/bin/ipcrm -s $i done ''; - serviceConfig.ExecStart = "@${httpd}/bin/httpd httpd -f ${httpdConf}"; - serviceConfig.ExecStop = "${httpd}/bin/httpd -f ${httpdConf} -k graceful-stop"; - serviceConfig.ExecReload = "${httpd}/bin/httpd -f ${httpdConf} -k graceful"; - serviceConfig.Group = mainCfg.group; - serviceConfig.Type = "forking"; - serviceConfig.PIDFile = "${runtimeDir}/httpd.pid"; - serviceConfig.Restart = "always"; - serviceConfig.RestartSec = "5s"; - serviceConfig.RuntimeDirectory = "httpd httpd/runtime"; - serviceConfig.RuntimeDirectoryMode = "0750"; + serviceConfig = { + ExecStart = "@${pkg}/bin/httpd httpd -f ${httpdConf}"; + ExecStop = "${pkg}/bin/httpd -f ${httpdConf} -k graceful-stop"; + ExecReload = "${pkg}/bin/httpd -f ${httpdConf} -k graceful"; + Group = cfg.group; + Type = "forking"; + PIDFile = "${runtimeDir}/httpd.pid"; + Restart = "always"; + RestartSec = "5s"; + RuntimeDirectory = "httpd httpd/runtime"; + RuntimeDirectoryMode = "0750"; + }; }; }; diff --git a/nixos/modules/services/web-servers/apache-httpd/per-server-options.nix b/nixos/modules/services/web-servers/apache-httpd/vhost-options.nix similarity index 100% rename from nixos/modules/services/web-servers/apache-httpd/per-server-options.nix rename to nixos/modules/services/web-servers/apache-httpd/vhost-options.nix