# SSL/TLS Certificates with ACME {#module-security-acme}
NixOS supports automatic domain validation & certificate retrieval and
renewal using the ACME protocol. Any provider can be used, but by default
NixOS uses Let's Encrypt. The alternative ACME client
[lego](https://go-acme.github.io/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 {#module-security-acme-prerequisites}
To use the ACME module, you must accept the provider's terms of service
by setting [](#opt-security.acme.acceptTerms)
to `true`. The Let's Encrypt ToS can be found
[here](https://letsencrypt.org/repository/).
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
[](#opt-security.acme.defaults.email)
and/or on a per-cert basis with
[](#opt-security.acme.certs._name_.email).
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
[](#opt-security.acme.defaults.server) option
to a provider of your choosing, or just change the server for one cert with
[](#opt-security.acme.certs._name_.server).
You will need an HTTP server or DNS server for verification. For HTTP,
the server must have a webroot defined that can serve
{file}`.well-known/acme-challenge`. This directory must be
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.
## Using ACME certificates in Nginx {#module-security-acme-nginx}
NixOS supports fetching ACME certificates for you by setting
`enableACME = true;` in a virtualHost config. We first create self-signed
placeholder certificates in place of the real ACME certs. The placeholder
certs are overwritten when the ACME certs arrive. For
`foo.example.com` the config would look like this:
```nix
{
security.acme.acceptTerms = true;
security.acme.defaults.email = "admin+acme@example.com";
services.nginx = {
enable = true;
virtualHosts = {
"foo.example.com" = {
forceSSL = true;
enableACME = true;
# All serverAliases will be added as extra domain names 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 extraDomainNames manually beforehand:
# security.acme.certs."foo.example.com".extraDomainNames = [ "baz.example.com" ];
"baz.example.com" = {
forceSSL = true;
useACMEHost = "foo.example.com";
locations."/" = {
root = "/var/www";
};
};
};
};
}
```
## Using ACME certificates in Apache/httpd {#module-security-acme-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 {#module-security-acme-configuring}
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.
```nix
{
security.acme.acceptTerms = true;
security.acme.defaults.email = "admin+acme@example.com";
# /var/lib/acme/.challenges must be writable by the ACME user
# and readable by the Nginx user. The easiest way to achieve
# this is to add the Nginx user to the ACME group.
users.users.nginx.extraGroups = [ "acme" ];
services.nginx = {
enable = true;
virtualHosts = {
"acmechallenge.example.com" = {
# Catchall vhost, will redirect users to HTTPS for all vhosts