diff options
author | Ismaël Bouya <ismael.bouya@normalesup.org> | 2019-01-10 20:56:44 +0100 |
---|---|---|
committer | Ismaël Bouya <ismael.bouya@normalesup.org> | 2019-01-10 21:02:06 +0100 |
commit | f8bde3d6d31da84b5e81bdfc4f96efdf6bec3df2 (patch) | |
tree | cc29816c7f448d736ca0ac6b24763fca4bb48332 | |
parent | 42429ef0756d9ee41cf0ff0b38210edb3b1637e5 (diff) | |
download | Nix-f8bde3d6d31da84b5e81bdfc4f96efdf6bec3df2.tar.gz Nix-f8bde3d6d31da84b5e81bdfc4f96efdf6bec3df2.tar.zst Nix-f8bde3d6d31da84b5e81bdfc4f96efdf6bec3df2.zip |
Add http configuration to modules and separate production from
integration
-rw-r--r-- | virtual/eldiron.nix | 57 | ||||
-rw-r--r-- | virtual/modules/websites.nix | 81 | ||||
-rw-r--r-- | virtual/modules/websites/apache/httpd_inte.nix | 722 | ||||
-rw-r--r-- | virtual/modules/websites/apache/httpd_prod.nix | 722 | ||||
-rw-r--r-- | virtual/modules/websites/apache/per-server-options.nix | 188 | ||||
-rw-r--r-- | virtual/modules/websites/aten.nix | 15 | ||||
-rw-r--r-- | virtual/modules/websites/chloe.nix | 16 | ||||
-rw-r--r-- | virtual/modules/websites/connexionswing.nix | 16 | ||||
-rw-r--r-- | virtual/modules/websites/ludivine.nix | 15 | ||||
-rw-r--r-- | virtual/modules/websites/piedsjaloux.nix | 16 |
10 files changed, 1792 insertions, 56 deletions
diff --git a/virtual/eldiron.nix b/virtual/eldiron.nix index efaa068..a1e6909 100644 --- a/virtual/eldiron.nix +++ b/virtual/eldiron.nix | |||
@@ -4,7 +4,7 @@ | |||
4 | enableRollback = true; | 4 | enableRollback = true; |
5 | }; | 5 | }; |
6 | 6 | ||
7 | eldiron = { config, pkgs, mylibs, ... }: | 7 | eldiron = { config, pkgs, mylibs, myconfig, ... }: |
8 | with mylibs; | 8 | with mylibs; |
9 | let | 9 | let |
10 | mypkgs = pkgs.callPackage ./packages.nix { | 10 | mypkgs = pkgs.callPackage ./packages.nix { |
@@ -14,6 +14,13 @@ | |||
14 | { | 14 | { |
15 | _module.args = { | 15 | _module.args = { |
16 | mylibs = import ../libs.nix; | 16 | mylibs = import ../libs.nix; |
17 | myconfig = { | ||
18 | ips = { | ||
19 | main = "176.9.151.89"; | ||
20 | production = "176.9.151.154"; | ||
21 | integration = "176.9.151.155"; | ||
22 | }; | ||
23 | }; | ||
17 | }; | 24 | }; |
18 | 25 | ||
19 | imports = [ | 26 | imports = [ |
@@ -47,6 +54,11 @@ | |||
47 | enable = true; | 54 | enable = true; |
48 | allowedTCPPorts = [ 22 80 443 9418 ]; | 55 | allowedTCPPorts = [ 22 80 443 9418 ]; |
49 | }; | 56 | }; |
57 | interfaces."eth0".ipv4.addresses = [ | ||
58 | # 176.9.151.89 declared in nixops -> infra / tools | ||
59 | { address = myconfig.ips.production; prefixLength = 32; } | ||
60 | { address = myconfig.ips.integration; prefixLength = 32; } | ||
61 | ]; | ||
50 | }; | 62 | }; |
51 | 63 | ||
52 | deployment = { | 64 | deployment = { |
@@ -54,7 +66,7 @@ | |||
54 | hetzner = { | 66 | hetzner = { |
55 | #robotUser = "defined in HETZNER_ROBOT_USER"; | 67 | #robotUser = "defined in HETZNER_ROBOT_USER"; |
56 | #robotPass = "defined in HETZNER_ROBOT_PASS"; | 68 | #robotPass = "defined in HETZNER_ROBOT_PASS"; |
57 | mainIPv4 = "176.9.151.89"; | 69 | mainIPv4 = myconfig.ips.main; |
58 | partitions = '' | 70 | partitions = '' |
59 | clearpart --all --initlabel --drives=sda,sdb | 71 | clearpart --all --initlabel --drives=sda,sdb |
60 | 72 | ||
@@ -138,7 +150,6 @@ | |||
138 | install -d -m 0750 -o wwwrun -g wwwrun /var/lib/php/sessions | 150 | install -d -m 0750 -o wwwrun -g wwwrun /var/lib/php/sessions |
139 | install -d -m 0750 -o wwwrun -g wwwrun /var/lib/php/sessions/adminer | 151 | install -d -m 0750 -o wwwrun -g wwwrun /var/lib/php/sessions/adminer |
140 | install -d -m 0750 -o wwwrun -g wwwrun /var/lib/php/sessions/mantisbt | 152 | install -d -m 0750 -o wwwrun -g wwwrun /var/lib/php/sessions/mantisbt |
141 | install -d -m 0750 -o wwwrun -g wwwrun /var/lib/php/sessions/ttrss | ||
142 | install -d -m 0750 -o wwwrun -g wwwrun /var/lib/php/sessions/davical | 153 | install -d -m 0750 -o wwwrun -g wwwrun /var/lib/php/sessions/davical |
143 | ''; | 154 | ''; |
144 | # FIXME: initial sync | 155 | # FIXME: initial sync |
@@ -187,7 +198,9 @@ | |||
187 | sslServerKey = "/var/lib/acme/${domain}/key.pem"; | 198 | sslServerKey = "/var/lib/acme/${domain}/key.pem"; |
188 | sslServerChain = "/var/lib/acme/${domain}/fullchain.pem"; | 199 | sslServerChain = "/var/lib/acme/${domain}/fullchain.pem"; |
189 | logFormat = "combinedVhost"; | 200 | logFormat = "combinedVhost"; |
190 | listen = [ { ip = "*"; port = 443; } ]; | 201 | listen = [ |
202 | { ip = "176.9.151.89"; port = 443; } | ||
203 | ]; | ||
191 | }; | 204 | }; |
192 | apacheConfig = config.services.myWebsites.apacheConfig; | 205 | apacheConfig = config.services.myWebsites.apacheConfig; |
193 | in rec { | 206 | in rec { |
@@ -240,14 +253,6 @@ | |||
240 | mypkgs.davical.apache.vhostConf | 253 | mypkgs.davical.apache.vhostConf |
241 | ]; | 254 | ]; |
242 | }) | 255 | }) |
243 | (withConf "eldiron" // { | ||
244 | hostName = "connexionswing.immae.eu"; | ||
245 | serverAliases = [ "sandetludo.immae.eu" ]; | ||
246 | documentRoot = mypkgs.connexionswing_dev.webRoot; | ||
247 | extraConfig = builtins.concatStringsSep "\n" [ | ||
248 | mypkgs.connexionswing_dev.apache.vhostConf | ||
249 | ]; | ||
250 | }) | ||
251 | (withConf "connexionswing" // { | 256 | (withConf "connexionswing" // { |
252 | hostName = "connexionswing.com"; | 257 | hostName = "connexionswing.com"; |
253 | serverAliases = [ "sandetludo.com" "www.connexionswing.com" "www.sandetludo.com" ]; | 258 | serverAliases = [ "sandetludo.com" "www.connexionswing.com" "www.sandetludo.com" ]; |
@@ -256,13 +261,6 @@ | |||
256 | mypkgs.connexionswing_prod.apache.vhostConf | 261 | mypkgs.connexionswing_prod.apache.vhostConf |
257 | ]; | 262 | ]; |
258 | }) | 263 | }) |
259 | (withConf "eldiron" // { | ||
260 | hostName = "ludivine.immae.eu"; | ||
261 | documentRoot = mypkgs.ludivinecassal_dev.webRoot; | ||
262 | extraConfig = builtins.concatStringsSep "\n" [ | ||
263 | mypkgs.ludivinecassal_dev.apache.vhostConf | ||
264 | ]; | ||
265 | }) | ||
266 | (withConf "ludivinecassal" // { | 264 | (withConf "ludivinecassal" // { |
267 | hostName = "ludivinecassal.com"; | 265 | hostName = "ludivinecassal.com"; |
268 | serverAliases = [ "www.ludivinecassal.com" ]; | 266 | serverAliases = [ "www.ludivinecassal.com" ]; |
@@ -271,13 +269,6 @@ | |||
271 | mypkgs.ludivinecassal_prod.apache.vhostConf | 269 | mypkgs.ludivinecassal_prod.apache.vhostConf |
272 | ]; | 270 | ]; |
273 | }) | 271 | }) |
274 | (withConf "eldiron" // { | ||
275 | hostName = "piedsjaloux.immae.eu"; | ||
276 | documentRoot = mypkgs.piedsjaloux_dev.webRoot; | ||
277 | extraConfig = builtins.concatStringsSep "\n" [ | ||
278 | mypkgs.piedsjaloux_dev.apache.vhostConf | ||
279 | ]; | ||
280 | }) | ||
281 | (withConf "piedsjaloux" // { | 272 | (withConf "piedsjaloux" // { |
282 | hostName = "piedsjaloux.fr"; | 273 | hostName = "piedsjaloux.fr"; |
283 | serverAliases = [ "www.piedsjaloux.fr" ]; | 274 | serverAliases = [ "www.piedsjaloux.fr" ]; |
@@ -286,13 +277,6 @@ | |||
286 | mypkgs.piedsjaloux_prod.apache.vhostConf | 277 | mypkgs.piedsjaloux_prod.apache.vhostConf |
287 | ]; | 278 | ]; |
288 | }) | 279 | }) |
289 | (withConf "eldiron" // { | ||
290 | hostName = "chloe.immae.eu"; | ||
291 | documentRoot = mypkgs.chloe_dev.webRoot; | ||
292 | extraConfig = builtins.concatStringsSep "\n" [ | ||
293 | mypkgs.chloe_dev.apache.vhostConf | ||
294 | ]; | ||
295 | }) | ||
296 | (withConf "chloe" // { | 280 | (withConf "chloe" // { |
297 | hostName = "osteopathe-cc.fr"; | 281 | hostName = "osteopathe-cc.fr"; |
298 | serverAliases = [ "www.osteopathe-cc.fr" ]; | 282 | serverAliases = [ "www.osteopathe-cc.fr" ]; |
@@ -301,13 +285,6 @@ | |||
301 | mypkgs.chloe_prod.apache.vhostConf | 285 | mypkgs.chloe_prod.apache.vhostConf |
302 | ]; | 286 | ]; |
303 | }) | 287 | }) |
304 | (withConf "eldiron" // { | ||
305 | hostName = "dev.aten.pro"; | ||
306 | documentRoot = mypkgs.aten_dev.webRoot; | ||
307 | extraConfig = builtins.concatStringsSep "\n" [ | ||
308 | mypkgs.aten_dev.apache.vhostConf | ||
309 | ]; | ||
310 | }) | ||
311 | (withConf "aten" // { | 288 | (withConf "aten" // { |
312 | hostName = "aten.pro"; | 289 | hostName = "aten.pro"; |
313 | serverAliases = [ "www.aten.pro" ]; | 290 | serverAliases = [ "www.aten.pro" ]; |
diff --git a/virtual/modules/websites.nix b/virtual/modules/websites.nix index 62f45d9..cbd7de0 100644 --- a/virtual/modules/websites.nix +++ b/virtual/modules/websites.nix | |||
@@ -1,6 +1,61 @@ | |||
1 | { lib, pkgs, config, mylibs, ... }: | 1 | { lib, pkgs, config, mylibs, myconfig, ... }: |
2 | let | 2 | let |
3 | cfg = config.services.myWebsites; | 3 | cfg = config.services.myWebsites; |
4 | makeService = name: cfg: let | ||
5 | toVhost = vhostConf: { | ||
6 | enableSSL = true; | ||
7 | sslServerCert = "/var/lib/acme/${vhostConf.certName}/cert.pem"; | ||
8 | sslServerKey = "/var/lib/acme/${vhostConf.certName}/key.pem"; | ||
9 | sslServerChain = "/var/lib/acme/${vhostConf.certName}/fullchain.pem"; | ||
10 | logFormat = "combinedVhost"; | ||
11 | listen = [ | ||
12 | { ip = cfg.ip; port = 443; } | ||
13 | ]; | ||
14 | hostName = builtins.head vhostConf.hosts; | ||
15 | serverAliases = builtins.tail vhostConf.hosts or []; | ||
16 | documentRoot = vhostConf.root; | ||
17 | extraConfig = builtins.concatStringsSep "\n" vhostConf.extraConfig; | ||
18 | }; | ||
19 | in rec { | ||
20 | enable = true; | ||
21 | listen = [ | ||
22 | { ip = cfg.ip; port = 443; } | ||
23 | ]; | ||
24 | stateDir = "/run/httpd_${name}"; | ||
25 | logPerVirtualHost = true; | ||
26 | multiProcessingModule = "worker"; | ||
27 | adminAddr = "httpd@immae.eu"; | ||
28 | logFormat = "combinedVhost"; | ||
29 | extraModules = pkgs.lib.lists.unique (pkgs.lib.lists.flatten cfg.modules); | ||
30 | extraConfig = builtins.concatStringsSep "\n" cfg.extraConfig; | ||
31 | virtualHosts = pkgs.lib.attrsets.mapAttrsToList (n: v: toVhost v) cfg.vhostConfs; | ||
32 | }; | ||
33 | makeServiceOptions = name: ip: { | ||
34 | enable = lib.mkEnableOption "enable websites in ${name}"; | ||
35 | ip = lib.mkOption { | ||
36 | type = lib.types.string; | ||
37 | default = ip; | ||
38 | description = "${name} ip to listen to"; | ||
39 | }; | ||
40 | modules = lib.mkOption { | ||
41 | type = lib.types.listOf (lib.types.str); | ||
42 | default = []; | ||
43 | }; | ||
44 | extraConfig = lib.mkOption { | ||
45 | type = lib.types.listOf (lib.types.lines); | ||
46 | default = []; | ||
47 | }; | ||
48 | vhostConfs = lib.mkOption { | ||
49 | type = lib.types.attrsOf (lib.types.submodule { | ||
50 | options = { | ||
51 | certName = lib.mkOption { type = lib.types.string; }; | ||
52 | hosts = lib.mkOption { type = lib.types.listOf lib.types.string; }; | ||
53 | root = lib.mkOption { type = lib.types.nullOr lib.types.path; }; | ||
54 | extraConfig = lib.mkOption { type = lib.types.listOf lib.types.lines; default = []; }; | ||
55 | }; | ||
56 | }); | ||
57 | }; | ||
58 | }; | ||
4 | in | 59 | in |
5 | { | 60 | { |
6 | imports = [ | 61 | imports = [ |
@@ -9,16 +64,16 @@ in | |||
9 | ./websites/aten.nix | 64 | ./websites/aten.nix |
10 | ./websites/piedsjaloux.nix | 65 | ./websites/piedsjaloux.nix |
11 | ./websites/connexionswing.nix | 66 | ./websites/connexionswing.nix |
67 | # built using: | ||
68 | # sed -e "s/services\.httpd/services\.httpdProd/g" .nix-defexpr/channels/nixpkgs/nixos/modules/services/web-servers/apache-httpd/default.nix | ||
69 | # And removed users / groups | ||
70 | ./websites/apache/httpd_prod.nix | ||
71 | ./websites/apache/httpd_inte.nix | ||
12 | ]; | 72 | ]; |
13 | 73 | ||
14 | options.services.myWebsites = { | 74 | options.services.myWebsites = { |
15 | production = { | 75 | production = makeServiceOptions "production" myconfig.ips.production; |
16 | enable = lib.mkEnableOption "enable websites in production"; | 76 | integration = makeServiceOptions "integration" myconfig.ips.integration; |
17 | }; | ||
18 | |||
19 | integration = { | ||
20 | enable = lib.mkEnableOption "enable websites in integration"; | ||
21 | }; | ||
22 | 77 | ||
23 | apacheConfig = lib.mkOption { | 78 | apacheConfig = lib.mkOption { |
24 | type = lib.types.attrsOf (lib.types.submodule { | 79 | type = lib.types.attrsOf (lib.types.submodule { |
@@ -111,5 +166,15 @@ in | |||
111 | ''; | 166 | ''; |
112 | }; | 167 | }; |
113 | }; | 168 | }; |
169 | |||
170 | # FIXME: logrotate | ||
171 | # FIXME: ipv6 | ||
172 | services.httpdProd = makeService "production" config.services.myWebsites.production; | ||
173 | services.myWebsites.production.modules = pkgs.lib.lists.flatten (pkgs.lib.attrsets.mapAttrsToList (n: v: v.modules or []) cfg.apacheConfig); | ||
174 | services.myWebsites.production.extraConfig = (builtins.filter (x: x != null) (pkgs.lib.attrsets.mapAttrsToList (n: v: v.extraConfig or null) cfg.apacheConfig)); | ||
175 | |||
176 | services.httpdInte = makeService "integration" config.services.myWebsites.integration; | ||
177 | services.myWebsites.integration.modules = pkgs.lib.lists.flatten (pkgs.lib.attrsets.mapAttrsToList (n: v: v.modules or []) cfg.apacheConfig); | ||
178 | services.myWebsites.integration.extraConfig = (builtins.filter (x: x != null) (pkgs.lib.attrsets.mapAttrsToList (n: v: v.extraConfig or null) cfg.apacheConfig)); | ||
114 | }; | 179 | }; |
115 | } | 180 | } |
diff --git a/virtual/modules/websites/apache/httpd_inte.nix b/virtual/modules/websites/apache/httpd_inte.nix new file mode 100644 index 0000000..83d8ab8 --- /dev/null +++ b/virtual/modules/websites/apache/httpd_inte.nix | |||
@@ -0,0 +1,722 @@ | |||
1 | { config, lib, pkgs, ... }: | ||
2 | |||
3 | with lib; | ||
4 | |||
5 | let | ||
6 | |||
7 | mainCfg = config.services.httpdInte; | ||
8 | |||
9 | httpd = mainCfg.package.out; | ||
10 | |||
11 | version24 = !versionOlder httpd.version "2.4"; | ||
12 | |||
13 | httpdConf = mainCfg.configFile; | ||
14 | |||
15 | php = mainCfg.phpPackage.override { apacheHttpd = httpd.dev; /* otherwise it only gets .out */ }; | ||
16 | |||
17 | phpMajorVersion = head (splitString "." php.version); | ||
18 | |||
19 | mod_perl = pkgs.apacheHttpdPackages.mod_perl.override { apacheHttpd = httpd; }; | ||
20 | |||
21 | defaultListen = cfg: if cfg.enableSSL | ||
22 | then [{ip = "*"; port = 443;}] | ||
23 | else [{ip = "*"; port = 80;}]; | ||
24 | |||
25 | getListen = cfg: | ||
26 | let list = (lib.optional (cfg.port != 0) {ip = "*"; port = cfg.port;}) ++ cfg.listen; | ||
27 | in if list == [] | ||
28 | then defaultListen cfg | ||
29 | else list; | ||
30 | |||
31 | listenToString = l: "${l.ip}:${toString l.port}"; | ||
32 | |||
33 | extraModules = attrByPath ["extraModules"] [] mainCfg; | ||
34 | extraForeignModules = filter isAttrs extraModules; | ||
35 | extraApacheModules = filter isString extraModules; | ||
36 | |||
37 | |||
38 | makeServerInfo = cfg: { | ||
39 | # Canonical name must not include a trailing slash. | ||
40 | canonicalNames = | ||
41 | let defaultPort = (head (defaultListen cfg)).port; in | ||
42 | map (port: | ||
43 | (if cfg.enableSSL then "https" else "http") + "://" + | ||
44 | cfg.hostName + | ||
45 | (if port != defaultPort then ":${toString port}" else "") | ||
46 | ) (map (x: x.port) (getListen cfg)); | ||
47 | |||
48 | # Admin address: inherit from the main server if not specified for | ||
49 | # a virtual host. | ||
50 | adminAddr = if cfg.adminAddr != null then cfg.adminAddr else mainCfg.adminAddr; | ||
51 | |||
52 | vhostConfig = cfg; | ||
53 | serverConfig = mainCfg; | ||
54 | fullConfig = config; # machine config | ||
55 | }; | ||
56 | |||
57 | |||
58 | allHosts = [mainCfg] ++ mainCfg.virtualHosts; | ||
59 | |||
60 | |||
61 | callSubservices = serverInfo: defs: | ||
62 | let f = svc: | ||
63 | let | ||
64 | svcFunction = | ||
65 | if svc ? function then svc.function | ||
66 | # instead of using serviceType="mediawiki"; you can copy mediawiki.nix to any location outside nixpkgs, modify it at will, and use serviceExpression=./mediawiki.nix; | ||
67 | else if svc ? serviceExpression then import (toString svc.serviceExpression) | ||
68 | else import (toString "${toString ./.}/${if svc ? serviceType then svc.serviceType else svc.serviceName}.nix"); | ||
69 | config = (evalModules | ||
70 | { modules = [ { options = res.options; config = svc.config or svc; } ]; | ||
71 | check = false; | ||
72 | }).config; | ||
73 | defaults = { | ||
74 | extraConfig = ""; | ||
75 | extraModules = []; | ||
76 | extraModulesPre = []; | ||
77 | extraPath = []; | ||
78 | extraServerPath = []; | ||
79 | globalEnvVars = []; | ||
80 | robotsEntries = ""; | ||
81 | startupScript = ""; | ||
82 | enablePHP = false; | ||
83 | enablePerl = false; | ||
84 | phpOptions = ""; | ||
85 | options = {}; | ||
86 | documentRoot = null; | ||
87 | }; | ||
88 | res = defaults // svcFunction { inherit config lib pkgs serverInfo php; }; | ||
89 | in res; | ||
90 | in map f defs; | ||
91 | |||
92 | |||
93 | # !!! callSubservices is expensive | ||
94 | subservicesFor = cfg: callSubservices (makeServerInfo cfg) cfg.extraSubservices; | ||
95 | |||
96 | mainSubservices = subservicesFor mainCfg; | ||
97 | |||
98 | allSubservices = mainSubservices ++ concatMap subservicesFor mainCfg.virtualHosts; | ||
99 | |||
100 | |||
101 | enableSSL = any (vhost: vhost.enableSSL) allHosts; | ||
102 | |||
103 | |||
104 | # Names of modules from ${httpd}/modules that we want to load. | ||
105 | apacheModules = | ||
106 | [ # HTTP authentication mechanisms: basic and digest. | ||
107 | "auth_basic" "auth_digest" | ||
108 | |||
109 | # Authentication: is the user who he claims to be? | ||
110 | "authn_file" "authn_dbm" "authn_anon" | ||
111 | (if version24 then "authn_core" else "authn_alias") | ||
112 | |||
113 | # Authorization: is the user allowed access? | ||
114 | "authz_user" "authz_groupfile" "authz_host" | ||
115 | |||
116 | # Other modules. | ||
117 | "ext_filter" "include" "log_config" "env" "mime_magic" | ||
118 | "cern_meta" "expires" "headers" "usertrack" /* "unique_id" */ "setenvif" | ||
119 | "mime" "dav" "status" "autoindex" "asis" "info" "dav_fs" | ||
120 | "vhost_alias" "negotiation" "dir" "imagemap" "actions" "speling" | ||
121 | "userdir" "alias" "rewrite" "proxy" "proxy_http" | ||
122 | ] | ||
123 | ++ optionals version24 [ | ||
124 | "mpm_${mainCfg.multiProcessingModule}" | ||
125 | "authz_core" | ||
126 | "unixd" | ||
127 | "cache" "cache_disk" | ||
128 | "slotmem_shm" | ||
129 | "socache_shmcb" | ||
130 | # For compatibility with old configurations, the new module mod_access_compat is provided. | ||
131 | "access_compat" | ||
132 | ] | ||
133 | ++ (if mainCfg.multiProcessingModule == "prefork" then [ "cgi" ] else [ "cgid" ]) | ||
134 | ++ optional enableSSL "ssl" | ||
135 | ++ extraApacheModules; | ||
136 | |||
137 | |||
138 | allDenied = if version24 then '' | ||
139 | Require all denied | ||
140 | '' else '' | ||
141 | Order deny,allow | ||
142 | Deny from all | ||
143 | ''; | ||
144 | |||
145 | allGranted = if version24 then '' | ||
146 | Require all granted | ||
147 | '' else '' | ||
148 | Order allow,deny | ||
149 | Allow from all | ||
150 | ''; | ||
151 | |||
152 | |||
153 | loggingConf = (if mainCfg.logFormat != "none" then '' | ||
154 | ErrorLog ${mainCfg.logDir}/error_log | ||
155 | |||
156 | LogLevel notice | ||
157 | |||
158 | LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined | ||
159 | LogFormat "%h %l %u %t \"%r\" %>s %b" common | ||
160 | LogFormat "%{Referer}i -> %U" referer | ||
161 | LogFormat "%{User-agent}i" agent | ||
162 | |||
163 | CustomLog ${mainCfg.logDir}/access_log ${mainCfg.logFormat} | ||
164 | '' else '' | ||
165 | ErrorLog /dev/null | ||
166 | ''); | ||
167 | |||
168 | |||
169 | browserHacks = '' | ||
170 | BrowserMatch "Mozilla/2" nokeepalive | ||
171 | BrowserMatch "MSIE 4\.0b2;" nokeepalive downgrade-1.0 force-response-1.0 | ||
172 | BrowserMatch "RealPlayer 4\.0" force-response-1.0 | ||
173 | BrowserMatch "Java/1\.0" force-response-1.0 | ||
174 | BrowserMatch "JDK/1\.0" force-response-1.0 | ||
175 | BrowserMatch "Microsoft Data Access Internet Publishing Provider" redirect-carefully | ||
176 | BrowserMatch "^WebDrive" redirect-carefully | ||
177 | BrowserMatch "^WebDAVFS/1.[012]" redirect-carefully | ||
178 | BrowserMatch "^gnome-vfs" redirect-carefully | ||
179 | ''; | ||
180 | |||
181 | |||
182 | sslConf = '' | ||
183 | SSLSessionCache ${if version24 then "shmcb" else "shm"}:${mainCfg.stateDir}/ssl_scache(512000) | ||
184 | |||
185 | ${if version24 then "Mutex" else "SSLMutex"} posixsem | ||
186 | |||
187 | SSLRandomSeed startup builtin | ||
188 | SSLRandomSeed connect builtin | ||
189 | |||
190 | SSLProtocol All -SSLv2 -SSLv3 | ||
191 | SSLCipherSuite HIGH:!aNULL:!MD5:!EXP | ||
192 | SSLHonorCipherOrder on | ||
193 | ''; | ||
194 | |||
195 | |||
196 | mimeConf = '' | ||
197 | TypesConfig ${httpd}/conf/mime.types | ||
198 | |||
199 | AddType application/x-x509-ca-cert .crt | ||
200 | AddType application/x-pkcs7-crl .crl | ||
201 | AddType application/x-httpd-php .php .phtml | ||
202 | |||
203 | <IfModule mod_mime_magic.c> | ||
204 | MIMEMagicFile ${httpd}/conf/magic | ||
205 | </IfModule> | ||
206 | ''; | ||
207 | |||
208 | |||
209 | perServerConf = isMainServer: cfg: let | ||
210 | |||
211 | serverInfo = makeServerInfo cfg; | ||
212 | |||
213 | subservices = callSubservices serverInfo cfg.extraSubservices; | ||
214 | |||
215 | maybeDocumentRoot = fold (svc: acc: | ||
216 | if acc == null then svc.documentRoot else assert svc.documentRoot == null; acc | ||
217 | ) null ([ cfg ] ++ subservices); | ||
218 | |||
219 | documentRoot = if maybeDocumentRoot != null then maybeDocumentRoot else | ||
220 | pkgs.runCommand "empty" {} "mkdir -p $out"; | ||
221 | |||
222 | documentRootConf = '' | ||
223 | DocumentRoot "${documentRoot}" | ||
224 | |||
225 | <Directory "${documentRoot}"> | ||
226 | Options Indexes FollowSymLinks | ||
227 | AllowOverride None | ||
228 | ${allGranted} | ||
229 | </Directory> | ||
230 | ''; | ||
231 | |||
232 | robotsTxt = | ||
233 | concatStringsSep "\n" (filter (x: x != "") ( | ||
234 | # If this is a vhost, the include the entries for the main server as well. | ||
235 | (if isMainServer then [] else [mainCfg.robotsEntries] ++ map (svc: svc.robotsEntries) mainSubservices) | ||
236 | ++ [cfg.robotsEntries] | ||
237 | ++ (map (svc: svc.robotsEntries) subservices))); | ||
238 | |||
239 | in '' | ||
240 | ${concatStringsSep "\n" (map (n: "ServerName ${n}") serverInfo.canonicalNames)} | ||
241 | |||
242 | ${concatMapStrings (alias: "ServerAlias ${alias}\n") cfg.serverAliases} | ||
243 | |||
244 | ${if cfg.sslServerCert != null then '' | ||
245 | SSLCertificateFile ${cfg.sslServerCert} | ||
246 | SSLCertificateKeyFile ${cfg.sslServerKey} | ||
247 | ${if cfg.sslServerChain != null then '' | ||
248 | SSLCertificateChainFile ${cfg.sslServerChain} | ||
249 | '' else ""} | ||
250 | '' else ""} | ||
251 | |||
252 | ${if cfg.enableSSL then '' | ||
253 | SSLEngine on | ||
254 | '' else if enableSSL then /* i.e., SSL is enabled for some host, but not this one */ | ||
255 | '' | ||
256 | SSLEngine off | ||
257 | '' else ""} | ||
258 | |||
259 | ${if isMainServer || cfg.adminAddr != null then '' | ||
260 | ServerAdmin ${cfg.adminAddr} | ||
261 | '' else ""} | ||
262 | |||
263 | ${if !isMainServer && mainCfg.logPerVirtualHost then '' | ||
264 | ErrorLog ${mainCfg.logDir}/error_log-${cfg.hostName} | ||
265 | CustomLog ${mainCfg.logDir}/access_log-${cfg.hostName} ${cfg.logFormat} | ||
266 | '' else ""} | ||
267 | |||
268 | ${optionalString (robotsTxt != "") '' | ||
269 | Alias /robots.txt ${pkgs.writeText "robots.txt" robotsTxt} | ||
270 | ''} | ||
271 | |||
272 | ${if isMainServer || maybeDocumentRoot != null then documentRootConf else ""} | ||
273 | |||
274 | ${if cfg.enableUserDir then '' | ||
275 | |||
276 | UserDir public_html | ||
277 | UserDir disabled root | ||
278 | |||
279 | <Directory "/home/*/public_html"> | ||
280 | AllowOverride FileInfo AuthConfig Limit Indexes | ||
281 | Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec | ||
282 | <Limit GET POST OPTIONS> | ||
283 | ${allGranted} | ||
284 | </Limit> | ||
285 | <LimitExcept GET POST OPTIONS> | ||
286 | ${allDenied} | ||
287 | </LimitExcept> | ||
288 | </Directory> | ||
289 | |||
290 | '' else ""} | ||
291 | |||
292 | ${if cfg.globalRedirect != null && cfg.globalRedirect != "" then '' | ||
293 | RedirectPermanent / ${cfg.globalRedirect} | ||
294 | '' else ""} | ||
295 | |||
296 | ${ | ||
297 | let makeFileConf = elem: '' | ||
298 | Alias ${elem.urlPath} ${elem.file} | ||
299 | ''; | ||
300 | in concatMapStrings makeFileConf cfg.servedFiles | ||
301 | } | ||
302 | |||
303 | ${ | ||
304 | let makeDirConf = elem: '' | ||
305 | Alias ${elem.urlPath} ${elem.dir}/ | ||
306 | <Directory ${elem.dir}> | ||
307 | Options +Indexes | ||
308 | ${allGranted} | ||
309 | AllowOverride All | ||
310 | </Directory> | ||
311 | ''; | ||
312 | in concatMapStrings makeDirConf cfg.servedDirs | ||
313 | } | ||
314 | |||
315 | ${concatMapStrings (svc: svc.extraConfig) subservices} | ||
316 | |||
317 | ${cfg.extraConfig} | ||
318 | ''; | ||
319 | |||
320 | |||
321 | confFile = pkgs.writeText "httpd.conf" '' | ||
322 | |||
323 | ServerRoot ${httpd} | ||
324 | |||
325 | ${optionalString version24 '' | ||
326 | DefaultRuntimeDir ${mainCfg.stateDir}/runtime | ||
327 | ''} | ||
328 | |||
329 | PidFile ${mainCfg.stateDir}/httpd.pid | ||
330 | |||
331 | ${optionalString (mainCfg.multiProcessingModule != "prefork") '' | ||
332 | # mod_cgid requires this. | ||
333 | ScriptSock ${mainCfg.stateDir}/cgisock | ||
334 | ''} | ||
335 | |||
336 | <IfModule prefork.c> | ||
337 | MaxClients ${toString mainCfg.maxClients} | ||
338 | MaxRequestsPerChild ${toString mainCfg.maxRequestsPerChild} | ||
339 | </IfModule> | ||
340 | |||
341 | ${let | ||
342 | listen = concatMap getListen allHosts; | ||
343 | toStr = listen: "Listen ${listenToString listen}\n"; | ||
344 | uniqueListen = uniqList {inputList = map toStr listen;}; | ||
345 | in concatStrings uniqueListen | ||
346 | } | ||
347 | |||
348 | User ${mainCfg.user} | ||
349 | Group ${mainCfg.group} | ||
350 | |||
351 | ${let | ||
352 | load = {name, path}: "LoadModule ${name}_module ${path}\n"; | ||
353 | allModules = | ||
354 | concatMap (svc: svc.extraModulesPre) allSubservices | ||
355 | ++ map (name: {inherit name; path = "${httpd}/modules/mod_${name}.so";}) apacheModules | ||
356 | ++ optional mainCfg.enableMellon { name = "auth_mellon"; path = "${pkgs.apacheHttpdPackages.mod_auth_mellon}/modules/mod_auth_mellon.so"; } | ||
357 | ++ optional enablePHP { name = "php${phpMajorVersion}"; path = "${php}/modules/libphp${phpMajorVersion}.so"; } | ||
358 | ++ optional enablePerl { name = "perl"; path = "${mod_perl}/modules/mod_perl.so"; } | ||
359 | ++ concatMap (svc: svc.extraModules) allSubservices | ||
360 | ++ extraForeignModules; | ||
361 | in concatMapStrings load allModules | ||
362 | } | ||
363 | |||
364 | AddHandler type-map var | ||
365 | |||
366 | <Files ~ "^\.ht"> | ||
367 | ${allDenied} | ||
368 | </Files> | ||
369 | |||
370 | ${mimeConf} | ||
371 | ${loggingConf} | ||
372 | ${browserHacks} | ||
373 | |||
374 | Include ${httpd}/conf/extra/httpd-default.conf | ||
375 | Include ${httpd}/conf/extra/httpd-autoindex.conf | ||
376 | Include ${httpd}/conf/extra/httpd-multilang-errordoc.conf | ||
377 | Include ${httpd}/conf/extra/httpd-languages.conf | ||
378 | |||
379 | ${if enableSSL then sslConf else ""} | ||
380 | |||
381 | # Fascist default - deny access to everything. | ||
382 | <Directory /> | ||
383 | Options FollowSymLinks | ||
384 | AllowOverride None | ||
385 | ${allDenied} | ||
386 | </Directory> | ||
387 | |||
388 | # But do allow access to files in the store so that we don't have | ||
389 | # to generate <Directory> clauses for every generated file that we | ||
390 | # want to serve. | ||
391 | <Directory /nix/store> | ||
392 | ${allGranted} | ||
393 | </Directory> | ||
394 | |||
395 | # Generate directives for the main server. | ||
396 | ${perServerConf true mainCfg} | ||
397 | |||
398 | # Always enable virtual hosts; it doesn't seem to hurt. | ||
399 | ${let | ||
400 | listen = concatMap getListen allHosts; | ||
401 | uniqueListen = uniqList {inputList = listen;}; | ||
402 | directives = concatMapStrings (listen: "NameVirtualHost ${listenToString listen}\n") uniqueListen; | ||
403 | in optionalString (!version24) directives | ||
404 | } | ||
405 | |||
406 | ${let | ||
407 | makeVirtualHost = vhost: '' | ||
408 | <VirtualHost ${concatStringsSep " " (map listenToString (getListen vhost))}> | ||
409 | ${perServerConf false vhost} | ||
410 | </VirtualHost> | ||
411 | ''; | ||
412 | in concatMapStrings makeVirtualHost mainCfg.virtualHosts | ||
413 | } | ||
414 | ''; | ||
415 | |||
416 | |||
417 | enablePHP = mainCfg.enablePHP || any (svc: svc.enablePHP) allSubservices; | ||
418 | |||
419 | enablePerl = mainCfg.enablePerl || any (svc: svc.enablePerl) allSubservices; | ||
420 | |||
421 | |||
422 | # Generate the PHP configuration file. Should probably be factored | ||
423 | # out into a separate module. | ||
424 | phpIni = pkgs.runCommand "php.ini" | ||
425 | { options = concatStringsSep "\n" | ||
426 | ([ mainCfg.phpOptions ] ++ (map (svc: svc.phpOptions) allSubservices)); | ||
427 | } | ||
428 | '' | ||
429 | cat ${php}/etc/php.ini > $out | ||
430 | echo "$options" >> $out | ||
431 | ''; | ||
432 | |||
433 | in | ||
434 | |||
435 | |||
436 | { | ||
437 | |||
438 | ###### interface | ||
439 | |||
440 | options = { | ||
441 | |||
442 | services.httpdInte = { | ||
443 | |||
444 | enable = mkOption { | ||
445 | type = types.bool; | ||
446 | default = false; | ||
447 | description = "Whether to enable the Apache HTTP Server."; | ||
448 | }; | ||
449 | |||
450 | package = mkOption { | ||
451 | type = types.package; | ||
452 | default = pkgs.apacheHttpd; | ||
453 | defaultText = "pkgs.apacheHttpd"; | ||
454 | description = '' | ||
455 | Overridable attribute of the Apache HTTP Server package to use. | ||
456 | ''; | ||
457 | }; | ||
458 | |||
459 | configFile = mkOption { | ||
460 | type = types.path; | ||
461 | default = confFile; | ||
462 | defaultText = "confFile"; | ||
463 | example = literalExample ''pkgs.writeText "httpd.conf" "# my custom config file ..."''; | ||
464 | description = '' | ||
465 | Override the configuration file used by Apache. By default, | ||
466 | NixOS generates one automatically. | ||
467 | ''; | ||
468 | }; | ||
469 | |||
470 | extraConfig = mkOption { | ||
471 | type = types.lines; | ||
472 | default = ""; | ||
473 | description = '' | ||
474 | Cnfiguration lines appended to the generated Apache | ||
475 | configuration file. Note that this mechanism may not work | ||
476 | when <option>configFile</option> is overridden. | ||
477 | ''; | ||
478 | }; | ||
479 | |||
480 | extraModules = mkOption { | ||
481 | type = types.listOf types.unspecified; | ||
482 | default = []; | ||
483 | example = literalExample ''[ "proxy_connect" { name = "php5"; path = "''${pkgs.php}/modules/libphp5.so"; } ]''; | ||
484 | description = '' | ||
485 | Additional Apache modules to be used. These can be | ||
486 | specified as a string in the case of modules distributed | ||
487 | with Apache, or as an attribute set specifying the | ||
488 | <varname>name</varname> and <varname>path</varname> of the | ||
489 | module. | ||
490 | ''; | ||
491 | }; | ||
492 | |||
493 | logPerVirtualHost = mkOption { | ||
494 | type = types.bool; | ||
495 | default = false; | ||
496 | description = '' | ||
497 | If enabled, each virtual host gets its own | ||
498 | <filename>access_log</filename> and | ||
499 | <filename>error_log</filename>, namely suffixed by the | ||
500 | <option>hostName</option> of the virtual host. | ||
501 | ''; | ||
502 | }; | ||
503 | |||
504 | user = mkOption { | ||
505 | type = types.str; | ||
506 | default = "wwwrun"; | ||
507 | description = '' | ||
508 | User account under which httpd runs. The account is created | ||
509 | automatically if it doesn't exist. | ||
510 | ''; | ||
511 | }; | ||
512 | |||
513 | group = mkOption { | ||
514 | type = types.str; | ||
515 | default = "wwwrun"; | ||
516 | description = '' | ||
517 | Group under which httpd runs. The account is created | ||
518 | automatically if it doesn't exist. | ||
519 | ''; | ||
520 | }; | ||
521 | |||
522 | logDir = mkOption { | ||
523 | type = types.path; | ||
524 | default = "/var/log/httpd"; | ||
525 | description = '' | ||
526 | Directory for Apache's log files. It is created automatically. | ||
527 | ''; | ||
528 | }; | ||
529 | |||
530 | stateDir = mkOption { | ||
531 | type = types.path; | ||
532 | default = "/run/httpd"; | ||
533 | description = '' | ||
534 | Directory for Apache's transient runtime state (such as PID | ||
535 | files). It is created automatically. Note that the default, | ||
536 | <filename>/run/httpd</filename>, is deleted at boot time. | ||
537 | ''; | ||
538 | }; | ||
539 | |||
540 | virtualHosts = mkOption { | ||
541 | type = types.listOf (types.submodule ( | ||
542 | { options = import ./per-server-options.nix { | ||
543 | inherit lib; | ||
544 | forMainServer = false; | ||
545 | }; | ||
546 | })); | ||
547 | default = []; | ||
548 | example = [ | ||
549 | { hostName = "foo"; | ||
550 | documentRoot = "/data/webroot-foo"; | ||
551 | } | ||
552 | { hostName = "bar"; | ||
553 | documentRoot = "/data/webroot-bar"; | ||
554 | } | ||
555 | ]; | ||
556 | description = '' | ||
557 | Specification of the virtual hosts served by Apache. Each | ||
558 | element should be an attribute set specifying the | ||
559 | configuration of the virtual host. The available options | ||
560 | are the non-global options permissible for the main host. | ||
561 | ''; | ||
562 | }; | ||
563 | |||
564 | enableMellon = mkOption { | ||
565 | type = types.bool; | ||
566 | default = false; | ||
567 | description = "Whether to enable the mod_auth_mellon module."; | ||
568 | }; | ||
569 | |||
570 | enablePHP = mkOption { | ||
571 | type = types.bool; | ||
572 | default = false; | ||
573 | description = "Whether to enable the PHP module."; | ||
574 | }; | ||
575 | |||
576 | phpPackage = mkOption { | ||
577 | type = types.package; | ||
578 | default = pkgs.php; | ||
579 | defaultText = "pkgs.php"; | ||
580 | description = '' | ||
581 | Overridable attribute of the PHP package to use. | ||
582 | ''; | ||
583 | }; | ||
584 | |||
585 | enablePerl = mkOption { | ||
586 | type = types.bool; | ||
587 | default = false; | ||
588 | description = "Whether to enable the Perl module (mod_perl)."; | ||
589 | }; | ||
590 | |||
591 | phpOptions = mkOption { | ||
592 | type = types.lines; | ||
593 | default = ""; | ||
594 | example = | ||
595 | '' | ||
596 | date.timezone = "CET" | ||
597 | ''; | ||
598 | description = | ||
599 | "Options appended to the PHP configuration file <filename>php.ini</filename>."; | ||
600 | }; | ||
601 | |||
602 | multiProcessingModule = mkOption { | ||
603 | type = types.str; | ||
604 | default = "prefork"; | ||
605 | example = "worker"; | ||
606 | description = | ||
607 | '' | ||
608 | Multi-processing module to be used by Apache. Available | ||
609 | modules are <literal>prefork</literal> (the default; | ||
610 | handles each request in a separate child process), | ||
611 | <literal>worker</literal> (hybrid approach that starts a | ||
612 | number of child processes each running a number of | ||
613 | threads) and <literal>event</literal> (a recent variant of | ||
614 | <literal>worker</literal> that handles persistent | ||
615 | connections more efficiently). | ||
616 | ''; | ||
617 | }; | ||
618 | |||
619 | maxClients = mkOption { | ||
620 | type = types.int; | ||
621 | default = 150; | ||
622 | example = 8; | ||
623 | description = "Maximum number of httpd processes (prefork)"; | ||
624 | }; | ||
625 | |||
626 | maxRequestsPerChild = mkOption { | ||
627 | type = types.int; | ||
628 | default = 0; | ||
629 | example = 500; | ||
630 | description = | ||
631 | "Maximum number of httpd requests answered per httpd child (prefork), 0 means unlimited"; | ||
632 | }; | ||
633 | } | ||
634 | |||
635 | # Include the options shared between the main server and virtual hosts. | ||
636 | // (import ./per-server-options.nix { | ||
637 | inherit lib; | ||
638 | forMainServer = true; | ||
639 | }); | ||
640 | |||
641 | }; | ||
642 | |||
643 | |||
644 | ###### implementation | ||
645 | |||
646 | config = mkIf config.services.httpdInte.enable { | ||
647 | |||
648 | assertions = [ { assertion = mainCfg.enableSSL == true | ||
649 | -> mainCfg.sslServerCert != null | ||
650 | && mainCfg.sslServerKey != null; | ||
651 | message = "SSL is enabled for httpd, but sslServerCert and/or sslServerKey haven't been specified."; } | ||
652 | ]; | ||
653 | |||
654 | warnings = map (cfg: ''apache-httpd's port option is deprecated. Use listen = [{/*ip = "*"; */ port = ${toString cfg.port};}]; instead'' ) (lib.filter (cfg: cfg.port != 0) allHosts); | ||
655 | |||
656 | environment.systemPackages = [httpd] ++ concatMap (svc: svc.extraPath) allSubservices; | ||
657 | |||
658 | services.httpdInte.phpOptions = | ||
659 | '' | ||
660 | ; Needed for PHP's mail() function. | ||
661 | sendmail_path = sendmail -t -i | ||
662 | '' + optionalString (!isNull config.time.timeZone) '' | ||
663 | |||
664 | ; Apparently PHP doesn't use $TZ. | ||
665 | date.timezone = "${config.time.timeZone}" | ||
666 | ''; | ||
667 | |||
668 | systemd.services.httpdInte = | ||
669 | { description = "Apache HTTPD"; | ||
670 | |||
671 | wantedBy = [ "multi-user.target" ]; | ||
672 | wants = [ "keys.target" ]; | ||
673 | after = [ "network.target" "fs.target" "postgresql.service" "keys.target" ]; | ||
674 | |||
675 | path = | ||
676 | [ httpd pkgs.coreutils pkgs.gnugrep ] | ||
677 | ++ # Needed for PHP's mail() function. !!! Probably the | ||
678 | # ssmtp module should export the path to sendmail in | ||
679 | # some way. | ||
680 | optional config.networking.defaultMailServer.directDelivery pkgs.ssmtp | ||
681 | ++ concatMap (svc: svc.extraServerPath) allSubservices; | ||
682 | |||
683 | environment = | ||
684 | optionalAttrs enablePHP { PHPRC = phpIni; } | ||
685 | // optionalAttrs mainCfg.enableMellon { LD_LIBRARY_PATH = "${pkgs.xmlsec}/lib"; } | ||
686 | // (listToAttrs (concatMap (svc: svc.globalEnvVars) allSubservices)); | ||
687 | |||
688 | preStart = | ||
689 | '' | ||
690 | mkdir -m 0750 -p ${mainCfg.stateDir} | ||
691 | [ $(id -u) != 0 ] || chown root.${mainCfg.group} ${mainCfg.stateDir} | ||
692 | ${optionalString version24 '' | ||
693 | mkdir -m 0750 -p "${mainCfg.stateDir}/runtime" | ||
694 | [ $(id -u) != 0 ] || chown root.${mainCfg.group} "${mainCfg.stateDir}/runtime" | ||
695 | ''} | ||
696 | mkdir -m 0700 -p ${mainCfg.logDir} | ||
697 | |||
698 | # Get rid of old semaphores. These tend to accumulate across | ||
699 | # server restarts, eventually preventing it from restarting | ||
700 | # successfully. | ||
701 | for i in $(${pkgs.utillinux}/bin/ipcs -s | grep ' ${mainCfg.user} ' | cut -f2 -d ' '); do | ||
702 | ${pkgs.utillinux}/bin/ipcrm -s $i | ||
703 | done | ||
704 | |||
705 | # Run the startup hooks for the subservices. | ||
706 | for i in ${toString (map (svn: svn.startupScript) allSubservices)}; do | ||
707 | echo Running Apache startup hook $i... | ||
708 | $i | ||
709 | done | ||
710 | ''; | ||
711 | |||
712 | serviceConfig.ExecStart = "@${httpd}/bin/httpd httpd -f ${httpdConf}"; | ||
713 | serviceConfig.ExecStop = "${httpd}/bin/httpd -f ${httpdConf} -k graceful-stop"; | ||
714 | serviceConfig.ExecReload = "${httpd}/bin/httpd -f ${httpdConf} -k graceful"; | ||
715 | serviceConfig.Type = "forking"; | ||
716 | serviceConfig.PIDFile = "${mainCfg.stateDir}/httpd.pid"; | ||
717 | serviceConfig.Restart = "always"; | ||
718 | serviceConfig.RestartSec = "5s"; | ||
719 | }; | ||
720 | |||
721 | }; | ||
722 | } | ||
diff --git a/virtual/modules/websites/apache/httpd_prod.nix b/virtual/modules/websites/apache/httpd_prod.nix new file mode 100644 index 0000000..576a305 --- /dev/null +++ b/virtual/modules/websites/apache/httpd_prod.nix | |||
@@ -0,0 +1,722 @@ | |||
1 | { config, lib, pkgs, ... }: | ||
2 | |||
3 | with lib; | ||
4 | |||
5 | let | ||
6 | |||
7 | mainCfg = config.services.httpdProd; | ||
8 | |||
9 | httpd = mainCfg.package.out; | ||
10 | |||
11 | version24 = !versionOlder httpd.version "2.4"; | ||
12 | |||
13 | httpdConf = mainCfg.configFile; | ||
14 | |||
15 | php = mainCfg.phpPackage.override { apacheHttpd = httpd.dev; /* otherwise it only gets .out */ }; | ||
16 | |||
17 | phpMajorVersion = head (splitString "." php.version); | ||
18 | |||
19 | mod_perl = pkgs.apacheHttpdPackages.mod_perl.override { apacheHttpd = httpd; }; | ||
20 | |||
21 | defaultListen = cfg: if cfg.enableSSL | ||
22 | then [{ip = "*"; port = 443;}] | ||
23 | else [{ip = "*"; port = 80;}]; | ||
24 | |||
25 | getListen = cfg: | ||
26 | let list = (lib.optional (cfg.port != 0) {ip = "*"; port = cfg.port;}) ++ cfg.listen; | ||
27 | in if list == [] | ||
28 | then defaultListen cfg | ||
29 | else list; | ||
30 | |||
31 | listenToString = l: "${l.ip}:${toString l.port}"; | ||
32 | |||
33 | extraModules = attrByPath ["extraModules"] [] mainCfg; | ||
34 | extraForeignModules = filter isAttrs extraModules; | ||
35 | extraApacheModules = filter isString extraModules; | ||
36 | |||
37 | |||
38 | makeServerInfo = cfg: { | ||
39 | # Canonical name must not include a trailing slash. | ||
40 | canonicalNames = | ||
41 | let defaultPort = (head (defaultListen cfg)).port; in | ||
42 | map (port: | ||
43 | (if cfg.enableSSL then "https" else "http") + "://" + | ||
44 | cfg.hostName + | ||
45 | (if port != defaultPort then ":${toString port}" else "") | ||
46 | ) (map (x: x.port) (getListen cfg)); | ||
47 | |||
48 | # Admin address: inherit from the main server if not specified for | ||
49 | # a virtual host. | ||
50 | adminAddr = if cfg.adminAddr != null then cfg.adminAddr else mainCfg.adminAddr; | ||
51 | |||
52 | vhostConfig = cfg; | ||
53 | serverConfig = mainCfg; | ||
54 | fullConfig = config; # machine config | ||
55 | }; | ||
56 | |||
57 | |||
58 | allHosts = [mainCfg] ++ mainCfg.virtualHosts; | ||
59 | |||
60 | |||
61 | callSubservices = serverInfo: defs: | ||
62 | let f = svc: | ||
63 | let | ||
64 | svcFunction = | ||
65 | if svc ? function then svc.function | ||
66 | # instead of using serviceType="mediawiki"; you can copy mediawiki.nix to any location outside nixpkgs, modify it at will, and use serviceExpression=./mediawiki.nix; | ||
67 | else if svc ? serviceExpression then import (toString svc.serviceExpression) | ||
68 | else import (toString "${toString ./.}/${if svc ? serviceType then svc.serviceType else svc.serviceName}.nix"); | ||
69 | config = (evalModules | ||
70 | { modules = [ { options = res.options; config = svc.config or svc; } ]; | ||
71 | check = false; | ||
72 | }).config; | ||
73 | defaults = { | ||
74 | extraConfig = ""; | ||
75 | extraModules = []; | ||
76 | extraModulesPre = []; | ||
77 | extraPath = []; | ||
78 | extraServerPath = []; | ||
79 | globalEnvVars = []; | ||
80 | robotsEntries = ""; | ||
81 | startupScript = ""; | ||
82 | enablePHP = false; | ||
83 | enablePerl = false; | ||
84 | phpOptions = ""; | ||
85 | options = {}; | ||
86 | documentRoot = null; | ||
87 | }; | ||
88 | res = defaults // svcFunction { inherit config lib pkgs serverInfo php; }; | ||
89 | in res; | ||
90 | in map f defs; | ||
91 | |||
92 | |||
93 | # !!! callSubservices is expensive | ||
94 | subservicesFor = cfg: callSubservices (makeServerInfo cfg) cfg.extraSubservices; | ||
95 | |||
96 | mainSubservices = subservicesFor mainCfg; | ||
97 | |||
98 | allSubservices = mainSubservices ++ concatMap subservicesFor mainCfg.virtualHosts; | ||
99 | |||
100 | |||
101 | enableSSL = any (vhost: vhost.enableSSL) allHosts; | ||
102 | |||
103 | |||
104 | # Names of modules from ${httpd}/modules that we want to load. | ||
105 | apacheModules = | ||
106 | [ # HTTP authentication mechanisms: basic and digest. | ||
107 | "auth_basic" "auth_digest" | ||
108 | |||
109 | # Authentication: is the user who he claims to be? | ||
110 | "authn_file" "authn_dbm" "authn_anon" | ||
111 | (if version24 then "authn_core" else "authn_alias") | ||
112 | |||
113 | # Authorization: is the user allowed access? | ||
114 | "authz_user" "authz_groupfile" "authz_host" | ||
115 | |||
116 | # Other modules. | ||
117 | "ext_filter" "include" "log_config" "env" "mime_magic" | ||
118 | "cern_meta" "expires" "headers" "usertrack" /* "unique_id" */ "setenvif" | ||
119 | "mime" "dav" "status" "autoindex" "asis" "info" "dav_fs" | ||
120 | "vhost_alias" "negotiation" "dir" "imagemap" "actions" "speling" | ||
121 | "userdir" "alias" "rewrite" "proxy" "proxy_http" | ||
122 | ] | ||
123 | ++ optionals version24 [ | ||
124 | "mpm_${mainCfg.multiProcessingModule}" | ||
125 | "authz_core" | ||
126 | "unixd" | ||
127 | "cache" "cache_disk" | ||
128 | "slotmem_shm" | ||
129 | "socache_shmcb" | ||
130 | # For compatibility with old configurations, the new module mod_access_compat is provided. | ||
131 | "access_compat" | ||
132 | ] | ||
133 | ++ (if mainCfg.multiProcessingModule == "prefork" then [ "cgi" ] else [ "cgid" ]) | ||
134 | ++ optional enableSSL "ssl" | ||
135 | ++ extraApacheModules; | ||
136 | |||
137 | |||
138 | allDenied = if version24 then '' | ||
139 | Require all denied | ||
140 | '' else '' | ||
141 | Order deny,allow | ||
142 | Deny from all | ||
143 | ''; | ||
144 | |||
145 | allGranted = if version24 then '' | ||
146 | Require all granted | ||
147 | '' else '' | ||
148 | Order allow,deny | ||
149 | Allow from all | ||
150 | ''; | ||
151 | |||
152 | |||
153 | loggingConf = (if mainCfg.logFormat != "none" then '' | ||
154 | ErrorLog ${mainCfg.logDir}/error_log | ||
155 | |||
156 | LogLevel notice | ||
157 | |||
158 | LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined | ||
159 | LogFormat "%h %l %u %t \"%r\" %>s %b" common | ||
160 | LogFormat "%{Referer}i -> %U" referer | ||
161 | LogFormat "%{User-agent}i" agent | ||
162 | |||
163 | CustomLog ${mainCfg.logDir}/access_log ${mainCfg.logFormat} | ||
164 | '' else '' | ||
165 | ErrorLog /dev/null | ||
166 | ''); | ||
167 | |||
168 | |||
169 | browserHacks = '' | ||
170 | BrowserMatch "Mozilla/2" nokeepalive | ||
171 | BrowserMatch "MSIE 4\.0b2;" nokeepalive downgrade-1.0 force-response-1.0 | ||
172 | BrowserMatch "RealPlayer 4\.0" force-response-1.0 | ||
173 | BrowserMatch "Java/1\.0" force-response-1.0 | ||
174 | BrowserMatch "JDK/1\.0" force-response-1.0 | ||
175 | BrowserMatch "Microsoft Data Access Internet Publishing Provider" redirect-carefully | ||
176 | BrowserMatch "^WebDrive" redirect-carefully | ||
177 | BrowserMatch "^WebDAVFS/1.[012]" redirect-carefully | ||
178 | BrowserMatch "^gnome-vfs" redirect-carefully | ||
179 | ''; | ||
180 | |||
181 | |||
182 | sslConf = '' | ||
183 | SSLSessionCache ${if version24 then "shmcb" else "shm"}:${mainCfg.stateDir}/ssl_scache(512000) | ||
184 | |||
185 | ${if version24 then "Mutex" else "SSLMutex"} posixsem | ||
186 | |||
187 | SSLRandomSeed startup builtin | ||
188 | SSLRandomSeed connect builtin | ||
189 | |||
190 | SSLProtocol All -SSLv2 -SSLv3 | ||
191 | SSLCipherSuite HIGH:!aNULL:!MD5:!EXP | ||
192 | SSLHonorCipherOrder on | ||
193 | ''; | ||
194 | |||
195 | |||
196 | mimeConf = '' | ||
197 | TypesConfig ${httpd}/conf/mime.types | ||
198 | |||
199 | AddType application/x-x509-ca-cert .crt | ||
200 | AddType application/x-pkcs7-crl .crl | ||
201 | AddType application/x-httpd-php .php .phtml | ||
202 | |||
203 | <IfModule mod_mime_magic.c> | ||
204 | MIMEMagicFile ${httpd}/conf/magic | ||
205 | </IfModule> | ||
206 | ''; | ||
207 | |||
208 | |||
209 | perServerConf = isMainServer: cfg: let | ||
210 | |||
211 | serverInfo = makeServerInfo cfg; | ||
212 | |||
213 | subservices = callSubservices serverInfo cfg.extraSubservices; | ||
214 | |||
215 | maybeDocumentRoot = fold (svc: acc: | ||
216 | if acc == null then svc.documentRoot else assert svc.documentRoot == null; acc | ||
217 | ) null ([ cfg ] ++ subservices); | ||
218 | |||
219 | documentRoot = if maybeDocumentRoot != null then maybeDocumentRoot else | ||
220 | pkgs.runCommand "empty" {} "mkdir -p $out"; | ||
221 | |||
222 | documentRootConf = '' | ||
223 | DocumentRoot "${documentRoot}" | ||
224 | |||
225 | <Directory "${documentRoot}"> | ||
226 | Options Indexes FollowSymLinks | ||
227 | AllowOverride None | ||
228 | ${allGranted} | ||
229 | </Directory> | ||
230 | ''; | ||
231 | |||
232 | robotsTxt = | ||
233 | concatStringsSep "\n" (filter (x: x != "") ( | ||
234 | # If this is a vhost, the include the entries for the main server as well. | ||
235 | (if isMainServer then [] else [mainCfg.robotsEntries] ++ map (svc: svc.robotsEntries) mainSubservices) | ||
236 | ++ [cfg.robotsEntries] | ||
237 | ++ (map (svc: svc.robotsEntries) subservices))); | ||
238 | |||
239 | in '' | ||
240 | ${concatStringsSep "\n" (map (n: "ServerName ${n}") serverInfo.canonicalNames)} | ||
241 | |||
242 | ${concatMapStrings (alias: "ServerAlias ${alias}\n") cfg.serverAliases} | ||
243 | |||
244 | ${if cfg.sslServerCert != null then '' | ||
245 | SSLCertificateFile ${cfg.sslServerCert} | ||
246 | SSLCertificateKeyFile ${cfg.sslServerKey} | ||
247 | ${if cfg.sslServerChain != null then '' | ||
248 | SSLCertificateChainFile ${cfg.sslServerChain} | ||
249 | '' else ""} | ||
250 | '' else ""} | ||
251 | |||
252 | ${if cfg.enableSSL then '' | ||
253 | SSLEngine on | ||
254 | '' else if enableSSL then /* i.e., SSL is enabled for some host, but not this one */ | ||
255 | '' | ||
256 | SSLEngine off | ||
257 | '' else ""} | ||
258 | |||
259 | ${if isMainServer || cfg.adminAddr != null then '' | ||
260 | ServerAdmin ${cfg.adminAddr} | ||
261 | '' else ""} | ||
262 | |||
263 | ${if !isMainServer && mainCfg.logPerVirtualHost then '' | ||
264 | ErrorLog ${mainCfg.logDir}/error_log-${cfg.hostName} | ||
265 | CustomLog ${mainCfg.logDir}/access_log-${cfg.hostName} ${cfg.logFormat} | ||
266 | '' else ""} | ||
267 | |||
268 | ${optionalString (robotsTxt != "") '' | ||
269 | Alias /robots.txt ${pkgs.writeText "robots.txt" robotsTxt} | ||
270 | ''} | ||
271 | |||
272 | ${if isMainServer || maybeDocumentRoot != null then documentRootConf else ""} | ||
273 | |||
274 | ${if cfg.enableUserDir then '' | ||
275 | |||
276 | UserDir public_html | ||
277 | UserDir disabled root | ||
278 | |||
279 | <Directory "/home/*/public_html"> | ||
280 | AllowOverride FileInfo AuthConfig Limit Indexes | ||
281 | Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec | ||
282 | <Limit GET POST OPTIONS> | ||
283 | ${allGranted} | ||
284 | </Limit> | ||
285 | <LimitExcept GET POST OPTIONS> | ||
286 | ${allDenied} | ||
287 | </LimitExcept> | ||
288 | </Directory> | ||
289 | |||
290 | '' else ""} | ||
291 | |||
292 | ${if cfg.globalRedirect != null && cfg.globalRedirect != "" then '' | ||
293 | RedirectPermanent / ${cfg.globalRedirect} | ||
294 | '' else ""} | ||
295 | |||
296 | ${ | ||
297 | let makeFileConf = elem: '' | ||
298 | Alias ${elem.urlPath} ${elem.file} | ||
299 | ''; | ||
300 | in concatMapStrings makeFileConf cfg.servedFiles | ||
301 | } | ||
302 | |||
303 | ${ | ||
304 | let makeDirConf = elem: '' | ||
305 | Alias ${elem.urlPath} ${elem.dir}/ | ||
306 | <Directory ${elem.dir}> | ||
307 | Options +Indexes | ||
308 | ${allGranted} | ||
309 | AllowOverride All | ||
310 | </Directory> | ||
311 | ''; | ||
312 | in concatMapStrings makeDirConf cfg.servedDirs | ||
313 | } | ||
314 | |||
315 | ${concatMapStrings (svc: svc.extraConfig) subservices} | ||
316 | |||
317 | ${cfg.extraConfig} | ||
318 | ''; | ||
319 | |||
320 | |||
321 | confFile = pkgs.writeText "httpd.conf" '' | ||
322 | |||
323 | ServerRoot ${httpd} | ||
324 | |||
325 | ${optionalString version24 '' | ||
326 | DefaultRuntimeDir ${mainCfg.stateDir}/runtime | ||
327 | ''} | ||
328 | |||
329 | PidFile ${mainCfg.stateDir}/httpd.pid | ||
330 | |||
331 | ${optionalString (mainCfg.multiProcessingModule != "prefork") '' | ||
332 | # mod_cgid requires this. | ||
333 | ScriptSock ${mainCfg.stateDir}/cgisock | ||
334 | ''} | ||
335 | |||
336 | <IfModule prefork.c> | ||
337 | MaxClients ${toString mainCfg.maxClients} | ||
338 | MaxRequestsPerChild ${toString mainCfg.maxRequestsPerChild} | ||
339 | </IfModule> | ||
340 | |||
341 | ${let | ||
342 | listen = concatMap getListen allHosts; | ||
343 | toStr = listen: "Listen ${listenToString listen}\n"; | ||
344 | uniqueListen = uniqList {inputList = map toStr listen;}; | ||
345 | in concatStrings uniqueListen | ||
346 | } | ||
347 | |||
348 | User ${mainCfg.user} | ||
349 | Group ${mainCfg.group} | ||
350 | |||
351 | ${let | ||
352 | load = {name, path}: "LoadModule ${name}_module ${path}\n"; | ||
353 | allModules = | ||
354 | concatMap (svc: svc.extraModulesPre) allSubservices | ||
355 | ++ map (name: {inherit name; path = "${httpd}/modules/mod_${name}.so";}) apacheModules | ||
356 | ++ optional mainCfg.enableMellon { name = "auth_mellon"; path = "${pkgs.apacheHttpdPackages.mod_auth_mellon}/modules/mod_auth_mellon.so"; } | ||
357 | ++ optional enablePHP { name = "php${phpMajorVersion}"; path = "${php}/modules/libphp${phpMajorVersion}.so"; } | ||
358 | ++ optional enablePerl { name = "perl"; path = "${mod_perl}/modules/mod_perl.so"; } | ||
359 | ++ concatMap (svc: svc.extraModules) allSubservices | ||
360 | ++ extraForeignModules; | ||
361 | in concatMapStrings load allModules | ||
362 | } | ||
363 | |||
364 | AddHandler type-map var | ||
365 | |||
366 | <Files ~ "^\.ht"> | ||
367 | ${allDenied} | ||
368 | </Files> | ||
369 | |||
370 | ${mimeConf} | ||
371 | ${loggingConf} | ||
372 | ${browserHacks} | ||
373 | |||
374 | Include ${httpd}/conf/extra/httpd-default.conf | ||
375 | Include ${httpd}/conf/extra/httpd-autoindex.conf | ||
376 | Include ${httpd}/conf/extra/httpd-multilang-errordoc.conf | ||
377 | Include ${httpd}/conf/extra/httpd-languages.conf | ||
378 | |||
379 | ${if enableSSL then sslConf else ""} | ||
380 | |||
381 | # Fascist default - deny access to everything. | ||
382 | <Directory /> | ||
383 | Options FollowSymLinks | ||
384 | AllowOverride None | ||
385 | ${allDenied} | ||
386 | </Directory> | ||
387 | |||
388 | # But do allow access to files in the store so that we don't have | ||
389 | # to generate <Directory> clauses for every generated file that we | ||
390 | # want to serve. | ||
391 | <Directory /nix/store> | ||
392 | ${allGranted} | ||
393 | </Directory> | ||
394 | |||
395 | # Generate directives for the main server. | ||
396 | ${perServerConf true mainCfg} | ||
397 | |||
398 | # Always enable virtual hosts; it doesn't seem to hurt. | ||
399 | ${let | ||
400 | listen = concatMap getListen allHosts; | ||
401 | uniqueListen = uniqList {inputList = listen;}; | ||
402 | directives = concatMapStrings (listen: "NameVirtualHost ${listenToString listen}\n") uniqueListen; | ||
403 | in optionalString (!version24) directives | ||
404 | } | ||
405 | |||
406 | ${let | ||
407 | makeVirtualHost = vhost: '' | ||
408 | <VirtualHost ${concatStringsSep " " (map listenToString (getListen vhost))}> | ||
409 | ${perServerConf false vhost} | ||
410 | </VirtualHost> | ||
411 | ''; | ||
412 | in concatMapStrings makeVirtualHost mainCfg.virtualHosts | ||
413 | } | ||
414 | ''; | ||
415 | |||
416 | |||
417 | enablePHP = mainCfg.enablePHP || any (svc: svc.enablePHP) allSubservices; | ||
418 | |||
419 | enablePerl = mainCfg.enablePerl || any (svc: svc.enablePerl) allSubservices; | ||
420 | |||
421 | |||
422 | # Generate the PHP configuration file. Should probably be factored | ||
423 | # out into a separate module. | ||
424 | phpIni = pkgs.runCommand "php.ini" | ||
425 | { options = concatStringsSep "\n" | ||
426 | ([ mainCfg.phpOptions ] ++ (map (svc: svc.phpOptions) allSubservices)); | ||
427 | } | ||
428 | '' | ||
429 | cat ${php}/etc/php.ini > $out | ||
430 | echo "$options" >> $out | ||
431 | ''; | ||
432 | |||
433 | in | ||
434 | |||
435 | |||
436 | { | ||
437 | |||
438 | ###### interface | ||
439 | |||
440 | options = { | ||
441 | |||
442 | services.httpdProd = { | ||
443 | |||
444 | enable = mkOption { | ||
445 | type = types.bool; | ||
446 | default = false; | ||
447 | description = "Whether to enable the Apache HTTP Server."; | ||
448 | }; | ||
449 | |||
450 | package = mkOption { | ||
451 | type = types.package; | ||
452 | default = pkgs.apacheHttpd; | ||
453 | defaultText = "pkgs.apacheHttpd"; | ||
454 | description = '' | ||
455 | Overridable attribute of the Apache HTTP Server package to use. | ||
456 | ''; | ||
457 | }; | ||
458 | |||
459 | configFile = mkOption { | ||
460 | type = types.path; | ||
461 | default = confFile; | ||
462 | defaultText = "confFile"; | ||
463 | example = literalExample ''pkgs.writeText "httpd.conf" "# my custom config file ..."''; | ||
464 | description = '' | ||
465 | Override the configuration file used by Apache. By default, | ||
466 | NixOS generates one automatically. | ||
467 | ''; | ||
468 | }; | ||
469 | |||
470 | extraConfig = mkOption { | ||
471 | type = types.lines; | ||
472 | default = ""; | ||
473 | description = '' | ||
474 | Cnfiguration lines appended to the generated Apache | ||
475 | configuration file. Note that this mechanism may not work | ||
476 | when <option>configFile</option> is overridden. | ||
477 | ''; | ||
478 | }; | ||
479 | |||
480 | extraModules = mkOption { | ||
481 | type = types.listOf types.unspecified; | ||
482 | default = []; | ||
483 | example = literalExample ''[ "proxy_connect" { name = "php5"; path = "''${pkgs.php}/modules/libphp5.so"; } ]''; | ||
484 | description = '' | ||
485 | Additional Apache modules to be used. These can be | ||
486 | specified as a string in the case of modules distributed | ||
487 | with Apache, or as an attribute set specifying the | ||
488 | <varname>name</varname> and <varname>path</varname> of the | ||
489 | module. | ||
490 | ''; | ||
491 | }; | ||
492 | |||
493 | logPerVirtualHost = mkOption { | ||
494 | type = types.bool; | ||
495 | default = false; | ||
496 | description = '' | ||
497 | If enabled, each virtual host gets its own | ||
498 | <filename>access_log</filename> and | ||
499 | <filename>error_log</filename>, namely suffixed by the | ||
500 | <option>hostName</option> of the virtual host. | ||
501 | ''; | ||
502 | }; | ||
503 | |||
504 | user = mkOption { | ||
505 | type = types.str; | ||
506 | default = "wwwrun"; | ||
507 | description = '' | ||
508 | User account under which httpd runs. The account is created | ||
509 | automatically if it doesn't exist. | ||
510 | ''; | ||
511 | }; | ||
512 | |||
513 | group = mkOption { | ||
514 | type = types.str; | ||
515 | default = "wwwrun"; | ||
516 | description = '' | ||
517 | Group under which httpd runs. The account is created | ||
518 | automatically if it doesn't exist. | ||
519 | ''; | ||
520 | }; | ||
521 | |||
522 | logDir = mkOption { | ||
523 | type = types.path; | ||
524 | default = "/var/log/httpd"; | ||
525 | description = '' | ||
526 | Directory for Apache's log files. It is created automatically. | ||
527 | ''; | ||
528 | }; | ||
529 | |||
530 | stateDir = mkOption { | ||
531 | type = types.path; | ||
532 | default = "/run/httpd"; | ||
533 | description = '' | ||
534 | Directory for Apache's transient runtime state (such as PID | ||
535 | files). It is created automatically. Note that the default, | ||
536 | <filename>/run/httpd</filename>, is deleted at boot time. | ||
537 | ''; | ||
538 | }; | ||
539 | |||
540 | virtualHosts = mkOption { | ||
541 | type = types.listOf (types.submodule ( | ||
542 | { options = import ./per-server-options.nix { | ||
543 | inherit lib; | ||
544 | forMainServer = false; | ||
545 | }; | ||
546 | })); | ||
547 | default = []; | ||
548 | example = [ | ||
549 | { hostName = "foo"; | ||
550 | documentRoot = "/data/webroot-foo"; | ||
551 | } | ||
552 | { hostName = "bar"; | ||
553 | documentRoot = "/data/webroot-bar"; | ||
554 | } | ||
555 | ]; | ||
556 | description = '' | ||
557 | Specification of the virtual hosts served by Apache. Each | ||
558 | element should be an attribute set specifying the | ||
559 | configuration of the virtual host. The available options | ||
560 | are the non-global options permissible for the main host. | ||
561 | ''; | ||
562 | }; | ||
563 | |||
564 | enableMellon = mkOption { | ||
565 | type = types.bool; | ||
566 | default = false; | ||
567 | description = "Whether to enable the mod_auth_mellon module."; | ||
568 | }; | ||
569 | |||
570 | enablePHP = mkOption { | ||
571 | type = types.bool; | ||
572 | default = false; | ||
573 | description = "Whether to enable the PHP module."; | ||
574 | }; | ||
575 | |||
576 | phpPackage = mkOption { | ||
577 | type = types.package; | ||
578 | default = pkgs.php; | ||
579 | defaultText = "pkgs.php"; | ||
580 | description = '' | ||
581 | Overridable attribute of the PHP package to use. | ||
582 | ''; | ||
583 | }; | ||
584 | |||
585 | enablePerl = mkOption { | ||
586 | type = types.bool; | ||
587 | default = false; | ||
588 | description = "Whether to enable the Perl module (mod_perl)."; | ||
589 | }; | ||
590 | |||
591 | phpOptions = mkOption { | ||
592 | type = types.lines; | ||
593 | default = ""; | ||
594 | example = | ||
595 | '' | ||
596 | date.timezone = "CET" | ||
597 | ''; | ||
598 | description = | ||
599 | "Options appended to the PHP configuration file <filename>php.ini</filename>."; | ||
600 | }; | ||
601 | |||
602 | multiProcessingModule = mkOption { | ||
603 | type = types.str; | ||
604 | default = "prefork"; | ||
605 | example = "worker"; | ||
606 | description = | ||
607 | '' | ||
608 | Multi-processing module to be used by Apache. Available | ||
609 | modules are <literal>prefork</literal> (the default; | ||
610 | handles each request in a separate child process), | ||
611 | <literal>worker</literal> (hybrid approach that starts a | ||
612 | number of child processes each running a number of | ||
613 | threads) and <literal>event</literal> (a recent variant of | ||
614 | <literal>worker</literal> that handles persistent | ||
615 | connections more efficiently). | ||
616 | ''; | ||
617 | }; | ||
618 | |||
619 | maxClients = mkOption { | ||
620 | type = types.int; | ||
621 | default = 150; | ||
622 | example = 8; | ||
623 | description = "Maximum number of httpd processes (prefork)"; | ||
624 | }; | ||
625 | |||
626 | maxRequestsPerChild = mkOption { | ||
627 | type = types.int; | ||
628 | default = 0; | ||
629 | example = 500; | ||
630 | description = | ||
631 | "Maximum number of httpd requests answered per httpd child (prefork), 0 means unlimited"; | ||
632 | }; | ||
633 | } | ||
634 | |||
635 | # Include the options shared between the main server and virtual hosts. | ||
636 | // (import ./per-server-options.nix { | ||
637 | inherit lib; | ||
638 | forMainServer = true; | ||
639 | }); | ||
640 | |||
641 | }; | ||
642 | |||
643 | |||
644 | ###### implementation | ||
645 | |||
646 | config = mkIf config.services.httpdProd.enable { | ||
647 | |||
648 | assertions = [ { assertion = mainCfg.enableSSL == true | ||
649 | -> mainCfg.sslServerCert != null | ||
650 | && mainCfg.sslServerKey != null; | ||
651 | message = "SSL is enabled for httpd, but sslServerCert and/or sslServerKey haven't been specified."; } | ||
652 | ]; | ||
653 | |||
654 | warnings = map (cfg: ''apache-httpd's port option is deprecated. Use listen = [{/*ip = "*"; */ port = ${toString cfg.port};}]; instead'' ) (lib.filter (cfg: cfg.port != 0) allHosts); | ||
655 | |||
656 | environment.systemPackages = [httpd] ++ concatMap (svc: svc.extraPath) allSubservices; | ||
657 | |||
658 | services.httpdProd.phpOptions = | ||
659 | '' | ||
660 | ; Needed for PHP's mail() function. | ||
661 | sendmail_path = sendmail -t -i | ||
662 | '' + optionalString (!isNull config.time.timeZone) '' | ||
663 | |||
664 | ; Apparently PHP doesn't use $TZ. | ||
665 | date.timezone = "${config.time.timeZone}" | ||
666 | ''; | ||
667 | |||
668 | systemd.services.httpdProd = | ||
669 | { description = "Apache HTTPD"; | ||
670 | |||
671 | wantedBy = [ "multi-user.target" ]; | ||
672 | wants = [ "keys.target" ]; | ||
673 | after = [ "network.target" "fs.target" "postgresql.service" "keys.target" ]; | ||
674 | |||
675 | path = | ||
676 | [ httpd pkgs.coreutils pkgs.gnugrep ] | ||
677 | ++ # Needed for PHP's mail() function. !!! Probably the | ||
678 | # ssmtp module should export the path to sendmail in | ||
679 | # some way. | ||
680 | optional config.networking.defaultMailServer.directDelivery pkgs.ssmtp | ||
681 | ++ concatMap (svc: svc.extraServerPath) allSubservices; | ||
682 | |||
683 | environment = | ||
684 | optionalAttrs enablePHP { PHPRC = phpIni; } | ||
685 | // optionalAttrs mainCfg.enableMellon { LD_LIBRARY_PATH = "${pkgs.xmlsec}/lib"; } | ||
686 | // (listToAttrs (concatMap (svc: svc.globalEnvVars) allSubservices)); | ||
687 | |||
688 | preStart = | ||
689 | '' | ||
690 | mkdir -m 0750 -p ${mainCfg.stateDir} | ||
691 | [ $(id -u) != 0 ] || chown root.${mainCfg.group} ${mainCfg.stateDir} | ||
692 | ${optionalString version24 '' | ||
693 | mkdir -m 0750 -p "${mainCfg.stateDir}/runtime" | ||
694 | [ $(id -u) != 0 ] || chown root.${mainCfg.group} "${mainCfg.stateDir}/runtime" | ||
695 | ''} | ||
696 | mkdir -m 0700 -p ${mainCfg.logDir} | ||
697 | |||
698 | # Get rid of old semaphores. These tend to accumulate across | ||
699 | # server restarts, eventually preventing it from restarting | ||
700 | # successfully. | ||
701 | for i in $(${pkgs.utillinux}/bin/ipcs -s | grep ' ${mainCfg.user} ' | cut -f2 -d ' '); do | ||
702 | ${pkgs.utillinux}/bin/ipcrm -s $i | ||
703 | done | ||
704 | |||
705 | # Run the startup hooks for the subservices. | ||
706 | for i in ${toString (map (svn: svn.startupScript) allSubservices)}; do | ||
707 | echo Running Apache startup hook $i... | ||
708 | $i | ||
709 | done | ||
710 | ''; | ||
711 | |||
712 | serviceConfig.ExecStart = "@${httpd}/bin/httpd httpd -f ${httpdConf}"; | ||
713 | serviceConfig.ExecStop = "${httpd}/bin/httpd -f ${httpdConf} -k graceful-stop"; | ||
714 | serviceConfig.ExecReload = "${httpd}/bin/httpd -f ${httpdConf} -k graceful"; | ||
715 | serviceConfig.Type = "forking"; | ||
716 | serviceConfig.PIDFile = "${mainCfg.stateDir}/httpd.pid"; | ||
717 | serviceConfig.Restart = "always"; | ||
718 | serviceConfig.RestartSec = "5s"; | ||
719 | }; | ||
720 | |||
721 | }; | ||
722 | } | ||
diff --git a/virtual/modules/websites/apache/per-server-options.nix b/virtual/modules/websites/apache/per-server-options.nix new file mode 100644 index 0000000..4bbd041 --- /dev/null +++ b/virtual/modules/websites/apache/per-server-options.nix | |||
@@ -0,0 +1,188 @@ | |||
1 | # This file defines the options that can be used both for the Apache | ||
2 | # main server configuration, and for the virtual hosts. (The latter | ||
3 | # has additional options that affect the web server as a whole, like | ||
4 | # the user/group to run under.) | ||
5 | |||
6 | { forMainServer, lib }: | ||
7 | |||
8 | with lib; | ||
9 | |||
10 | { | ||
11 | |||
12 | hostName = mkOption { | ||
13 | type = types.str; | ||
14 | default = "localhost"; | ||
15 | description = "Canonical hostname for the server."; | ||
16 | }; | ||
17 | |||
18 | serverAliases = mkOption { | ||
19 | type = types.listOf types.str; | ||
20 | default = []; | ||
21 | example = ["www.example.org" "www.example.org:8080" "example.org"]; | ||
22 | description = '' | ||
23 | Additional names of virtual hosts served by this virtual host configuration. | ||
24 | ''; | ||
25 | }; | ||
26 | |||
27 | port = mkOption { | ||
28 | type = types.int; | ||
29 | default = 0; | ||
30 | description = '' | ||
31 | Port for the server. Option will be removed, use <option>listen</option> instead. | ||
32 | ''; | ||
33 | }; | ||
34 | |||
35 | listen = mkOption { | ||
36 | type = types.listOf (types.submodule ( | ||
37 | { | ||
38 | options = { | ||
39 | port = mkOption { | ||
40 | type = types.int; | ||
41 | description = "port to listen on"; | ||
42 | }; | ||
43 | ip = mkOption { | ||
44 | type = types.string; | ||
45 | default = "*"; | ||
46 | description = "Ip to listen on. 0.0.0.0 for ipv4 only, * for all."; | ||
47 | }; | ||
48 | }; | ||
49 | } )); | ||
50 | description = '' | ||
51 | List of { /* ip: "*"; */ port = 80;} to listen on | ||
52 | ''; | ||
53 | |||
54 | default = []; | ||
55 | }; | ||
56 | |||
57 | enableSSL = mkOption { | ||
58 | type = types.bool; | ||
59 | default = false; | ||
60 | description = "Whether to enable SSL (https) support."; | ||
61 | }; | ||
62 | |||
63 | # Note: sslServerCert and sslServerKey can be left empty, but this | ||
64 | # only makes sense for virtual hosts (they will inherit from the | ||
65 | # main server). | ||
66 | |||
67 | sslServerCert = mkOption { | ||
68 | type = types.nullOr types.path; | ||
69 | default = null; | ||
70 | example = "/var/host.cert"; | ||
71 | description = "Path to server SSL certificate."; | ||
72 | }; | ||
73 | |||
74 | sslServerKey = mkOption { | ||
75 | type = types.path; | ||
76 | example = "/var/host.key"; | ||
77 | description = "Path to server SSL certificate key."; | ||
78 | }; | ||
79 | |||
80 | sslServerChain = mkOption { | ||
81 | type = types.nullOr types.path; | ||
82 | default = null; | ||
83 | example = "/var/ca.pem"; | ||
84 | description = "Path to server SSL chain file."; | ||
85 | }; | ||
86 | |||
87 | adminAddr = mkOption ({ | ||
88 | type = types.nullOr types.str; | ||
89 | example = "admin@example.org"; | ||
90 | description = "E-mail address of the server administrator."; | ||
91 | } // (if forMainServer then {} else {default = null;})); | ||
92 | |||
93 | documentRoot = mkOption { | ||
94 | type = types.nullOr types.path; | ||
95 | default = null; | ||
96 | example = "/data/webserver/docs"; | ||
97 | description = '' | ||
98 | The path of Apache's document root directory. If left undefined, | ||
99 | an empty directory in the Nix store will be used as root. | ||
100 | ''; | ||
101 | }; | ||
102 | |||
103 | servedDirs = mkOption { | ||
104 | type = types.listOf types.attrs; | ||
105 | default = []; | ||
106 | example = [ | ||
107 | { urlPath = "/nix"; | ||
108 | dir = "/home/eelco/Dev/nix-homepage"; | ||
109 | } | ||
110 | ]; | ||
111 | description = '' | ||
112 | This option provides a simple way to serve static directories. | ||
113 | ''; | ||
114 | }; | ||
115 | |||
116 | servedFiles = mkOption { | ||
117 | type = types.listOf types.attrs; | ||
118 | default = []; | ||
119 | example = [ | ||
120 | { urlPath = "/foo/bar.png"; | ||
121 | file = "/home/eelco/some-file.png"; | ||
122 | } | ||
123 | ]; | ||
124 | description = '' | ||
125 | This option provides a simple way to serve individual, static files. | ||
126 | ''; | ||
127 | }; | ||
128 | |||
129 | extraConfig = mkOption { | ||
130 | type = types.lines; | ||
131 | default = ""; | ||
132 | example = '' | ||
133 | <Directory /home> | ||
134 | Options FollowSymlinks | ||
135 | AllowOverride All | ||
136 | </Directory> | ||
137 | ''; | ||
138 | description = '' | ||
139 | These lines go to httpd.conf verbatim. They will go after | ||
140 | directories and directory aliases defined by default. | ||
141 | ''; | ||
142 | }; | ||
143 | |||
144 | extraSubservices = mkOption { | ||
145 | type = types.listOf types.unspecified; | ||
146 | default = []; | ||
147 | description = "Extra subservices to enable in the webserver."; | ||
148 | }; | ||
149 | |||
150 | enableUserDir = mkOption { | ||
151 | type = types.bool; | ||
152 | default = false; | ||
153 | description = '' | ||
154 | Whether to enable serving <filename>~/public_html</filename> as | ||
155 | <literal>/~<replaceable>username</replaceable></literal>. | ||
156 | ''; | ||
157 | }; | ||
158 | |||
159 | globalRedirect = mkOption { | ||
160 | type = types.nullOr types.str; | ||
161 | default = null; | ||
162 | example = http://newserver.example.org/; | ||
163 | description = '' | ||
164 | If set, all requests for this host are redirected permanently to | ||
165 | the given URL. | ||
166 | ''; | ||
167 | }; | ||
168 | |||
169 | logFormat = mkOption { | ||
170 | type = types.str; | ||
171 | default = "common"; | ||
172 | example = "combined"; | ||
173 | description = '' | ||
174 | Log format for Apache's log files. Possible values are: combined, common, referer, agent. | ||
175 | ''; | ||
176 | }; | ||
177 | |||
178 | robotsEntries = mkOption { | ||
179 | type = types.lines; | ||
180 | default = ""; | ||
181 | example = "Disallow: /foo/"; | ||
182 | description = '' | ||
183 | Specification of pages to be ignored by web crawlers. See <link | ||
184 | xlink:href='http://www.robotstxt.org/'/> for details. | ||
185 | ''; | ||
186 | }; | ||
187 | |||
188 | } | ||
diff --git a/virtual/modules/websites/aten.nix b/virtual/modules/websites/aten.nix index 1a65389..53db03a 100644 --- a/virtual/modules/websites/aten.nix +++ b/virtual/modules/websites/aten.nix | |||
@@ -27,12 +27,25 @@ in { | |||
27 | services.phpfpm.poolConfigs.aten_prod = aten_prod.phpFpm.pool; | 27 | services.phpfpm.poolConfigs.aten_prod = aten_prod.phpFpm.pool; |
28 | system.activationScripts.aten_prod = aten_prod.activationScript; | 28 | system.activationScripts.aten_prod = aten_prod.activationScript; |
29 | services.myWebsites.apacheConfig.aten_prod.modules = aten_prod.apache.modules; | 29 | services.myWebsites.apacheConfig.aten_prod.modules = aten_prod.apache.modules; |
30 | services.myWebsites.production.modules = aten_prod.apache.modules; | ||
31 | services.myWebsites.production.vhostConfs.aten = { | ||
32 | certName = "aten"; | ||
33 | hosts = [ "aten.pro" "www.aten.pro" ]; | ||
34 | root = aten_prod.webRoot; | ||
35 | extraConfig = [ aten_prod.apache.vhostConf ]; | ||
36 | }; | ||
30 | }) | 37 | }) |
31 | (lib.mkIf cfg.integration.enable { | 38 | (lib.mkIf cfg.integration.enable { |
32 | security.acme.certs."eldiron".extraDomains."dev.aten.pro" = null; | 39 | security.acme.certs."eldiron".extraDomains."dev.aten.pro" = null; |
33 | services.phpfpm.poolConfigs.aten_dev = aten_dev.phpFpm.pool; | 40 | services.phpfpm.poolConfigs.aten_dev = aten_dev.phpFpm.pool; |
34 | system.activationScripts.aten_dev = aten_dev.activationScript; | 41 | system.activationScripts.aten_dev = aten_dev.activationScript; |
35 | services.myWebsites.apacheConfig.aten_dev.modules = aten_dev.apache.modules; | 42 | services.myWebsites.integration.modules = aten_dev.apache.modules; |
43 | services.myWebsites.integration.vhostConfs.aten = { | ||
44 | certName = "eldiron"; | ||
45 | hosts = [ "dev.aten.pro" ]; | ||
46 | root = aten_dev.webRoot; | ||
47 | extraConfig = [ aten_dev.apache.vhostConf ]; | ||
48 | }; | ||
36 | }) | 49 | }) |
37 | ]; | 50 | ]; |
38 | } | 51 | } |
diff --git a/virtual/modules/websites/chloe.nix b/virtual/modules/websites/chloe.nix index d54c42d..67e8e1f 100644 --- a/virtual/modules/websites/chloe.nix +++ b/virtual/modules/websites/chloe.nix | |||
@@ -26,13 +26,25 @@ in { | |||
26 | 26 | ||
27 | services.phpfpm.poolConfigs.chloe_prod = chloe_prod.phpFpm.pool; | 27 | services.phpfpm.poolConfigs.chloe_prod = chloe_prod.phpFpm.pool; |
28 | system.activationScripts.chloe_prod = chloe_prod.activationScript; | 28 | system.activationScripts.chloe_prod = chloe_prod.activationScript; |
29 | services.myWebsites.apacheConfig.chloe_prod.modules = chloe_prod.apache.modules; | 29 | services.myWebsites.production.modules = chloe_prod.apache.modules; |
30 | services.myWebsites.production.vhostConfs.chloe = { | ||
31 | certName = "chloe"; | ||
32 | hosts = ["osteopathe-cc.fr" "www.osteopathe-cc.fr" ]; | ||
33 | root = chloe_prod.webRoot; | ||
34 | extraConfig = [ chloe_prod.apache.vhostConf ]; | ||
35 | }; | ||
30 | }) | 36 | }) |
31 | (lib.mkIf cfg.integration.enable { | 37 | (lib.mkIf cfg.integration.enable { |
32 | security.acme.certs."eldiron".extraDomains."chloe.immae.eu" = null; | 38 | security.acme.certs."eldiron".extraDomains."chloe.immae.eu" = null; |
33 | services.phpfpm.poolConfigs.chloe_dev = chloe_dev.phpFpm.pool; | 39 | services.phpfpm.poolConfigs.chloe_dev = chloe_dev.phpFpm.pool; |
34 | system.activationScripts.chloe_dev = chloe_dev.activationScript; | 40 | system.activationScripts.chloe_dev = chloe_dev.activationScript; |
35 | services.myWebsites.apacheConfig.chloe_dev.modules = chloe_dev.apache.modules; | 41 | services.myWebsites.integration.modules = chloe_dev.apache.modules; |
42 | services.myWebsites.integration.vhostConfs.chloe = { | ||
43 | certName = "eldiron"; | ||
44 | hosts = ["chloe.immae.eu" ]; | ||
45 | root = chloe_dev.webRoot; | ||
46 | extraConfig = [ chloe_dev.apache.vhostConf ]; | ||
47 | }; | ||
36 | }) | 48 | }) |
37 | ]; | 49 | ]; |
38 | } | 50 | } |
diff --git a/virtual/modules/websites/connexionswing.nix b/virtual/modules/websites/connexionswing.nix index 8bf63a8..dcc7264 100644 --- a/virtual/modules/websites/connexionswing.nix +++ b/virtual/modules/websites/connexionswing.nix | |||
@@ -28,14 +28,26 @@ in { | |||
28 | 28 | ||
29 | services.phpfpm.poolConfigs.connexionswing_prod = connexionswing_prod.phpFpm.pool; | 29 | services.phpfpm.poolConfigs.connexionswing_prod = connexionswing_prod.phpFpm.pool; |
30 | system.activationScripts.connexionswing_prod = connexionswing_prod.activationScript; | 30 | system.activationScripts.connexionswing_prod = connexionswing_prod.activationScript; |
31 | services.myWebsites.apacheConfig.connexionswing_prod.modules = connexionswing_prod.apache.modules; | 31 | services.myWebsites.production.modules = connexionswing_prod.apache.modules; |
32 | services.myWebsites.production.vhostConfs.connexionswing = { | ||
33 | certName = "connexionswing"; | ||
34 | hosts = ["connexionswing.com" "sandetludo.com" "www.connexionswing.com" "www.sandetludo.com" ]; | ||
35 | root = connexionswing_prod.webRoot; | ||
36 | extraConfig = [ connexionswing_prod.apache.vhostConf ]; | ||
37 | }; | ||
32 | }) | 38 | }) |
33 | (lib.mkIf cfg.integration.enable { | 39 | (lib.mkIf cfg.integration.enable { |
34 | security.acme.certs."eldiron".extraDomains."sandetludo.immae.eu" = null; | 40 | security.acme.certs."eldiron".extraDomains."sandetludo.immae.eu" = null; |
35 | security.acme.certs."eldiron".extraDomains."connexionswing.immae.eu" = null; | 41 | security.acme.certs."eldiron".extraDomains."connexionswing.immae.eu" = null; |
36 | services.phpfpm.poolConfigs.connexionswing_dev = connexionswing_dev.phpFpm.pool; | 42 | services.phpfpm.poolConfigs.connexionswing_dev = connexionswing_dev.phpFpm.pool; |
37 | system.activationScripts.connexionswing_dev = connexionswing_dev.activationScript; | 43 | system.activationScripts.connexionswing_dev = connexionswing_dev.activationScript; |
38 | services.myWebsites.apacheConfig.connexionswing_dev.modules = connexionswing_dev.apache.modules; | 44 | services.myWebsites.integration.modules = connexionswing_dev.apache.modules; |
45 | services.myWebsites.integration.vhostConfs.connexionswing = { | ||
46 | certName = "eldiron"; | ||
47 | hosts = ["connexionswing.immae.eu" "sandetludo.immae.eu" ]; | ||
48 | root = connexionswing_dev.webRoot; | ||
49 | extraConfig = [ connexionswing_dev.apache.vhostConf ]; | ||
50 | }; | ||
39 | }) | 51 | }) |
40 | ]; | 52 | ]; |
41 | } | 53 | } |
diff --git a/virtual/modules/websites/ludivine.nix b/virtual/modules/websites/ludivine.nix index f06e41a..6eb98e7 100644 --- a/virtual/modules/websites/ludivine.nix +++ b/virtual/modules/websites/ludivine.nix | |||
@@ -26,7 +26,13 @@ in { | |||
26 | 26 | ||
27 | services.phpfpm.poolConfigs.ludivinecassal_prod = ludivinecassal_prod.phpFpm.pool; | 27 | services.phpfpm.poolConfigs.ludivinecassal_prod = ludivinecassal_prod.phpFpm.pool; |
28 | system.activationScripts.ludivinecassal_prod = ludivinecassal_prod.activationScript; | 28 | system.activationScripts.ludivinecassal_prod = ludivinecassal_prod.activationScript; |
29 | services.myWebsites.apacheConfig.ludivinecassal_prod.modules = ludivinecassal_prod.apache.modules; | 29 | services.myWebsites.production.modules = ludivinecassal_prod.apache.modules; |
30 | services.myWebsites.production.vhostConfs.ludivine = { | ||
31 | certName = "ludivinecassal"; | ||
32 | hosts = ["ludivinecassal.com" "www.ludivinecassal.com" ]; | ||
33 | root = ludivinecassal_prod.webRoot; | ||
34 | extraConfig = [ ludivinecassal_prod.apache.vhostConf ]; | ||
35 | }; | ||
30 | }) | 36 | }) |
31 | (lib.mkIf cfg.integration.enable { | 37 | (lib.mkIf cfg.integration.enable { |
32 | security.acme.certs."eldiron".extraDomains."ludivine.immae.eu" = null; | 38 | security.acme.certs."eldiron".extraDomains."ludivine.immae.eu" = null; |
@@ -34,6 +40,13 @@ in { | |||
34 | services.phpfpm.poolConfigs.ludivinecassal_dev = ludivinecassal_dev.phpFpm.pool; | 40 | services.phpfpm.poolConfigs.ludivinecassal_dev = ludivinecassal_dev.phpFpm.pool; |
35 | system.activationScripts.ludivinecassal_dev = ludivinecassal_dev.activationScript; | 41 | system.activationScripts.ludivinecassal_dev = ludivinecassal_dev.activationScript; |
36 | services.myWebsites.apacheConfig.ludivinecassal_dev.modules = ludivinecassal_dev.apache.modules; | 42 | services.myWebsites.apacheConfig.ludivinecassal_dev.modules = ludivinecassal_dev.apache.modules; |
43 | services.myWebsites.integration.modules = ludivinecassal_dev.apache.modules; | ||
44 | services.myWebsites.integration.vhostConfs.ludivine = { | ||
45 | certName = "eldiron"; | ||
46 | hosts = [ "ludivine.immae.eu" ]; | ||
47 | root = ludivinecassal_dev.webRoot; | ||
48 | extraConfig = [ ludivinecassal_dev.apache.vhostConf ]; | ||
49 | }; | ||
37 | }) | 50 | }) |
38 | ]; | 51 | ]; |
39 | } | 52 | } |
diff --git a/virtual/modules/websites/piedsjaloux.nix b/virtual/modules/websites/piedsjaloux.nix index 285fd18..46161c7 100644 --- a/virtual/modules/websites/piedsjaloux.nix +++ b/virtual/modules/websites/piedsjaloux.nix | |||
@@ -26,13 +26,25 @@ in { | |||
26 | 26 | ||
27 | services.phpfpm.poolConfigs.piedsjaloux_prod = piedsjaloux_prod.phpFpm.pool; | 27 | services.phpfpm.poolConfigs.piedsjaloux_prod = piedsjaloux_prod.phpFpm.pool; |
28 | system.activationScripts.piedsjaloux_prod = piedsjaloux_prod.activationScript; | 28 | system.activationScripts.piedsjaloux_prod = piedsjaloux_prod.activationScript; |
29 | services.myWebsites.apacheConfig.piedsjaloux_prod.modules = piedsjaloux_prod.apache.modules; | 29 | services.myWebsites.production.modules = piedsjaloux_prod.apache.modules; |
30 | services.myWebsites.production.vhostConfs.piedsjaloux = { | ||
31 | certName = "piedsjaloux"; | ||
32 | hosts = [ "piedsjaloux.fr" "www.piedsjaloux.fr" ]; | ||
33 | root = piedsjaloux_prod.webRoot; | ||
34 | extraConfig = [ piedsjaloux_prod.apache.vhostConf ]; | ||
35 | }; | ||
30 | }) | 36 | }) |
31 | (lib.mkIf cfg.integration.enable { | 37 | (lib.mkIf cfg.integration.enable { |
32 | security.acme.certs."eldiron".extraDomains."piedsjaloux.immae.eu" = null; | 38 | security.acme.certs."eldiron".extraDomains."piedsjaloux.immae.eu" = null; |
33 | services.phpfpm.poolConfigs.piedsjaloux_dev = piedsjaloux_dev.phpFpm.pool; | 39 | services.phpfpm.poolConfigs.piedsjaloux_dev = piedsjaloux_dev.phpFpm.pool; |
34 | system.activationScripts.piedsjaloux_dev = piedsjaloux_dev.activationScript; | 40 | system.activationScripts.piedsjaloux_dev = piedsjaloux_dev.activationScript; |
35 | services.myWebsites.apacheConfig.piedsjaloux_dev.modules = piedsjaloux_dev.apache.modules; | 41 | services.myWebsites.integration.modules = piedsjaloux_dev.apache.modules; |
42 | services.myWebsites.integration.vhostConfs.piedsjaloux = { | ||
43 | certName = "eldiron"; | ||
44 | hosts = [ "piedsjaloux.immae.eu" ]; | ||
45 | root = piedsjaloux_dev.webRoot; | ||
46 | extraConfig = [ piedsjaloux_dev.apache.vhostConf ]; | ||
47 | }; | ||
36 | }) | 48 | }) |
37 | ]; | 49 | ]; |
38 | } | 50 | } |