diff options
author | Ismaël Bouya <ismael.bouya@normalesup.org> | 2019-05-14 08:47:00 +0200 |
---|---|---|
committer | Ismaël Bouya <ismael.bouya@normalesup.org> | 2019-05-14 09:41:18 +0200 |
commit | daf64e3f7de98e4267823d14fa34891b27b5f657 (patch) | |
tree | 82a3bc59b1bff35b7cd2fc4aeb02e0485e5b37a0 /modules | |
parent | 017cb76f3355369a57cee7e851e013fbe7b265b7 (diff) | |
download | Nix-daf64e3f7de98e4267823d14fa34891b27b5f657.tar.gz Nix-daf64e3f7de98e4267823d14fa34891b27b5f657.tar.zst Nix-daf64e3f7de98e4267823d14fa34891b27b5f657.zip |
Start moving websites configuration to modules
Diffstat (limited to 'modules')
-rw-r--r-- | modules/default.nix | 2 | ||||
-rw-r--r-- | modules/private/default.nix | 2 | ||||
-rw-r--r-- | modules/private/httpd-service-builder.nix | 8 | ||||
-rw-r--r-- | modules/websites/default.nix | 148 | ||||
-rw-r--r-- | modules/websites/nosslVhost/index.html | 11 |
5 files changed, 166 insertions, 5 deletions
diff --git a/modules/default.nix b/modules/default.nix index 6c49160..acb0bb5 100644 --- a/modules/default.nix +++ b/modules/default.nix | |||
@@ -8,4 +8,6 @@ | |||
8 | mastodon = ./webapps/mastodon.nix; | 8 | mastodon = ./webapps/mastodon.nix; |
9 | mediagoblin = ./webapps/mediagoblin.nix; | 9 | mediagoblin = ./webapps/mediagoblin.nix; |
10 | peertube = ./webapps/peertube.nix; | 10 | peertube = ./webapps/peertube.nix; |
11 | |||
12 | websites = ./websites; | ||
11 | } // (if builtins.pathExists ./private then import ./private else {}) | 13 | } // (if builtins.pathExists ./private then import ./private else {}) |
diff --git a/modules/private/default.nix b/modules/private/default.nix index ba46374..6c71af3 100644 --- a/modules/private/default.nix +++ b/modules/private/default.nix | |||
@@ -1,6 +1,6 @@ | |||
1 | { | 1 | { |
2 | # adatped from nixpkgs/nixos/modules/services/web-servers/apache-httpd/default.nix | 2 | # adatped from nixpkgs/nixos/modules/services/web-servers/apache-httpd/default.nix |
3 | httpdProd = import ./httpd-service-builder.nix { httpdName = "Prod"; withUsers = false; }; | ||
4 | httpdInte = import ./httpd-service-builder.nix { httpdName = "Inte"; withUsers = false; }; | 3 | httpdInte = import ./httpd-service-builder.nix { httpdName = "Inte"; withUsers = false; }; |
4 | httpdProd = import ./httpd-service-builder.nix { httpdName = "Prod"; withUsers = false; }; | ||
5 | httpdTools = import ./httpd-service-builder.nix { httpdName = "Tools"; withUsers = true; }; | 5 | httpdTools = import ./httpd-service-builder.nix { httpdName = "Tools"; withUsers = true; }; |
6 | } | 6 | } |
diff --git a/modules/private/httpd-service-builder.nix b/modules/private/httpd-service-builder.nix index 0f0fe22..d049202 100644 --- a/modules/private/httpd-service-builder.nix +++ b/modules/private/httpd-service-builder.nix | |||
@@ -7,7 +7,7 @@ with lib; | |||
7 | 7 | ||
8 | let | 8 | let |
9 | 9 | ||
10 | mainCfg = config.services."httpd${httpdName}"; | 10 | mainCfg = config.services.httpd."${httpdName}"; |
11 | 11 | ||
12 | httpd = mainCfg.package.out; | 12 | httpd = mainCfg.package.out; |
13 | 13 | ||
@@ -438,7 +438,7 @@ in | |||
438 | 438 | ||
439 | options = { | 439 | options = { |
440 | 440 | ||
441 | services."httpd${httpdName}" = { | 441 | services.httpd."${httpdName}" = { |
442 | 442 | ||
443 | enable = mkOption { | 443 | enable = mkOption { |
444 | type = types.bool; | 444 | type = types.bool; |
@@ -655,7 +655,7 @@ in | |||
655 | 655 | ||
656 | ###### implementation | 656 | ###### implementation |
657 | 657 | ||
658 | config = mkIf config.services."httpd${httpdName}".enable { | 658 | config = mkIf config.services.httpd."${httpdName}".enable { |
659 | 659 | ||
660 | assertions = [ { assertion = mainCfg.enableSSL == true | 660 | assertions = [ { assertion = mainCfg.enableSSL == true |
661 | -> mainCfg.sslServerCert != null | 661 | -> mainCfg.sslServerCert != null |
@@ -679,7 +679,7 @@ in | |||
679 | 679 | ||
680 | environment.systemPackages = [httpd] ++ concatMap (svc: svc.extraPath) allSubservices; | 680 | environment.systemPackages = [httpd] ++ concatMap (svc: svc.extraPath) allSubservices; |
681 | 681 | ||
682 | services."httpd${httpdName}".phpOptions = | 682 | services.httpd."${httpdName}".phpOptions = |
683 | '' | 683 | '' |
684 | ; Needed for PHP's mail() function. | 684 | ; Needed for PHP's mail() function. |
685 | sendmail_path = sendmail -t -i | 685 | sendmail_path = sendmail -t -i |
diff --git a/modules/websites/default.nix b/modules/websites/default.nix new file mode 100644 index 0000000..6a18c8a --- /dev/null +++ b/modules/websites/default.nix | |||
@@ -0,0 +1,148 @@ | |||
1 | { lib, config, ... }: with lib; | ||
2 | let | ||
3 | cfg = config.services.websites; | ||
4 | in | ||
5 | { | ||
6 | options.services.websites = with types; mkOption { | ||
7 | default = {}; | ||
8 | description = "Each type of website to enable will target a distinct httpd server"; | ||
9 | type = attrsOf (submodule { | ||
10 | options = { | ||
11 | enable = mkEnableOption "Enable websites of this type"; | ||
12 | adminAddr = mkOption { | ||
13 | type = str; | ||
14 | description = "Admin e-mail address of the instance"; | ||
15 | }; | ||
16 | httpdName = mkOption { | ||
17 | type = str; | ||
18 | description = "Name of the httpd instance to assign this type to"; | ||
19 | }; | ||
20 | ips = mkOption { | ||
21 | type = listOf string; | ||
22 | default = []; | ||
23 | description = "ips to listen to"; | ||
24 | }; | ||
25 | modules = mkOption { | ||
26 | type = listOf str; | ||
27 | default = []; | ||
28 | description = "Additional modules to load in Apache"; | ||
29 | }; | ||
30 | extraConfig = mkOption { | ||
31 | type = listOf lines; | ||
32 | default = []; | ||
33 | description = "Additional configuration to append to Apache"; | ||
34 | }; | ||
35 | nosslVhost = mkOption { | ||
36 | description = "A default nossl vhost for captive portals"; | ||
37 | default = {}; | ||
38 | type = submodule { | ||
39 | options = { | ||
40 | enable = mkEnableOption "Add default no-ssl vhost for this instance"; | ||
41 | host = mkOption { | ||
42 | type = string; | ||
43 | description = "The hostname to use for this vhost"; | ||
44 | }; | ||
45 | root = mkOption { | ||
46 | type = path; | ||
47 | default = ./nosslVhost; | ||
48 | description = "The root folder to serve"; | ||
49 | }; | ||
50 | indexFile = mkOption { | ||
51 | type = string; | ||
52 | default = "index.html"; | ||
53 | description = "The index file to show."; | ||
54 | }; | ||
55 | }; | ||
56 | }; | ||
57 | }; | ||
58 | fallbackVhost = mkOption { | ||
59 | description = "The fallback vhost that will be defined as first vhost in Apache"; | ||
60 | type = submodule { | ||
61 | options = { | ||
62 | certName = mkOption { type = string; }; | ||
63 | hosts = mkOption { type = listOf string; }; | ||
64 | root = mkOption { type = nullOr path; }; | ||
65 | extraConfig = mkOption { type = listOf lines; default = []; }; | ||
66 | }; | ||
67 | }; | ||
68 | }; | ||
69 | vhostConfs = mkOption { | ||
70 | default = {}; | ||
71 | description = "List of vhosts to define for Apache"; | ||
72 | type = attrsOf (submodule { | ||
73 | options = { | ||
74 | certName = mkOption { type = string; }; | ||
75 | hosts = mkOption { type = listOf string; }; | ||
76 | root = mkOption { type = nullOr path; }; | ||
77 | extraConfig = mkOption { type = listOf lines; default = []; }; | ||
78 | }; | ||
79 | }); | ||
80 | }; | ||
81 | }; | ||
82 | }); | ||
83 | }; | ||
84 | |||
85 | config.services.httpd = let | ||
86 | redirectVhost = ips: { # Should go last, catchall http -> https redirect | ||
87 | listen = map (ip: { inherit ip; port = 80; }) ips; | ||
88 | hostName = "redirectSSL"; | ||
89 | serverAliases = [ "*" ]; | ||
90 | enableSSL = false; | ||
91 | logFormat = "combinedVhost"; | ||
92 | documentRoot = "/var/lib/acme/acme-challenge"; | ||
93 | extraConfig = '' | ||
94 | RewriteEngine on | ||
95 | RewriteCond "%{REQUEST_URI}" "!^/\.well-known" | ||
96 | RewriteRule ^(.+) https://%{HTTP_HOST}$1 [R=301] | ||
97 | # To redirect in specific "VirtualHost *:80", do | ||
98 | # RedirectMatch 301 ^/((?!\.well-known.*$).*)$ https://host/$1 | ||
99 | # rather than rewrite | ||
100 | ''; | ||
101 | }; | ||
102 | nosslVhost = ips: cfg: { | ||
103 | listen = map (ip: { inherit ip; port = 80; }) ips; | ||
104 | hostName = cfg.host; | ||
105 | enableSSL = false; | ||
106 | logFormat = "combinedVhost"; | ||
107 | documentRoot = cfg.root; | ||
108 | extraConfig = '' | ||
109 | <Directory ${cfg.root}> | ||
110 | DirectoryIndex ${cfg.indexFile} | ||
111 | AllowOverride None | ||
112 | Require all granted | ||
113 | |||
114 | RewriteEngine on | ||
115 | RewriteRule ^/(.+) / [L] | ||
116 | </Directory> | ||
117 | ''; | ||
118 | }; | ||
119 | toVhost = ips: vhostConf: { | ||
120 | enableSSL = true; | ||
121 | sslServerCert = "/var/lib/acme/${vhostConf.certName}/cert.pem"; | ||
122 | sslServerKey = "/var/lib/acme/${vhostConf.certName}/key.pem"; | ||
123 | sslServerChain = "/var/lib/acme/${vhostConf.certName}/chain.pem"; | ||
124 | logFormat = "combinedVhost"; | ||
125 | listen = map (ip: { inherit ip; port = 443; }) ips; | ||
126 | hostName = builtins.head vhostConf.hosts; | ||
127 | serverAliases = builtins.tail vhostConf.hosts or []; | ||
128 | documentRoot = vhostConf.root; | ||
129 | extraConfig = builtins.concatStringsSep "\n" vhostConf.extraConfig; | ||
130 | }; | ||
131 | in attrsets.mapAttrs' (name: icfg: attrsets.nameValuePair | ||
132 | icfg.httpdName (mkIf icfg.enable { | ||
133 | enable = true; | ||
134 | listen = map (ip: { inherit ip; port = 443; }) icfg.ips; | ||
135 | stateDir = "/run/httpd_${name}"; | ||
136 | logPerVirtualHost = true; | ||
137 | multiProcessingModule = "worker"; | ||
138 | inherit (icfg) adminAddr; | ||
139 | logFormat = "combinedVhost"; | ||
140 | extraModules = lists.unique icfg.modules; | ||
141 | extraConfig = builtins.concatStringsSep "\n" icfg.extraConfig; | ||
142 | virtualHosts = [ (toVhost icfg.ips icfg.fallbackVhost) ] | ||
143 | ++ optionals (icfg.nosslVhost.enable) [ (nosslVhost icfg.ips icfg.nosslVhost) ] | ||
144 | ++ (attrsets.mapAttrsToList (n: v: toVhost icfg.ips v) icfg.vhostConfs) | ||
145 | ++ [ (redirectVhost icfg.ips) ]; | ||
146 | }) | ||
147 | ) cfg; | ||
148 | } | ||
diff --git a/modules/websites/nosslVhost/index.html b/modules/websites/nosslVhost/index.html new file mode 100644 index 0000000..4401a80 --- /dev/null +++ b/modules/websites/nosslVhost/index.html | |||
@@ -0,0 +1,11 @@ | |||
1 | <!DOCTYPE html> | ||
2 | <html> | ||
3 | <head> | ||
4 | <title>No SSL site</title> | ||
5 | </head> | ||
6 | <body> | ||
7 | <h1>No SSL on this site</h1> | ||
8 | <p>Use for wifi networks with login page that doesn't work well with | ||
9 | https.</p> | ||
10 | </body> | ||
11 | </html> | ||