Certbot and scheduled certificate renewals


I’m currently migrating all my web services from CentOS 7 to Rocky Linux 8. I’ve been using Certbot and Let’s Encrypt for SSL/TLS certificates since 2016, and I’m reasonably familiar with the certification generation process.

I just installed Certbot on an Internet-facing Rocky Linux 8 server. Installing the certbot package displays (among other things) the following information:

Certbot has set up a scheduled task to automatically renew this certificate in the background.

I was a bit puzzled by this, since I couldn’t remember it from previous installations on CentOS 7. So I checked:

# crontab -l
no crontab for root

Maybe a systemd timer ? Curiously enough, systemctl list-timers show nothing even remotely related to Certbot. But here it is:

# systemctl list-timers --all
n/a    n/a     n/a      n/a     certbot-renew.timer    certbot-renew.service

Any idea what to do with this information ? Up until now I just put my certificate generation/renewal commands in a shell script and ran it every month either with a cronjob or manually (because sometimes there are hiccups).



Hey Niki!

I had to setup certbot installed from EPEL already a few times, and yeah the renewal is done via a systemd timer, by default once every 12 hours, or better said, in every 0:00-12:00 and 12:00-24:00 range once.
I generally always make sure that it is also started after the install / first cert enrollment, but it’s enabled by default:

# systemctl cat certbot-renew.timer
# /usr/lib/systemd/system/certbot-renew.timer
Description=This is the timer to set the schedule for automated renewals

OnCalendar=*-*-* 00/12:00:00

# systemctl cat certbot-renew.service
# /usr/lib/systemd/system/certbot-renew.service
Description=This service automatically renews any certbot certificates found

ExecStart=/usr/bin/certbot renew --noninteractive --no-random-sleep-on-renew $PRE_HOOK $POST_HOOK $RENEW_HOOK $DEPLOY_HOOK $CERTBOT_ARGS

If you want to make sure it is really running, systemctl status certbot-renew.timer should give you the Active state: active (waiting).

Tbh the default is more than enough, so as long as the systemd timer is running nothing else should be needed to be done :slight_smile: (and you will of course see the output of it in the journal)


Thank you very much for your detailed answer. I did a little more research, and as it turns out, the timers are not really useful to me since I’m using certbot with the standalone plugin. Here’s how I issued my initial certificate:

# certbot certonly --non-interactive --email info@microlinux.fr \
  --preferred-challenges http --standalone --agree-tos --renew-by-default \
  --webroot-path /var/www/html -d sd-155842.dedibox.fr
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Account registered.
Requesting a certificate for sd-155842.dedibox.fr

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/sd-155842.dedibox.fr/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/sd-155842.dedibox.fr/privkey.pem
This certificate expires on 2023-08-03.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.

This is the most simple and bone-headed method, and the reason I’m using it is that back in 2015 when the first public beta of Let’s Encrypt certificates were available, I was running Slackware Linux on my servers and the standalone plugin was the only one available. So in all honesty, it’s force of habit, I’d say.

On a side note, I’ve written a letsencrypt.sh shell script that greatly simplifies the creation and renewal of all my certificates, since it can happen that I have a few dozen certificates for various domains and subdomains on a single machine:

The only drawback of getting certificates with the standalone plugin is the fact that it requires TCP port 80 to be available. So if I run certbot renew with the web server running, I get the following error message:

Failed to renew certificate sd-155842.dedibox.fr with error: Could not bind TCP port 80 
because it is already in use by another process on this system (such as a web server). 
Please stop the program in question and then try again.

The pragmatic solution I have found for this is that I run the letsencrypt.sh script manually every couple months or so only. It stops Apache, renews all the certificates and starts Apache again. Service interruption is no more than 30 seconds, and I only host non-critical stuff like SME websites, blogs, etc. I do this on a Sunday morning when the whole country’s asleep. :slightly_smiling_face:

I wonder if it would be worth the hassle to learn using the webroot plugin (which apparently can renew certificates with Apache running). Unfortunately the Certbot documentation is not exactly a model of clarity in this regard.




I’m running certbot in a podman container with a systemd timer. It renews the certificates for an nginx webserver, also in a container. It’s a bit planning to get the volume binds right but it’s not that hard.


Description=Renew Let's Encrypt certificates daily at 01:30

OnCalendar=*-*-* 01:30:00



Description=Renew Let's Encrypt certificates

ExecStart=podman run -it --rm -v %h/nginx/data/letsencrypt:/etc/letsencrypt:z -v %h/nginx/data/www/letsencrypt:/srv/letsencrypt:z -v %h/nginx/log:/var/log:z certbot/certbot renew --webroot -w /srv/letsencrypt
ExecStart=podman exec nginx-quic nginx -s reload


Since I keep the nginx server (container) running during renewal, I use the webroot method. After renewal, nginx is reloaded.

This only works for renewal. First time issue has to be done “manually”.