aboutsummaryrefslogtreecommitdiff
path: root/nixpkgs/nixos/modules/services/web-servers/apache-httpd/default.nix
diff options
context:
space:
mode:
Diffstat (limited to 'nixpkgs/nixos/modules/services/web-servers/apache-httpd/default.nix')
-rw-r--r--nixpkgs/nixos/modules/services/web-servers/apache-httpd/default.nix210
1 files changed, 107 insertions, 103 deletions
diff --git a/nixpkgs/nixos/modules/services/web-servers/apache-httpd/default.nix b/nixpkgs/nixos/modules/services/web-servers/apache-httpd/default.nix
index 9942c63acce..832c8b30ee9 100644
--- a/nixpkgs/nixos/modules/services/web-servers/apache-httpd/default.nix
+++ b/nixpkgs/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
@@ -29,8 +29,8 @@ let
listenInfo = unique (concatMap mkListenInfo vhosts);
+ enableHttp2 = any (vhost: vhost.http2) vhosts;
enableSSL = any (listen: listen.ssl) listenInfo;
-
enableUserDir = any (vhost: vhost.enableUserDir) vhosts;
# NOTE: generally speaking order of modules is very important
@@ -41,23 +41,19 @@ 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 enableHttp2 "http2"
++ 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;
-
-
- allDenied = "Require all denied";
- allGranted = "Require all granted";
+ ++ 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;
-
- 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 +62,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 +84,36 @@ let
sslConf = ''
- SSLSessionCache shmcb:${runtimeDir}/ssl_scache(512000)
+ <IfModule mod_ssl.c>
+ 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
+ </IfModule>
'';
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
<IfModule mod_mime_magic.c>
- MIMEMagicFile ${httpd}/conf/magic
+ MIMEMagicFile ${pkg}/conf/magic
</IfModule>
'';
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);
@@ -167,6 +165,7 @@ let
SSLCertificateFile ${sslServerCert}
SSLCertificateKeyFile ${sslServerKey}
${optionalString (sslServerChain != null) "SSLCertificateChainFile ${sslServerChain}"}
+ ${optionalString hostOpts.http2 "Protocols h2 h2c http/1.1"}
${acmeChallenge}
${mkVHostCommonConf hostOpts}
</VirtualHost>
@@ -203,9 +202,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 +216,7 @@ let
<Directory "${documentRoot}">
Options Indexes FollowSymLinks
AllowOverride None
- ${allGranted}
+ Require all granted
</Directory>
${optionalString hostOpts.enableUserDir ''
@@ -244,7 +243,7 @@ let
Alias ${elem.urlPath} ${elem.dir}/
<Directory ${elem.dir}>
Options +Indexes
- ${allGranted}
+ Require all granted
AllowOverride All
</Directory>
'';
@@ -259,20 +258,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
''}
<IfModule prefork.c>
- MaxClients ${toString mainCfg.maxClients}
- MaxRequestsPerChild ${toString mainCfg.maxRequestsPerChild}
+ MaxClients ${toString cfg.maxClients}
+ MaxRequestsPerChild ${toString cfg.maxRequestsPerChild}
</IfModule>
${let
@@ -281,12 +280,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 +295,37 @@ let
AddHandler type-map var
<Files ~ "^\.ht">
- ${allDenied}
+ Require all denied
</Files>
${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.
<Directory />
Options FollowSymLinks
AllowOverride None
- ${allDenied}
+ Require all denied
</Directory>
# But do allow access to files in the store so that we don't have
# to generate <Directory> clauses for every generated file that we
# want to serve.
<Directory /nix/store>
- ${allGranted}
+ Require all granted
</Directory>
- ${mainCfg.extraConfig}
+ ${cfg.extraConfig}
${concatMapStringsSep "\n" mkVHostConf vhosts}
'';
@@ -334,7 +333,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 +366,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 +399,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 <option>configFile</option> is overridden.
'';
};
@@ -419,7 +414,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
<varname>name</varname> and <varname>path</varname> of the
@@ -458,8 +453,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 +461,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 +469,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 +533,18 @@ in
''
date.timezone = "CET"
'';
- description =
- "Options appended to the PHP configuration file <filename>php.ini</filename>.";
+ description = ''
+ Options appended to the PHP configuration file <filename>php.ini</filename>.
+ '';
};
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 <literal>prefork</literal> (the default;
handles each request in a separate child process),
<literal>worker</literal> (hybrid approach that starts a
@@ -572,8 +566,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 +587,9 @@ in
};
+ # implementation
- ###### implementation
-
- config = mkIf config.services.httpd.enable {
+ config = mkIf cfg.enable {
assertions = [
{
@@ -626,30 +620,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;
@@ -689,6 +683,15 @@ in
"access_compat"
];
+ systemd.tmpfiles.rules =
+ let
+ svc = config.systemd.services.httpd.serviceConfig;
+ in
+ [
+ "d '${cfg.logDir}' 0700 ${svc.User} ${svc.Group}"
+ "Z '${cfg.logDir}' - ${svc.User} ${svc.Group}"
+ ];
+
systemd.services.httpd =
let
vhostsACME = filter (hostOpts: hostOpts.enableACME) vhosts;
@@ -700,35 +703,36 @@ 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}
-
# 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";
+ User = "root";
+ Group = cfg.group;
+ Type = "forking";
+ PIDFile = "${runtimeDir}/httpd.pid";
+ Restart = "always";
+ RestartSec = "5s";
+ RuntimeDirectory = "httpd httpd/runtime";
+ RuntimeDirectoryMode = "0750";
+ };
};
};