It could be tiresome to have to manually renew your Let’s Encrypt certificates using Certbot on your VPSs every few months. This gets increasingly frustrating as you have more services and thus, more certificates to renew. Having to renew them manually is also quite detrimental to the scalability of your services and infrastructure. Therefore, there emerges a need to enable the certificates to self-renew. This article will introduce a relatively new way to perform automatic certificate renewal with systemd timers instead of traditional ways such as crontab.
Why? Because on a system with systemd, it is easier to have everything managed through systemd.
In order to achieve auto-renewal of certificates, we will need to write two systemd unit files: a service unit which defines what to execute, and a timer which defines when to execute.
Writing a Service Unit
In simple terms, the systemd service file defines the commands to be executed for the certificate renewal. You can think of it to be similar to a script. Here are some noteworthy points:
Type=oneshot: This option makes the service unit behave more like a script. The unit will not become a daemon, and you can define multiple
ExecStartentries which will execute in serial. If any of the entries fail, the unit is considered failed.
- The first
ExecStart: Launches Certbot in
-n(non-interactive) mode to renew the certificates. More arguments can be added as needed.
- The second
ExecStart: Optional. Certbot needs to listen on port 80 for web-based authentication. Since port 80 is a privileged port, Certbot needs to run with root privileges. However, this means that the certificates saved will be owned by root:root. This second command yields the ownership of the certificates. You can modify this command as needed.
- The third
ExecStart: Restart the service(s) using the expiring certificates so they can load in the refreshed certificate.
reloadmight also be supported by some services as a more graceful version than
This example below is written for one of my matrix-synapse servers. Since Certbot requires root privileges to listen on port 80 to renew the certificates, the renewed certificates it releases into
/etc/letsencrypt are also owned by
root:root. My coarse solution for this problem is to simply use a chown command to yield the ownership of the needed directories to the service’s group
ssl-cert per the conventions. The user
matrix-synapse is a member of the
ssl-cert group, which gives it access to the certificates and keys.
Of course, should you have multiple services running on the same server or just wish to have more fine-grained permissions, you can always design a more intricate chown command or seek an alternative solution for the permissions. I am merely demonstrating the bare minimums here.
Another thing worth mentioning is that if you have Certbot installed via pip (not that you should) instead of a package manager, Certbot will be at
/usr/local/bin/certbot instead of
Writing a Timer Unit
The timer file controls when/how often the service file is executed.
OnCalendar=daily: Denotes that the service file above should be executed on a daily basis.
Persistent=true: The last time the timer is ran is stored on disk. If for whatever reason (e.g, power-off) the timer was not executed on-time, it will be executed immediately when the timer is next loaded.