# SSL Generator Block {#block-ssl} This NixOS module is a block that implements the [SSL certificate generator](contracts-ssl.html) contract. It is implemented by: - [`shb.certs.cas.selfsigned`][10] and [`shb.certs.certs.selfsigned`][11]: Generates self-signed certificates, including self-signed CA thanks to the [certtool][1] package. - [`shb.certs.certs.letsencrypt`][12]: Requests certificates from [Let's Encrypt][2]. [1]: https://search.nixos.org/packages?channel=23.11&show=gnutls&from=0&size=50&sort=relevance&type=packages&query=certtool [2]: https://letsencrypt.org/ [10]: blocks-ssl.html#blocks-ssl-options-shb.certs.cas.selfsigned [11]: blocks-ssl.html#blocks-ssl-options-shb.certs.certs.selfsigned [12]: blocks-ssl.html#blocks-ssl-options-shb.certs.certs.letsencrypt ## Self-Signed Certificates {#block-ssl-impl-self-signed} Defined in [`/modules/blocks/ssl.nix`](@REPO@/modules/blocks/ssl.nix). To use self-signed certificates, we must first generate at least one Certificate Authority (CA): ```nix 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: ```nix 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 {#block-ssl-impl-lets-encrypt} Defined in [`/modules/blocks/ssl.nix`](@REPO@/modules/blocks/ssl.nix). We can ask Let's Encrypt to generate a certificate with: ```nix 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: ```yaml LINODE_TOKEN=XYZ... ``` If you use one subdomain per service, asking for certificates for a subdomain is done with: ```nix shb.certs.certs.letsencrypt."example.com".extraDomains = [ "nextcloud.${domain}" ]; ``` For other providers, see the [official instruction](https://go-acme.github.io/lego/dns/). ## Usage {#block-ssl-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: ```nix config.shb.certs.certs...paths.cert config.shb.certs.certs...paths.key config.shb.certs.certs...systemdService ``` For example: ```nix 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: ```nix config.shb.certs.systemdService ``` See also the [SSL certificate generator usage](contracts-ssl.html#ssl-contract-usage) for a more detailed usage example. ## Monitoring {#blocks-ssl-monitoring} A dashboard for SSL certificates is provided. See [SSL Certificates Dashboard and Alert](blocks-monitoring.html#blocks-monitoring-ssl) section in the monitoring chapter. ## Debug {#block-ssl-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 {#blocks-ssl-debug-lets-encrypt} 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}.timer` triggers the `acme-order-renew-${fqdn}.service` service 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}.service` asks 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 [`security.acme`]: https://nixos.org/manual/nixos/stable/#module-security-acme ## Tests {#block-ssl-tests} The self-signed implementation is tested in [`/tests/vm/ssl.nix`](@REPO@/tests/vm/ssl.nix). ## Options Reference {#block-ssl-options} ```{=include=} options id-prefix: blocks-ssl-options- list-id: selfhostblocks-options source: @OPTIONS_JSON@ ```