diff --git a/nixos/modules/security/acme.nix b/nixos/modules/security/acme.nix
index 82cd6431ad10..776ef07d716c 100644
--- a/nixos/modules/security/acme.nix
+++ b/nixos/modules/security/acme.nix
@@ -87,13 +87,13 @@ let
default = {};
example = literalExample ''
{
- "example.org" = "/srv/http/nginx";
+ "example.org" = null;
"mydomain.org" = null;
}
'';
description = ''
- A list of extra domain names, which are included in the one certificate to be issued, with their
- own server roots if needed.
+ A list of extra domain names, which are included in the one certificate to be issued.
+ Setting a distinct server root is deprecated and not functional in 20.03+
'';
};
@@ -250,7 +250,7 @@ in
"example.com" = {
webroot = "/var/www/challenges/";
email = "foo@example.com";
- extraDomains = { "www.example.com" = null; "foo.example.com" = "/var/www/foo/"; };
+ extraDomains = { "www.example.com" = null; "foo.example.com" = null; };
};
"bar.example.com" = {
webroot = "/var/www/challenges/";
diff --git a/nixos/modules/security/acme.xml b/nixos/modules/security/acme.xml
index 2b29c1174845..f802faee9749 100644
--- a/nixos/modules/security/acme.xml
+++ b/nixos/modules/security/acme.xml
@@ -6,65 +6,49 @@
SSL/TLS Certificates with ACME
NixOS supports automatic domain validation & certificate retrieval and
- renewal using the ACME protocol. This is currently only implemented by and
- for Let's Encrypt. The alternative ACME client lego is
- used under the hood.
+ renewal using the ACME protocol. Any provider can be used, but by default
+ NixOS uses Let's Encrypt. The alternative ACME client lego
+ is used under the hood.
+
+
+ Automatic cert validation and configuration for Apache and Nginx virtual
+ hosts is included in NixOS, however if you would like to generate a wildcard
+ cert or you are not using a web server you will have to configure DNS
+ based validation.
Prerequisites
- You need to have a running HTTP server for verification. The server must
- have a webroot defined that can serve
+ To use the ACME module, you must accept the provider's terms of service
+ by setting
+ to true. The Let's Encrypt ToS can be found
+ here.
+
+
+
+ You must also set an email address to be used when creating accounts with
+ Let's Encrypt. You can set this for all certs with
+
+ and/or on a per-cert basis with
+ .
+ This address is only used for registration and renewal reminders,
+ and cannot be used to administer the certificates in any way.
+
+
+
+ Alternatively, you can use a different ACME server by changing the
+ option
+ to a provider of your choosing, or just change the server for one cert with
+ .
+
+
+
+ You will need an HTTP server or DNS server for verification. For HTTP,
+ the server must have a webroot defined that can serve
.well-known/acme-challenge. This directory must be
- writeable by the user that will run the ACME client.
-
-
-
- For instance, this generic snippet could be used for Nginx:
-
-http {
- server {
- server_name _;
- listen 80;
- listen [::]:80;
-
- location /.well-known/acme-challenge {
- root /var/www/challenges;
- }
-
- location / {
- return 301 https://$host$request_uri;
- }
- }
-}
-
-
-
-
- Configuring
-
-
- To enable ACME certificate retrieval & renewal for a certificate for
- foo.example.com, add the following in your
- configuration.nix:
-
-."foo.example.com" = {
- webroot = "/var/www/challenges";
- email = "foo@example.com";
-};
-
-
-
-
- The private key key.pem and certificate
- fullchain.pem will be put into
- /var/lib/acme/foo.example.com.
-
-
- Refer to for all available configuration
- options for the security.acme
- module.
+ writeable by the user that will run the ACME client. For DNS, you must
+ set up credentials with your provider/server for use with lego.
@@ -80,12 +64,27 @@ http {
+ = true;
+ = "admin+acme@example.com";
services.nginx = {
- enable = true;
+ enable = true;
virtualHosts = {
"foo.example.com" = {
forceSSL = true;
enableACME = true;
+ # All serverAliases will be added as extra domains on the certificate.
+ serverAliases = [ "bar.example.com" ];
+ locations."/" = {
+ root = "/var/www";
+ };
+ };
+
+ # We can also add a different vhost and reuse the same certificate
+ # but we have to append extraDomains manually.
+ security.acme.certs."foo.example.com".extraDomains."baz.example.com" = null;
+ "baz.example.com" = {
+ forceSSL = true;
+ useACMEHost = "foo.example.com";
locations."/" = {
root = "/var/www";
};
@@ -94,4 +93,162 @@ services.nginx = {
}
+
+ Using ACME certificates in Apache/httpd
+
+
+ Using ACME certificates with Apache virtual hosts is identical
+ to using them with Nginx. The attribute names are all the same, just replace
+ "nginx" with "httpd" where appropriate.
+
+
+
+ Manual configuration of HTTP-01 validation
+
+
+ First off you will need to set up a virtual host to serve the challenges.
+ This example uses a vhost called certs.example.com, with
+ the intent that you will generate certs for all your vhosts and redirect
+ everyone to HTTPS.
+
+
+
+ = true;
+ = "admin+acme@example.com";
+services.nginx = {
+ enable = true;
+ virtualHosts = {
+ "acmechallenge.example.com" = {
+ # Catchall vhost, will redirect users to HTTPS for all vhosts
+ serverAliases = [ "*.example.com" ];
+ # /var/lib/acme/.challenges must be writable by the ACME user
+ # and readable by the Nginx user.
+ # By default, this is the case.
+ locations."/.well-known/acme-challenge" = {
+ root = "/var/lib/acme/.challenges";
+ };
+ locations."/" = {
+ return = "301 https://$host$request_uri";
+ };
+ };
+ };
+}
+# Alternative config for Apache
+services.httpd = {
+ enable = true;
+ virtualHosts = {
+ "acmechallenge.example.com" = {
+ # Catchall vhost, will redirect users to HTTPS for all vhosts
+ serverAliases = [ "*.example.com" ];
+ # /var/lib/acme/.challenges must be writable by the ACME user and readable by the Apache user.
+ # By default, this is the case.
+ documentRoot = "/var/lib/acme/.challenges";
+ extraConfig = ''
+ RewriteEngine On
+ RewriteCond %{HTTPS} off
+ RewriteCond %{REQUEST_URI} !^/\.well-known/acme-challenge [NC]
+ RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301]
+ '';
+ };
+ };
+}
+
+
+
+ Now you need to configure ACME to generate a certificate.
+
+
+
+."foo.example.com" = {
+ webroot = "/var/lib/acme/.challenges";
+ email = "foo@example.com";
+ # Since we have a wildcard vhost to handle port 80,
+ # we can generate certs for anything!
+ # Just make sure your DNS resolves them.
+ extraDomains = [ "mail.example.com" ];
+};
+
+
+
+ The private key key.pem and certificate
+ fullchain.pem will be put into
+ /var/lib/acme/foo.example.com.
+
+
+
+ Refer to for all available configuration
+ options for the security.acme
+ module.
+
+
+
+ Configuring ACME for DNS validation
+
+
+ This is useful if you want to generate a wildcard certificate, since
+ ACME servers will only hand out wildcard certs over DNS validation.
+ There a number of supported DNS providers and servers you can utilise,
+ see the lego docs
+ for provider/server specific configuration values. For the sake of these
+ docs, we will provide a fully self-hosted example using bind.
+
+
+
+services.bind = {
+ enable = true;
+ extraConfig = ''
+ include "/var/lib/secrets/dnskeys.conf";
+ '';
+ zones = [
+ rec {
+ name = "example.com";
+ file = "/var/db/bind/${name}";
+ master = true;
+ extraConfig = "allow-update { key rfc2136key.example.com.; };";
+ }
+ ];
+}
+
+# Now we can configure ACME
+ = true;
+ = "admin+acme@example.com";
+."example.com" = {
+ domain = "*.example.com";
+ dnsProvider = "rfc2136";
+ credentialsFile = "/var/lib/secrets/certs.secret";
+ # We don't need to wait for propagation since this is a local DNS server
+ dnsPropagationCheck = false;
+};
+
+
+
+ The dnskeys.conf and certs.secret
+ must be kept secure and thus you should not keep their contents in your
+ Nix config. Instead, generate them one time with these commands:
+
+
+
+mkdir -p /var/lib/secrets
+tsig-keygen rfc2136key.example.com > /var/lib/secrets/dnskeys.conf
+chown named:root /var/lib/secrets/dnskeys.conf
+chmod 400 /var/lib/secrets/dnskeys.conf
+
+# Copy the secret value from the dnskeys.conf, and put it in
+# RFC2136_TSIG_SECRET below
+
+cat > /var/lib/secrets/certs.secret << EOF
+RFC2136_NAMESERVER='127.0.0.1:53'
+RFC2136_TSIG_ALGORITHM='hmac-sha256.'
+RFC2136_TSIG_KEY='rfc2136key.example.com'
+RFC2136_TSIG_SECRET='your secret key'
+EOF
+chmod 400 /var/lib/secrets/certs.secret
+
+
+
+ Now you're all set to generate certs! You should monitor the first invokation
+ by running systemctl start acme-example.com.service &
+ journalctl -fu acme-example.com.service and watching its log output.
+
+