1{ config, lib, name, ... }:
2let
3 inherit (lib) literalExpression mkOption nameValuePair types;
4in
5{
6 options = {
7
8 hostName = mkOption {
9 type = types.str;
10 default = name;
11 description = "Canonical hostname for the server.";
12 };
13
14 serverAliases = mkOption {
15 type = types.listOf types.str;
16 default = [];
17 example = ["www.example.org" "www.example.org:8080" "example.org"];
18 description = ''
19 Additional names of virtual hosts served by this virtual host configuration.
20 '';
21 };
22
23 listen = mkOption {
24 type = with types; listOf (submodule ({
25 options = {
26 port = mkOption {
27 type = types.port;
28 description = "Port to listen on";
29 };
30 ip = mkOption {
31 type = types.str;
32 default = "*";
33 description = "IP to listen on. 0.0.0.0 for IPv4 only, * for all.";
34 };
35 ssl = mkOption {
36 type = types.bool;
37 default = false;
38 description = "Whether to enable SSL (https) support.";
39 };
40 };
41 }));
42 default = [];
43 example = [
44 { ip = "195.154.1.1"; port = 443; ssl = true;}
45 { ip = "192.154.1.1"; port = 80; }
46 { ip = "*"; port = 8080; }
47 ];
48 description = ''
49 Listen addresses and ports for this virtual host.
50 <note>
51 <para>
52 This option overrides <literal>addSSL</literal>, <literal>forceSSL</literal> and <literal>onlySSL</literal>.
53 </para>
54 <para>
55 If you only want to set the addresses manually and not the ports, take a look at <literal>listenAddresses</literal>.
56 </para>
57 </note>
58 '';
59 };
60
61 listenAddresses = mkOption {
62 type = with types; nonEmptyListOf str;
63
64 description = ''
65 Listen addresses for this virtual host.
66 Compared to <literal>listen</literal> this only sets the addreses
67 and the ports are chosen automatically.
68 '';
69 default = [ "*" ];
70 example = [ "127.0.0.1" ];
71 };
72
73 enableSSL = mkOption {
74 type = types.bool;
75 visible = false;
76 default = false;
77 };
78
79 addSSL = mkOption {
80 type = types.bool;
81 default = false;
82 description = ''
83 Whether to enable HTTPS in addition to plain HTTP. This will set defaults for
84 <literal>listen</literal> to listen on all interfaces on the respective default
85 ports (80, 443).
86 '';
87 };
88
89 onlySSL = mkOption {
90 type = types.bool;
91 default = false;
92 description = ''
93 Whether to enable HTTPS and reject plain HTTP connections. This will set
94 defaults for <literal>listen</literal> to listen on all interfaces on port 443.
95 '';
96 };
97
98 forceSSL = mkOption {
99 type = types.bool;
100 default = false;
101 description = ''
102 Whether to add a separate nginx server block that permanently redirects (301)
103 all plain HTTP traffic to HTTPS. This will set defaults for
104 <literal>listen</literal> to listen on all interfaces on the respective default
105 ports (80, 443), where the non-SSL listens are used for the redirect vhosts.
106 '';
107 };
108
109 enableACME = mkOption {
110 type = types.bool;
111 default = false;
112 description = ''
113 Whether to ask Let's Encrypt to sign a certificate for this vhost.
114 Alternately, you can use an existing certificate through <option>useACMEHost</option>.
115 '';
116 };
117
118 useACMEHost = mkOption {
119 type = types.nullOr types.str;
120 default = null;
121 description = ''
122 A host of an existing Let's Encrypt certificate to use.
123 This is useful if you have many subdomains and want to avoid hitting the
124 <link xlink:href="https://letsencrypt.org/docs/rate-limits/">rate limit</link>.
125 Alternately, you can generate a certificate through <option>enableACME</option>.
126 <emphasis>Note that this option does not create any certificates, nor it does add subdomains to existing ones – you will need to create them manually using <xref linkend="opt-security.acme.certs"/>.</emphasis>
127 '';
128 };
129
130 acmeRoot = mkOption {
131 type = types.str;
132 default = "/var/lib/acme/acme-challenge";
133 description = "Directory for the acme challenge which is PUBLIC, don't put certs or keys in here";
134 };
135
136 sslServerCert = mkOption {
137 type = types.path;
138 example = "/var/host.cert";
139 description = "Path to server SSL certificate.";
140 };
141
142 sslServerKey = mkOption {
143 type = types.path;
144 example = "/var/host.key";
145 description = "Path to server SSL certificate key.";
146 };
147
148 sslServerChain = mkOption {
149 type = types.nullOr types.path;
150 default = null;
151 example = "/var/ca.pem";
152 description = "Path to server SSL chain file.";
153 };
154
155 http2 = mkOption {
156 type = types.bool;
157 default = true;
158 description = ''
159 Whether to enable HTTP 2. HTTP/2 is supported in all multi-processing modules that come with httpd. <emphasis>However, if you use the prefork mpm, there will
160 be severe restrictions.</emphasis> Refer to <link xlink:href="https://httpd.apache.org/docs/2.4/howto/http2.html#mpm-config"/> for details.
161 '';
162 };
163
164 adminAddr = mkOption {
165 type = types.nullOr types.str;
166 default = null;
167 example = "admin@example.org";
168 description = "E-mail address of the server administrator.";
169 };
170
171 documentRoot = mkOption {
172 type = types.nullOr types.path;
173 default = null;
174 example = "/data/webserver/docs";
175 description = ''
176 The path of Apache's document root directory. If left undefined,
177 an empty directory in the Nix store will be used as root.
178 '';
179 };
180
181 servedDirs = mkOption {
182 type = types.listOf types.attrs;
183 default = [];
184 example = [
185 { urlPath = "/nix";
186 dir = "/home/eelco/Dev/nix-homepage";
187 }
188 ];
189 description = ''
190 This option provides a simple way to serve static directories.
191 '';
192 };
193
194 servedFiles = mkOption {
195 type = types.listOf types.attrs;
196 default = [];
197 example = [
198 { urlPath = "/foo/bar.png";
199 file = "/home/eelco/some-file.png";
200 }
201 ];
202 description = ''
203 This option provides a simple way to serve individual, static files.
204
205 <note><para>
206 This option has been deprecated and will be removed in a future
207 version of NixOS. You can achieve the same result by making use of
208 the <literal>locations.<name>.alias</literal> option.
209 </para></note>
210 '';
211 };
212
213 extraConfig = mkOption {
214 type = types.lines;
215 default = "";
216 example = ''
217 <Directory /home>
218 Options FollowSymlinks
219 AllowOverride All
220 </Directory>
221 '';
222 description = ''
223 These lines go to httpd.conf verbatim. They will go after
224 directories and directory aliases defined by default.
225 '';
226 };
227
228 enableUserDir = mkOption {
229 type = types.bool;
230 default = false;
231 description = ''
232 Whether to enable serving <filename>~/public_html</filename> as
233 <literal>/~<replaceable>username</replaceable></literal>.
234 '';
235 };
236
237 globalRedirect = mkOption {
238 type = types.nullOr types.str;
239 default = null;
240 example = "http://newserver.example.org/";
241 description = ''
242 If set, all requests for this host are redirected permanently to
243 the given URL.
244 '';
245 };
246
247 logFormat = mkOption {
248 type = types.str;
249 default = "common";
250 example = "combined";
251 description = ''
252 Log format for Apache's log files. Possible values are: combined, common, referer, agent.
253 '';
254 };
255
256 robotsEntries = mkOption {
257 type = types.lines;
258 default = "";
259 example = "Disallow: /foo/";
260 description = ''
261 Specification of pages to be ignored by web crawlers. See <link
262 xlink:href='http://www.robotstxt.org/'/> for details.
263 '';
264 };
265
266 locations = mkOption {
267 type = with types; attrsOf (submodule (import ./location-options.nix));
268 default = {};
269 example = literalExpression ''
270 {
271 "/" = {
272 proxyPass = "http://localhost:3000";
273 };
274 "/foo/bar.png" = {
275 alias = "/home/eelco/some-file.png";
276 };
277 };
278 '';
279 description = ''
280 Declarative location config. See <link
281 xlink:href="https://httpd.apache.org/docs/2.4/mod/core.html#location"/> for details.
282 '';
283 };
284
285 };
286
287 config = {
288
289 locations = builtins.listToAttrs (map (elem: nameValuePair elem.urlPath { alias = elem.file; }) config.servedFiles);
290
291 };
292}