Home Explore Blog Models CI



nixpkgs

4th chunk of `nixos/modules/security/acme/default.md`
fa3917bdd0d3fa6ee50f036f3b06e413db1dddac2eddba4e00000001000009b3
supported and part of the module's test suite for Nginx + Apache.

You must follow the guide above on configuring DNS-01 validation
first, however instead of setting the options for one certificate
(e.g. [](#opt-security.acme.certs._name_.dnsProvider))
you will set them as defaults
(e.g. [](#opt-security.acme.defaults.dnsProvider)).

```nix
{
  # Configure ACME appropriately
  security.acme.acceptTerms = true;
  security.acme.defaults.email = "admin+acme@example.com";
  security.acme.defaults = {
    dnsProvider = "rfc2136";
    environmentFile = "/var/lib/secrets/certs.secret";
    # We don't need to wait for propagation since this is a local DNS server
    dnsPropagationCheck = false;
  };

  # For each virtual host you would like to use DNS-01 validation with,
  # set acmeRoot = null
  services.nginx = {
    enable = true;
    virtualHosts = {
      "foo.example.com" = {
        enableACME = true;
        acmeRoot = null;
      };
    };
  };
}
```

And that's it! Next time your configuration is rebuilt, or when
you add a new virtualHost, it will be DNS-01 validated.

## Using ACME with services demanding root owned certificates {#module-security-acme-root-owned}

Some services refuse to start if the configured certificate files
are not owned by root. PostgreSQL and OpenSMTPD are examples of these.
There is no way to change the user the ACME module uses (it will always be
`acme`), however you can use systemd's
`LoadCredential` feature to resolve this elegantly.
Below is an example configuration for OpenSMTPD, but this pattern
can be applied to any service.

```nix
{
  # Configure ACME however you like (DNS or HTTP validation), adding
  # the following configuration for the relevant certificate.
  # Note: You cannot use `systemctl reload` here as that would mean
  # the LoadCredential configuration below would be skipped and
  # the service would continue to use old certificates.
  security.acme.certs."mail.example.com".postRun = ''
    systemctl restart opensmtpd
  '';

  # Now you must augment OpenSMTPD's systemd service to load
  # the certificate files.
  systemd.services.opensmtpd.requires = [ "acme-mail.example.com.service" ];
  systemd.services.opensmtpd.serviceConfig.LoadCredential =
    let
      certDir = config.security.acme.certs."mail.example.com".directory;
    in
    [
      "cert.pem:${certDir}/cert.pem"
      "key.pem:${certDir}/key.pem"
    ];

  # Finally, configure OpenSMTPD to use these certs.
  services.opensmtpd =

Title: NixOS ACME: DNS-01 Validation for Virtual Hosts and Root-Owned Certificates
Summary
This chunk details two advanced ACME configurations in NixOS. First, it explains how to apply DNS-01 validation to all virtual hosts by setting ACME options like `dnsProvider` and `environmentFile` in `security.acme.defaults`, and then setting `acmeRoot = null` for `services.nginx.virtualHosts` using `enableACME`. Second, it addresses the challenge of services (e.g., OpenSMTPD, PostgreSQL) that require root-owned certificates, which conflict with the `acme` user ownership. The solution leverages `systemd`'s `LoadCredential` feature: the ACME certificate's `postRun` restarts the service (rather than reloading) to ensure `LoadCredential` is applied, and the service's `systemd.services` configuration is augmented to `LoadCredential` the `cert.pem` and `key.pem` files from the ACME directory, making them accessible to the service without direct root ownership.