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{ 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 = ["www.example.org" "example.org"];
24 description = ''
25 Additional names of virtual hosts served by this virtual host configuration.
26 '';
27 };
28
29 listen = mkOption {
30 type = with types; listOf (submodule { options = {
31 addr = mkOption { type = str; description = "IP address."; };
32 port = mkOption { type = int; description = "Port number."; default = 80; };
33 ssl = mkOption { type = bool; description = "Enable SSL."; default = false; };
34 extraParameters = mkOption { type = listOf str; description = "Extra parameters of this listen directive."; default = []; example = [ "reuseport" "deferred" ]; };
35 }; });
36 default = [];
37 example = [
38 { addr = "195.154.1.1"; port = 443; ssl = true;}
39 { addr = "192.154.1.1"; port = 80; }
40 ];
41 description = ''
42 Listen addresses and ports for this virtual host.
43 IPv6 addresses must be enclosed in square brackets.
44 Note: this option overrides <literal>addSSL</literal>
45 and <literal>onlySSL</literal>.
46
47 If you only want to set the addresses manually and not
48 the ports, take a look at <literal>listenAddresses</literal>
49 '';
50 };
51
52 listenAddresses = mkOption {
53 type = with types; listOf str;
54
55 description = ''
56 Listen addresses for this virtual host.
57 Compared to <literal>listen</literal> this only sets the addreses
58 and the ports are choosen automatically.
59
60 Note: This option overrides <literal>enableIPv6</literal>
61 '';
62 default = [];
63 example = [ "127.0.0.1" "::1" ];
64 };
65
66 enableACME = mkOption {
67 type = types.bool;
68 default = false;
69 description = ''
70 Whether to ask Let's Encrypt to sign a certificate for this vhost.
71 Alternately, you can use an existing certificate through <option>useACMEHost</option>.
72 '';
73 };
74
75 useACMEHost = mkOption {
76 type = types.nullOr types.str;
77 default = null;
78 description = ''
79 A host of an existing Let's Encrypt certificate to use.
80 This is useful if you have many subdomains and want to avoid hitting the
81 <link xlink:href="https://letsencrypt.org/docs/rate-limits/">rate limit</link>.
82 Alternately, you can generate a certificate through <option>enableACME</option>.
83 <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>
84 '';
85 };
86
87 acmeRoot = mkOption {
88 type = types.str;
89 default = "/var/lib/acme/acme-challenge";
90 description = "Directory for the acme challenge which is PUBLIC, don't put certs or keys in here";
91 };
92
93 acmeFallbackHost = mkOption {
94 type = types.nullOr types.str;
95 default = null;
96 description = ''
97 Host which to proxy requests to if acme challenge is not found. Useful
98 if you want multiple hosts to be able to verify the same domain name.
99 '';
100 };
101
102 addSSL = mkOption {
103 type = types.bool;
104 default = false;
105 description = ''
106 Whether to enable HTTPS in addition to plain HTTP. This will set defaults for
107 <literal>listen</literal> to listen on all interfaces on the respective default
108 ports (80, 443).
109 '';
110 };
111
112 onlySSL = mkOption {
113 type = types.bool;
114 default = false;
115 description = ''
116 Whether to enable HTTPS and reject plain HTTP connections. This will set
117 defaults for <literal>listen</literal> to listen on all interfaces on port 443.
118 '';
119 };
120
121 enableSSL = mkOption {
122 type = types.bool;
123 visible = false;
124 default = false;
125 };
126
127 forceSSL = mkOption {
128 type = types.bool;
129 default = false;
130 description = ''
131 Whether to add a separate nginx server block that permanently redirects (301)
132 all plain HTTP traffic to HTTPS. This will set defaults for
133 <literal>listen</literal> to listen on all interfaces on the respective default
134 ports (80, 443), where the non-SSL listens are used for the redirect vhosts.
135 '';
136 };
137
138 rejectSSL = mkOption {
139 type = types.bool;
140 default = false;
141 description = ''
142 Whether to listen for and reject all HTTPS connections to this vhost. Useful in
143 <link linkend="opt-services.nginx.virtualHosts._name_.default">default</link>
144 server blocks to avoid serving the certificate for another vhost. Uses the
145 <literal>ssl_reject_handshake</literal> directive available in nginx versions
146 1.19.4 and above.
147 '';
148 };
149
150 sslCertificate = mkOption {
151 type = types.path;
152 example = "/var/host.cert";
153 description = "Path to server SSL certificate.";
154 };
155
156 sslCertificateKey = mkOption {
157 type = types.path;
158 example = "/var/host.key";
159 description = "Path to server SSL certificate key.";
160 };
161
162 sslTrustedCertificate = mkOption {
163 type = types.nullOr types.path;
164 default = null;
165 example = literalExpression ''"''${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt"'';
166 description = "Path to root SSL certificate for stapling and client certificates.";
167 };
168
169 http2 = mkOption {
170 type = types.bool;
171 default = true;
172 description = ''
173 Whether to enable HTTP 2.
174 Note that (as of writing) due to nginx's implementation, to disable
175 HTTP 2 you have to disable it on all vhosts that use a given
176 IP address / port.
177 If there is one server block configured to enable http2,then it is
178 enabled for all server blocks on this IP.
179 See https://stackoverflow.com/a/39466948/263061.
180 '';
181 };
182
183 http3 = mkOption {
184 type = types.bool;
185 default = false;
186 description = ''
187 Whether to enable HTTP 3.
188 This requires using <literal>pkgs.nginxQuic</literal> package
189 which can be achieved by setting <literal>services.nginx.package = pkgs.nginxQuic;</literal>.
190 Note that HTTP 3 support is experimental and
191 *not* yet recommended for production.
192 Read more at https://quic.nginx.org/
193 '';
194 };
195
196 root = mkOption {
197 type = types.nullOr types.path;
198 default = null;
199 example = "/data/webserver/docs";
200 description = ''
201 The path of the web root directory.
202 '';
203 };
204
205 default = mkOption {
206 type = types.bool;
207 default = false;
208 description = ''
209 Makes this vhost the default.
210 '';
211 };
212
213 extraConfig = mkOption {
214 type = types.lines;
215 default = "";
216 description = ''
217 These lines go to the end of the vhost verbatim.
218 '';
219 };
220
221 globalRedirect = mkOption {
222 type = types.nullOr types.str;
223 default = null;
224 example = "newserver.example.org";
225 description = ''
226 If set, all requests for this host are redirected permanently to
227 the given hostname.
228 '';
229 };
230
231 basicAuth = mkOption {
232 type = types.attrsOf types.str;
233 default = {};
234 example = literalExpression ''
235 {
236 user = "password";
237 };
238 '';
239 description = ''
240 Basic Auth protection for a vhost.
241
242 WARNING: This is implemented to store the password in plain text in the
243 Nix store.
244 '';
245 };
246
247 basicAuthFile = mkOption {
248 type = types.nullOr types.path;
249 default = null;
250 description = ''
251 Basic Auth password file for a vhost.
252 Can be created via: <command>htpasswd -c <filename> <username></command>.
253
254 WARNING: The generate file contains the users' passwords in a
255 non-cryptographically-securely hashed way.
256 '';
257 };
258
259 locations = mkOption {
260 type = types.attrsOf (types.submodule (import ./location-options.nix {
261 inherit lib;
262 }));
263 default = {};
264 example = literalExpression ''
265 {
266 "/" = {
267 proxyPass = "http://localhost:3000";
268 };
269 };
270 '';
271 description = "Declarative location config";
272 };
273 };
274}