On my Debian mail server and web server, I’m using Let’s Encrypt SSL certificates to provide secure communication between clients and my mail and web services.
In this article, I’ll describe how to setup an automatic SSL certificate renewal solution.
Debian provides the Let’s Encrypt client certbot via its official APT repositories, we can simply install it using: apt install certbot
Setting up the certificates for a given domain is as easy as executing the following command (here, I’m creating a certificate for the common name “mail.heissler.at”, which is the address of my mail server; a similar command has been executed on the web server):
/usr/bin/certbot certonly --webroot --cert-name mail.heissler.at -w /var/www/html -w /var/www/html -d mail.heissler.at
Certbot then communicates with Let’s Encrypt to request the certificates and perform any necessary challenges as defined in the ACME standard (see https://letsencrypt.org/docs/challenge-types/). In our case, ownership can be proven through the HTTP challenge, which automatically adds a file on our web server (e.g. /var/www/html/.well-known/acme-challenge/<token>
).
If everything went ok, Certbot confirms that the certificates are enabled and outputs the details.
After deploying these certificates, we must ensure that they are renewed every 3 months.
As the Debian comes with systemd as the init system, a systemd service and timer has been configured and activated during certbot package installation to automatically renew the certificates using the certbot client. Thus, no cron job scheduling is required anymore.
The certbot timer configuration for systemd /etc/systemd/system/timers.target.wants/certbot.timer
looks as follows (here, it checks twice a day if certificates are due to renewal):
[Unit]
Description=Run certbot twice daily
[Timer]
OnCalendar=*-*-* 00,12:00:00
RandomizedDelaySec=43200
Persistent=true
[Install]
WantedBy=timers.target
You can check the status of the certbot systemd timer by executing systemctl status certbot.timer:
● certbot.timer - Run certbot twice daily
Loaded: loaded (/lib/systemd/system/certbot.timer; enabled; vendor preset: enabled)
Active: active (waiting) since Thu 2021-06-12 18:40:09 UTC; 7 days ago
Trigger: Sat 2021-06-19 19:25:28 UTC; 5h 14min left
To ensure, that all services which are relying on the SSL certificates are picking up the changes, I’ve configured certbot to use so-called renew hooks (you can find more details in the offical certbot docs).
I’ve configured the post renewal hook for the mail server as follows in /etc/letsencrypt/renewal-hooks/post/01_install_mail_cert.sh
:
#!/bin/bash
set -e
case $RENEWED_DOMAINS in
*)
cat $RENEWED_LINEAGE/privkey.pem $RENEWED_LINEAGE/fullchain.pem >/etc/ssl/certs/server-combined.pem
/bin/systemctl restart exim4.service
for i in courier-authdaemon.service courier-pop.service courier-imap.service ; do
/bin/systemctl restart $i
done
;;
esac
The created server-combined.pem file will be used by the Courier services. It is referenced through a symlink in /etc/courier
:
drwxr-xr-x 6 root courier 4096 Nov 14 2020 .
drwxr-xr-x 87 root root 4096 Aug 19 12:29 ..
...
lrwxrwxrwx 1 root root 34 May 11 2019 imapd.pem -> /etc/ssl/certs/server-combined.pem
...
lrwxrwxrwx 1 root root 34 May 11 2019 pop3d.pem -> /etc/ssl/certs/server-combined.pem
The Exim mail server is configured to use the exim.crt
and exim.key
files, which are linked to the current letsencrypt fullchain.pem
certificate and corresponding private key files.
drwxr-xr-x 3 root root 4096 May 7 2021 .
drwxr-xr-x 87 root root 4096 Aug 19 12:29 ..
...
lrwxrwxrwx 1 root root 52 Dec 27 2020 exim.crt -> /etc/letsencrypt/live/mail.heissler.at/fullchain.pem
lrwxrwxrwx 1 root root 50 Dec 27 2020 exim.key -> /etc/letsencrypt/live/mail.heissler.at/privkey.pem
-rw-r--r-- 1 root root 49784 Dec 27 2020 exim4.conf
...
The Nginx service on my web server is also configured to use the current certificate and private key for the given domain (a similar letsencrypt files and directory structure has been created there); the default configuration file is located at /etc/nginx/sites-enabled/default
:
server {
listen 80 default_server;
listen [::]:80 default_server;
# SSL configuration
#
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
ssl_certificate /etc/letsencrypt/live/heissler.at/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/heissler.at/privkey.pem;
The letsencrypt renewal post hook configuration /etc/letsencrypt/renewal-hooks/post/01_install_web_cert.sh
looks as follows there:
/etc/letsencrypt/renewal-hooks/post/01_install_mail_web_cert.sh
#!/bin/bash
set -e
case $RENEWED_DOMAINS in
*)
/bin/systemctl restart nginx
;;
esac
Leave a Reply