1# This file defines the options that can be used both for the Nginx
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{ config, lib, ... }:
7
8with lib;
9{
10 options = {
11 serverName = mkOption {
12 type = types.nullOr types.str;
13 default = null;
14 description = ''
15 Name of this virtual host. Defaults to attribute name in virtualHosts.
16 '';
17 example = "example.org";
18 };
19
20 serverAliases = mkOption {
21 type = types.listOf types.str;
22 default = [ ];
23 example = [
24 "www.example.org"
25 "example.org"
26 ];
27 description = ''
28 Additional names of virtual hosts served by this virtual host configuration.
29 '';
30 };
31
32 listen = mkOption {
33 type =
34 with types;
35 listOf (submodule {
36 options = {
37 addr = mkOption {
38 type = str;
39 description = "Listen address.";
40 };
41 port = mkOption {
42 type = types.nullOr port;
43 description = ''
44 Port number to listen on.
45 If unset and the listen address is not a socket then nginx defaults to 80.
46 '';
47 default = null;
48 };
49 ssl = mkOption {
50 type = bool;
51 description = "Enable SSL.";
52 default = false;
53 };
54 proxyProtocol = mkOption {
55 type = bool;
56 description = "Enable PROXY protocol.";
57 default = false;
58 };
59 extraParameters = mkOption {
60 type = listOf str;
61 description = "Extra parameters of this listen directive.";
62 default = [ ];
63 example = [
64 "backlog=1024"
65 "deferred"
66 ];
67 };
68 };
69 });
70 default = [ ];
71 example = [
72 {
73 addr = "195.154.1.1";
74 port = 443;
75 ssl = true;
76 }
77 {
78 addr = "192.154.1.1";
79 port = 80;
80 }
81 { addr = "unix:/var/run/nginx.sock"; }
82 ];
83 description = ''
84 Listen addresses and ports for this virtual host.
85 IPv6 addresses must be enclosed in square brackets.
86 Note: this option overrides `addSSL`
87 and `onlySSL`.
88
89 If you only want to set the addresses manually and not
90 the ports, take a look at `listenAddresses`.
91 '';
92 };
93
94 listenAddresses = mkOption {
95 type = with types; listOf str;
96
97 description = ''
98 Listen addresses for this virtual host.
99 Compared to `listen` this only sets the addresses
100 and the ports are chosen automatically.
101
102 Note: This option overrides `enableIPv6`
103 '';
104 default = [ ];
105 example = [
106 "127.0.0.1"
107 "[::1]"
108 ];
109 };
110
111 enableACME = mkOption {
112 type = types.bool;
113 default = false;
114 description = ''
115 Whether to ask Let's Encrypt to sign a certificate for this vhost.
116 Alternately, you can use an existing certificate through {option}`useACMEHost`.
117 '';
118 };
119
120 useACMEHost = mkOption {
121 type = types.nullOr types.str;
122 default = null;
123 description = ''
124 A host of an existing Let's Encrypt certificate to use.
125 This is useful if you have many subdomains and want to avoid hitting the
126 [rate limit](https://letsencrypt.org/docs/rate-limits).
127 Alternately, you can generate a certificate through {option}`enableACME`.
128 *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 [](#opt-security.acme.certs).*
129 '';
130 };
131
132 acmeRoot = mkOption {
133 type = types.nullOr types.str;
134 default = "/var/lib/acme/acme-challenge";
135 description = ''
136 Directory for the ACME challenge, which is **public**. Don't put certs or keys in here.
137 Set to null to inherit from config.security.acme.
138 '';
139 };
140
141 acmeFallbackHost = mkOption {
142 type = types.nullOr types.str;
143 default = null;
144 description = ''
145 Host which to proxy requests to if ACME challenge is not found. Useful
146 if you want multiple hosts to be able to verify the same domain name.
147
148 With this option, you could request certificates for the present domain
149 with an ACME client that is running on another host, which you would
150 specify here.
151 '';
152 };
153
154 addSSL = mkOption {
155 type = types.bool;
156 default = false;
157 description = ''
158 Whether to enable HTTPS in addition to plain HTTP. This will set defaults for
159 `listen` to listen on all interfaces on the respective default
160 ports (80, 443).
161 '';
162 };
163
164 onlySSL = mkOption {
165 type = types.bool;
166 default = false;
167 description = ''
168 Whether to enable HTTPS and reject plain HTTP connections. This will set
169 defaults for `listen` to listen on all interfaces on port 443.
170 '';
171 };
172
173 enableSSL = mkOption {
174 type = types.bool;
175 visible = false;
176 default = false;
177 };
178
179 forceSSL = mkOption {
180 type = types.bool;
181 default = false;
182 description = ''
183 Whether to add a separate nginx server block that redirects (defaults
184 to 301, configurable with `redirectCode`) all plain HTTP traffic to
185 HTTPS. This will set defaults for `listen` to listen on all interfaces
186 on the respective default ports (80, 443), where the non-SSL listens
187 are used for the redirect vhosts.
188 '';
189 };
190
191 rejectSSL = mkOption {
192 type = types.bool;
193 default = false;
194 description = ''
195 Whether to listen for and reject all HTTPS connections to this vhost. Useful in
196 [default](#opt-services.nginx.virtualHosts._name_.default)
197 server blocks to avoid serving the certificate for another vhost. Uses the
198 `ssl_reject_handshake` directive available in nginx versions
199 1.19.4 and above.
200 '';
201 };
202
203 kTLS = mkOption {
204 type = types.bool;
205 default = false;
206 description = ''
207 Whether to enable kTLS support.
208 Implementing TLS in the kernel (kTLS) improves performance by significantly
209 reducing the need for copying operations between user space and the kernel.
210 Required Nginx version 1.21.4 or later.
211 '';
212 };
213
214 sslCertificate = mkOption {
215 type = types.path;
216 example = "/var/host.cert";
217 description = "Path to server SSL certificate.";
218 };
219
220 sslCertificateKey = mkOption {
221 type = types.path;
222 example = "/var/host.key";
223 description = "Path to server SSL certificate key.";
224 };
225
226 sslTrustedCertificate = mkOption {
227 type = types.nullOr types.path;
228 default = null;
229 example = literalExpression ''"''${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt"'';
230 description = "Path to root SSL certificate for stapling and client certificates.";
231 };
232
233 http2 = mkOption {
234 type = types.bool;
235 default = true;
236 description = ''
237 Whether to enable the HTTP/2 protocol.
238 Note that (as of writing) due to nginx's implementation, to disable
239 HTTP/2 you have to disable it on all vhosts that use a given
240 IP address / port.
241 If there is one server block configured to enable http2, then it is
242 enabled for all server blocks on this IP.
243 See https://stackoverflow.com/a/39466948/263061.
244 '';
245 };
246
247 http3 = mkOption {
248 type = types.bool;
249 default = true;
250 description = ''
251 Whether to enable the HTTP/3 protocol.
252 This requires using `pkgs.nginxQuic` package
253 which can be achieved by setting `services.nginx.package = pkgs.nginxQuic;`
254 and activate the QUIC transport protocol
255 `services.nginx.virtualHosts.<name>.quic = true;`.
256 Note that HTTP/3 support is experimental and *not* yet recommended for production.
257 Read more at https://quic.nginx.org/
258 HTTP/3 availability must be manually advertised, preferably in each location block.
259 '';
260 };
261
262 http3_hq = mkOption {
263 type = types.bool;
264 default = false;
265 description = ''
266 Whether to enable the HTTP/0.9 protocol negotiation used in QUIC interoperability tests.
267 This requires using `pkgs.nginxQuic` package
268 which can be achieved by setting `services.nginx.package = pkgs.nginxQuic;`
269 and activate the QUIC transport protocol
270 `services.nginx.virtualHosts.<name>.quic = true;`.
271 Note that special application protocol support is experimental and *not* yet recommended for production.
272 Read more at https://quic.nginx.org/
273 '';
274 };
275
276 quic = mkOption {
277 type = types.bool;
278 default = false;
279 description = ''
280 Whether to enable the QUIC transport protocol.
281 This requires using `pkgs.nginxQuic` package
282 which can be achieved by setting `services.nginx.package = pkgs.nginxQuic;`.
283 Note that QUIC support is experimental and
284 *not* yet recommended for production.
285 Read more at https://quic.nginx.org/
286 '';
287 };
288
289 reuseport = mkOption {
290 type = types.bool;
291 default = false;
292 description = ''
293 Create an individual listening socket .
294 It is required to specify only once on one of the hosts.
295 '';
296 };
297
298 root = mkOption {
299 type = types.nullOr types.path;
300 default = null;
301 example = "/data/webserver/docs";
302 description = ''
303 The path of the web root directory.
304 '';
305 };
306
307 default = mkOption {
308 type = types.bool;
309 default = false;
310 description = ''
311 Makes this vhost the default.
312 '';
313 };
314
315 extraConfig = mkOption {
316 type = types.lines;
317 default = "";
318 description = ''
319 These lines go to the end of the vhost verbatim.
320 '';
321 };
322
323 globalRedirect = mkOption {
324 type = types.nullOr types.str;
325 default = null;
326 example = "newserver.example.org";
327 description = ''
328 If set, all requests for this host are redirected (defaults to 301,
329 configurable with `redirectCode`) to the given hostname.
330 '';
331 };
332
333 redirectCode = mkOption {
334 type = types.ints.between 300 399;
335 default = 301;
336 example = 308;
337 description = ''
338 HTTP status used by `globalRedirect` and `forceSSL`. Possible usecases
339 include temporary (302, 307) redirects, keeping the request method and
340 body (307, 308), or explicitly resetting the method to GET (303).
341 See <https://developer.mozilla.org/en-US/docs/Web/HTTP/Redirections>.
342 '';
343 };
344
345 basicAuth = mkOption {
346 type = types.attrsOf types.str;
347 default = { };
348 example = literalExpression ''
349 {
350 user = "password";
351 };
352 '';
353 description = ''
354 Basic Auth protection for a vhost.
355
356 WARNING: This is implemented to store the password in plain text in the
357 Nix store.
358 '';
359 };
360
361 basicAuthFile = mkOption {
362 type = types.nullOr types.path;
363 default = null;
364 description = ''
365 Basic Auth password file for a vhost.
366 Can be created by running {command}`nix-shell --packages apacheHttpd --run 'htpasswd -B -c FILENAME USERNAME'`.
367 '';
368 };
369
370 locations = mkOption {
371 type = types.attrsOf (
372 types.submodule (
373 import ./location-options.nix {
374 inherit lib config;
375 }
376 )
377 );
378 default = { };
379 example = literalExpression ''
380 {
381 "/" = {
382 proxyPass = "http://localhost:3000";
383 };
384 };
385 '';
386 description = "Declarative location config";
387 };
388 };
389}