5.1 KiB
SSL Generator Block
This NixOS module is a block that implements the SSL certificate generator contract.
It is implemented by:
shb.certs.cas.selfsignedandshb.certs.certs.selfsigned: Generates self-signed certificates, including self-signed CA thanks to the certtool package.shb.certs.certs.letsencrypt: Requests certificates from Let's Encrypt.
Self-Signed Certificates
Defined in /modules/blocks/ssl.nix.
To use self-signed certificates, we must first generate at least one Certificate Authority (CA):
shb.certs.cas.selfsigned.myca = {
name = "My CA";
};
Every CA defined this way will be concatenated into the file /etc/ssl/certs/ca-certificates.cert
which means those CAs and all certificates generated by those CAs will be automatically trusted.
We can then generate one or more certificates signed by that CA:
shb.certs.certs.selfsigned = {
"example.com" = {
ca = config.shb.certs.cas.selfsigned.myca;
domain = "example.com";
group = "nginx";
reloadServices = [ "nginx.service" ];
};
"www.example.com" = {
ca = config.shb.certs.cas.selfsigned.myca;
domain = "www.example.com";
group = "nginx";
};
};
The group has been chosen to be nginx to be consistent with the examples further down in this
document.
Let's Encrypt
Defined in /modules/blocks/ssl.nix.
We can ask Let's Encrypt to generate a certificate with:
shb.certs.certs.letsencrypt."example.com" = {
domain = "example.com";
group = "nginx";
reloadServices = [ "nginx.service" ];
dnsProvider = "linode";
adminEmail = "admin@example.com";
credentialsFile = /path/to/secret/file;
additionalEnvironment = {
LINODE_HTTP_TIMEOUT = "10";
LINODE_POLLING_INTERVAL = "10";
LINODE_PROPAGATION_TIMEOUT = "240";
};
};
The credential file's content would be a key-value pair:
LINODE_TOKEN=XYZ...
If you use one subdomain per service, asking for certificates for a subdomain is done with:
shb.certs.certs.letsencrypt."example.com".extraDomains = [ "nextcloud.${domain}" ];
For other providers, see the official instruction.
Usage
To use either a self-signed certificates or a Let's Encrypt generated one, we can reference the path where the certificate and the private key are located:
config.shb.certs.certs.<implementation>.<name>.paths.cert
config.shb.certs.certs.<implementation>.<name>.paths.key
config.shb.certs.certs.<implementation>.<name>.systemdService
For example:
config.shb.certs.certs.selfsigned."example.com".paths.cert
config.shb.certs.certs.selfsigned."example.com".paths.key
config.shb.certs.certs.selfsigned."example.com".systemdService
The full CA bundle is generated by the following Systemd service, running after each individual generator finished:
config.shb.certs.systemdService
See also the SSL certificate generator usage for a more detailed usage example.
Monitoring
A dashboard for SSL certificates is provided. See SSL Certificates Dashboard and Alert section in the monitoring chapter.
Debug
Each CA and Cert is generated by a systemd service whose name can be seen in the systemdService
option. You can then see the latest errors messages using journalctl.
Let's Encrypt debug
Since the SHB SSL block uses the security.acme module under the hood,
knowing how that one works can become required if something goes wrong.
For each domain and subdomain, noted as fqdn hereunder,
the following systemd timers and services are created:
acme-renew-${fqdn}.timertriggers theacme-order-renew-${fqdn}.serviceservice every day.acme-${fqdn}.service(re)generate the initial self-signed certificate, only if the following job never succeeded at least once yet.acme-order-renew-${fqdn}.serviceasks for a new certificate only if the certificate will expire in the next 30 days. Has logic to only renew if the list of domains has not changed.
Also, a global service named acme-setup.service is created
Tests
The self-signed implementation is tested in /tests/vm/ssl.nix.
Options Reference
id-prefix: blocks-ssl-options-
list-id: selfhostblocks-options
source: @OPTIONS_JSON@