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