aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIsmaël Bouya <ismael.bouya@normalesup.org>2019-01-10 20:56:44 +0100
committerIsmaël Bouya <ismael.bouya@normalesup.org>2019-01-10 21:02:06 +0100
commitf8bde3d6d31da84b5e81bdfc4f96efdf6bec3df2 (patch)
treecc29816c7f448d736ca0ac6b24763fca4bb48332
parent42429ef0756d9ee41cf0ff0b38210edb3b1637e5 (diff)
downloadNix-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.nix57
-rw-r--r--virtual/modules/websites.nix81
-rw-r--r--virtual/modules/websites/apache/httpd_inte.nix722
-rw-r--r--virtual/modules/websites/apache/httpd_prod.nix722
-rw-r--r--virtual/modules/websites/apache/per-server-options.nix188
-rw-r--r--virtual/modules/websites/aten.nix15
-rw-r--r--virtual/modules/websites/chloe.nix16
-rw-r--r--virtual/modules/websites/connexionswing.nix16
-rw-r--r--virtual/modules/websites/ludivine.nix15
-rw-r--r--virtual/modules/websites/piedsjaloux.nix16
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, ... }:
2let 2let
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 };
4in 59in
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
3with lib;
4
5let
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
433in
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
3with lib;
4
5let
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
433in
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
8with 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}