Let's encrypt offers free certificates that are (mostly) recognised and trusted by default on many platforms. Unfortunately, all issued certificates have a 90-day expiry time such that the procedure to renew the certificates must somehow be automated. These notes explain a way of setting up certbot to renew certificates.
Certbot requires:
although certbot can be configured with an embedded micro server based on nginx, these notes assume that a web server is configured on the machine using certbot.
The web server is needed for "Let's encrypt" to verify that the machine requesting the certificates is indeed the owner of the domain.
Certbot can be installed either manually by issuing:
wget https://dl.eff.org/certbot-auto chmod a+x certbot-auto
or installed via the distribution packaging system, for instance, on Debian, issue:
aptitude install certbot
which should pull all the necessary packages.
Since Certbot has to be made to run periodically to update the certificates, it is handy to create a configuration file at /etc/letsencrypt/cli.ini
with contents similar to:
# Use a 4096 bit RSA key instead of 2048. rsa-key-size = 4096 # Set email and domains. email = admin@mydomain.tld domains = mydomain.tld, www.mydomain.tld, mail.mydomain.tld, backup.mydomain.tld # Text interface. text = True # No prompts. non-interactive = True # Suppress the Terms of Service agreement interaction. agree-tos = True # Use the webroot authenticator. authenticator = webroot webroot-path = /var/www/
For the "Let's encrypt" verification to succeed, the created configuration will make Certbot place verification files under /var/www/.well-known/acme-challenge/
since webroot-path
is set to /var/www
.
Multiple domains can be configured via the domains
configuration key in the file above - at the time of writing, "Let's encrypt" does not offer wildcard certificates but they are planned for the future.
Notice that "Let's encrypt" certificates can also be used for other services such as mail servers (in fact, the configuration in the previous section, contains mail.mydomain.tld
which is meant to be a mail server MX domain) but that Certbot is configured with the webroot
authenticator which means that all the specified domains in /etc/letsencrypt/cli.ini
must be reachable via HTTP.
Furthermore, virtual domains do not necessarily share the same document root such that it is convenient for Apache to serve the verification files created by Certbot from a common document root.
To work around these issues, add a file at /etc/apache2/conf-available/letsencrypt.conf
with the following contents:
Alias "/.well-known/acme-challenge/" "/var/www/certbot/.well-known/acme-challenge/" <Directory "/var/www/certbot/.well-known/"> AllowOverride None Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec Require method GET POST OPTIONS </Directory> RewriteEngine On RewriteCond %{REQUEST_URI} !^/\.well-known/acme-challenge/.* RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [QSA,L,R=301]
and create the /var/www/certbot
directory:
mkdir -p /var/www/certbot
This configuration will be enabled for all domains and will allow Apache to serve the contents of the /var/www/certbot/.well-known/
directory when "Let's encrypt" verifies the server.
Finally, issue:
a2enconf letsencrypt
to enable the configuration and:
apachectl graceful
to make Apache reload the configuration.
Issuing:
certbot certonly --dry-run
should output something to the following:
Saving debug log to /var/log/letsencrypt/letsencrypt.log Cert not due for renewal, but simulating renewal for dry run Renewing an existing certificate Performing the following challenges: http-01 challenge for mydomain.tld http-01 challenge for www.mydomain.tld http-01 challenge for mail.mydomain.tld http-01 challenge for backup.mydomain.tld Using the webroot path /var/www/ for all unmatched domains. Waiting for verification... Cleaning up challenges Generating key (4096 bits): /etc/letsencrypt/keys/0010_key-certbot.pem Creating CSR: /etc/letsencrypt/csr/0010_csr-certbot.pem IMPORTANT NOTES: - The dry run was successful.
which indicates that the verification phase of "Let's encrypt" has succeeded and that certificates can be obtained.
Now that the test succeeded, issue the same command without the –dry-run
option:
certbot certonly
which should create certificates in /etc/letsencrypt/live/mydomain.tld/
where:
privkey.pem
will be the private key of the certificatefullchain.pem
is the full certificate chainchain.pem
contains additional intermediary certificates that might be needed to validate the server certificate and is also used for OCSP staplingcert.pem
is the server certificate
Now that the certificates are pulled to /etc/letsencrypt/live/mydomain.tld/
, various SSL-enabled services can be configured to read the certificates. It is a good idea to keep the certificates inside /etc/letsencrypt/live/mydomain.tld/
because they can then be renewed using Certbot without having to move files around.
For Dovecot, edit /etc/dovecot/conf.d/10-ssl.conf
and edit the configuration to set ssl_cert
and ssl_key
:
ssl_cert = </etc/letsencrypt/live/mydomain.tld/fullchain.pem ssl_key = </etc/letsencrypt/live/mydomain.tld/privkey.pem
Note that it is preferable to always use the full certificate chain instead of providing the additional intermediary certificates every time.
For Postfix, edit /etc/postfix/main.cf
and add or edit the smtpd_tls_cert_file
and smtpd_tls_key_file
:
smtpd_tls_cert_file=/etc/letsencrypt/live/mydomain.tld/fullchain.pem smtpd_tls_key_file=/etc/letsencrypt/live/mydomain.tld/privkey.pem
Assuming an Apache version over or equal to 2.4.8
, edit the SSL virtual domain file(s) and add:
SSLEngine on SSLCertificateFile /etc/letsencrypt/live/mydomain.tld/fullchain.pem SSLCertificateKeyFile /etc/letsencrypt/live/mydomain.tld/privkey.pem
Even though the name "Certbot" would imply the automation of certificate renewals, "Certbot" only really automates pulling certificates from "Let's encrypt" and renewing certifiacates that are found to be old - however, issuing the command has performed manually. That is, the "auto-renewal" feature of "Certbot" just means that when running Certbot, old certificates will be renewed but that does not mean that Certbot will run in the background and automatically renew certificates when they expire - as the name would imply (which is terrible). . .
Using crontab, create a script at /etc/cron.hourly/certbot-renewal
with the following contents:
#!/bin/sh ########################################################################### ## Copyright (C) Wizardry and Steamworks 2017 - License: GNU GPLv3 ## ########################################################################### # Script to renew certbot let's encrypt certificates and reload daemons. # ########################################################################### ### Renew certificates and exit if the certificates are already up to date. RENEW=`certbot certonly 2>&1 | grep -i 'Keeping the existing certificate'` if [ ! -z "$RENEW" ]; then exit 0 fi ### Reload all services using the certificates. # reload postfix postfix reload # reload dovecot doveadm reload # reload apache apachectl graceful
and edit the last section to reload all daemons that have certificates installed.