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
-
shb.certs.enableDashboard -
Whether to enable the SSL SHB dashboard.
Type: boolean
Default:
trueExample:
trueDeclared by:
<selfhostblocks/modules/blocks/ssl.nix> -
shb.certs.cas.selfsigned -
Generate a self-signed Certificate Authority.
Type: attribute set of (submodule)
Default:
{ }Declared by:
<selfhostblocks/modules/blocks/ssl.nix> -
shb.certs.cas.selfsigned.<name>.name -
Certificate Authority Name. You can put what you want here, it will be displayed by the browser.
Type: string
Default:
"Self Host Blocks Certificate"Declared by:
<selfhostblocks/modules/blocks/ssl.nix> -
shb.certs.cas.selfsigned.<name>.paths -
Paths where CA certs will be located.
This option implements the SSL Generator contract.
Type: open submodule of anything
Default:
{ cert = "/var/lib/certs/cas/‹name›.cert"; key = "/var/lib/certs/cas/‹name›.key"; }Declared by:
<selfhostblocks/modules/blocks/ssl.nix> -
shb.certs.cas.selfsigned.<name>.paths.cert -
Path to the cert file.
Type: absolute path
Declared by:
<selfhostblocks/modules/blocks/ssl.nix> -
shb.certs.cas.selfsigned.<name>.paths.key -
Path to the key file.
Type: absolute path
Declared by:
<selfhostblocks/modules/blocks/ssl.nix> -
shb.certs.cas.selfsigned.<name>.systemdService -
Systemd oneshot service used to generate the certs.
This option implements the SSL Generator contract.
Type: string
Default:
"shb-certs-ca-‹name›.service"Declared by:
<selfhostblocks/modules/blocks/ssl.nix> -
shb.certs.certs.letsencrypt -
Generate certificates signed by Let’s Encrypt.
Type: attribute set of (submodule)
Default:
{ }Declared by:
<selfhostblocks/modules/blocks/ssl.nix> -
shb.certs.certs.letsencrypt.<name>.additionalEnvironment -
Additional environment variables used to configure the DNS provider.
For secrets, use shb.ssl.credentialsFile instead.
See the chosen provider’s documentation for available options.
Type: attribute set of string
Default:
{ }Example:
{ DNSPROVIDER_TIMEOUT = "10"; DNSPROVIDER_PROPAGATION_TIMEOUT = "240"; }Declared by:
<selfhostblocks/modules/blocks/ssl.nix> -
shb.certs.certs.letsencrypt.<name>.adminEmail -
Admin email in case certificate retrieval goes wrong.
Type: string
Declared by:
<selfhostblocks/modules/blocks/ssl.nix> -
shb.certs.certs.letsencrypt.<name>.afterAndWants -
Systemd service(s) that must start successfully before attempting to reach acme.
Type: list of string
Default:
[ ]Example:
[ "dnsmasq.service" ]Declared by:
<selfhostblocks/modules/blocks/ssl.nix> -
shb.certs.certs.letsencrypt.<name>.credentialsFile -
Credentials file location for the chosen DNS provider.
The content of this file must expose environment variables as written in the documentation of each DNS provider.
For example, if the documentation says the credential must be located in the environment variable DNSPROVIDER_TOKEN, then the file content must be:
DNSPROVIDER_TOKEN=xyz
You can put non-secret environment variables here too or use shb.ssl.additionalcfg instead.
Type: null or absolute path
Default:
nullExample:
"/run/secrets/ssl"Declared by:
<selfhostblocks/modules/blocks/ssl.nix> -
shb.certs.certs.letsencrypt.<name>.debug -
Enable debug logging
Type: boolean
Default:
falseDeclared by:
<selfhostblocks/modules/blocks/ssl.nix> -
shb.certs.certs.letsencrypt.<name>.dnsProvider -
DNS provider to use.
See https://go-acme.github.io/lego/dns/ for the list of supported providers.
If null is given, use instead the reverse proxy to validate the domain.
Type: null or string
Default:
nullExample:
"linode"Declared by:
<selfhostblocks/modules/blocks/ssl.nix> -
shb.certs.certs.letsencrypt.<name>.dnsResolver -
IP of a DNS server used to resolve hostnames.
Type: string
Default:
"8.8.8.8"Declared by:
<selfhostblocks/modules/blocks/ssl.nix> -
shb.certs.certs.letsencrypt.<name>.domain -
Domain to generate a certificate for. This can be a wildcard domain like
*.example.com.Type: string
Example:
"example.com"Declared by:
<selfhostblocks/modules/blocks/ssl.nix> -
shb.certs.certs.letsencrypt.<name>.extraDomains -
Other domains to generate a certificate for.
Type: list of string
Default:
[ ]Example:
[ "sub1.example.com" "sub2.example.com" ]Declared by:
<selfhostblocks/modules/blocks/ssl.nix> -
shb.certs.certs.letsencrypt.<name>.group -
Unix group owning this certificate.
Type: null or string
Default:
"acme"Example:
"nginx"Declared by:
<selfhostblocks/modules/blocks/ssl.nix> -
shb.certs.certs.letsencrypt.<name>.makeAvailableToUser -
Make all certificates available to given user.
Type: null or string
Default:
nullDeclared by:
<selfhostblocks/modules/blocks/ssl.nix> -
shb.certs.certs.letsencrypt.<name>.paths -
Paths where certs will be located.
This option implements the SSL Generator contract.
Type: open submodule of anything
Default:
{ cert = "/var/lib/acme/‹name›/cert.pem"; key = "/var/lib/acme/‹name›/key.pem"; }Declared by:
<selfhostblocks/modules/blocks/ssl.nix> -
shb.certs.certs.letsencrypt.<name>.paths.cert -
Path to the cert file.
Type: absolute path
Declared by:
<selfhostblocks/modules/blocks/ssl.nix> -
shb.certs.certs.letsencrypt.<name>.paths.key -
Path to the key file.
Type: absolute path
Declared by:
<selfhostblocks/modules/blocks/ssl.nix> -
shb.certs.certs.letsencrypt.<name>.reloadServices -
The list of systemd services to call
systemctl try-reload-or-restarton.Type: list of string
Default:
[ ]Example:
[ "nginx.service" ]Declared by:
<selfhostblocks/modules/blocks/ssl.nix> -
shb.certs.certs.letsencrypt.<name>.stagingServer -
User Let’s Encrypt’s staging server.
Type: boolean
Default:
falseDeclared by:
<selfhostblocks/modules/blocks/ssl.nix> -
shb.certs.certs.letsencrypt.<name>.systemdService -
Systemd oneshot service used to generate the certs.
This option implements the SSL Generator contract.
Type: string
Default:
"shb-certs-cert-letsencrypt-‹name›.service"Declared by:
<selfhostblocks/modules/blocks/ssl.nix> -
shb.certs.certs.selfsigned -
Generate self-signed certificates signed by a Certificate Authority.
Type: attribute set of (submodule)
Default:
{ }Declared by:
<selfhostblocks/modules/blocks/ssl.nix> -
shb.certs.certs.selfsigned.<name>.ca -
CA used to generate this certificate. Only used for self-signed.
This contract input takes the contract output of the
shb.certs.casSSL block.Type: null or (open submodule of anything)
Default:
nullDeclared by:
<selfhostblocks/modules/blocks/ssl.nix> -
shb.certs.certs.selfsigned.<name>.ca.paths -
Paths where the files for the CA will be located.
This option is the contract output of the
shb.certs.casSSL block.Type: open submodule of anything
Declared by:
<selfhostblocks/modules/blocks/ssl.nix> -
shb.certs.certs.selfsigned.<name>.ca.paths.cert -
Path to the cert file.
Type: absolute path
Declared by:
<selfhostblocks/modules/blocks/ssl.nix> -
shb.certs.certs.selfsigned.<name>.ca.paths.key -
Path to the key file.
Type: absolute path
Declared by:
<selfhostblocks/modules/blocks/ssl.nix> -
shb.certs.certs.selfsigned.<name>.ca.systemdService -
Systemd oneshot service used to generate the CA. Ends with the
.servicesuffix.Use this if downstream services must wait for the certificates to be generated before starting.
Type: string
Example:
"ca-generator.service"Declared by:
<selfhostblocks/modules/blocks/ssl.nix> -
shb.certs.certs.selfsigned.<name>.domain -
Domain to generate a certificate for. This can be a wildcard domain like
*.example.com.Type: string
Example:
"example.com"Declared by:
<selfhostblocks/modules/blocks/ssl.nix> -
shb.certs.certs.selfsigned.<name>.extraDomains -
Other domains to generate a certificate for.
Type: list of string
Default:
[ ]Example:
[ "sub1.example.com" "sub2.example.com" ]Declared by:
<selfhostblocks/modules/blocks/ssl.nix> -
shb.certs.certs.selfsigned.<name>.group -
Unix group owning this certificate.
Type: string
Default:
"root"Example:
"nginx"Declared by:
<selfhostblocks/modules/blocks/ssl.nix> -
shb.certs.certs.selfsigned.<name>.paths -
Paths where certs will be located.
This option implements the SSL Generator contract.
Type: open submodule of anything
Default:
{ cert = "/var/lib/certs/selfsigned/‹name›.cert"; key = "/var/lib/certs/selfsigned/‹name›.key"; }Declared by:
<selfhostblocks/modules/blocks/ssl.nix> -
shb.certs.certs.selfsigned.<name>.paths.cert -
Path to the cert file.
Type: absolute path
Declared by:
<selfhostblocks/modules/blocks/ssl.nix> -
shb.certs.certs.selfsigned.<name>.paths.key -
Path to the key file.
Type: absolute path
Declared by:
<selfhostblocks/modules/blocks/ssl.nix> -
shb.certs.certs.selfsigned.<name>.reloadServices -
The list of systemd services to call
systemctl try-reload-or-restarton.Type: list of string
Default:
[ ]Example:
[ "nginx.service" ]Declared by:
<selfhostblocks/modules/blocks/ssl.nix> -
shb.certs.certs.selfsigned.<name>.systemdService -
Systemd oneshot service used to generate the certs.
This option implements the SSL Generator contract.
Type: string
Default:
"shb-certs-cert-selfsigned-‹name›.service"Declared by:
<selfhostblocks/modules/blocks/ssl.nix> -
shb.certs.systemdService -
Systemd oneshot service used to generate the Certificate Authority bundle.
Type: string
Default:
"shb-ca-bundle.service"Declared by:
<selfhostblocks/modules/blocks/ssl.nix>