Reputation: 1187
I've seen conflicting recommendations. From the eff.org docs:
if you're setting up a cron or systemd job, we recommend running it twice per day... Please select a random minute within the hour for your renewal tasks.
I've also seen recommendations for weekly jobs.
I'm not a cron expert, so I'd prefer an answer with detailed steps for setting up the cron job.
Upvotes: 57
Views: 115751
Reputation: 60642
Melroy's answer does an excellent job explaining what's happening, especially when you have "snap" installation.
However, it never mentions, how to actually adjust the schedule ins this case (because config files are reset after snap refreshes).
So let me quote the solution I found elsewhere:
The systemd units created by snapd are mutable, but you should not modify them directly because any changes will be reverted during snap refreshes..
What you can do is:
systemctl edit snap.certbot.renew.timer
This will give you an empty override file. You can then make the contents:[Timer] OnCalendar= OnCalendar=*-*-* 17:04
(or whatever random time of day you'd like Certbot to run).
Sources:
Upvotes: 1
Reputation: 186
I figured out how to make it run by cron on systems where the webserver could not be stopped/started by the certbot tool reliably or could not access the verification file because it is not in the webtree. In this case you do the initial setup of an offline initial installation and then renewals can be done by cron.
Here is my script and it is working in production:
#!/bin/bash
# get root apache process id
pid=`ps -ef |grep apache2 |grep root | egrep -v "grep" |awk '{print $2;}'`
echo "Found Apache2 pid=($pid)\n"
# shut it down gracefully (our way)
# request shutdown
kill -TERM $pid
# wait 4 seconds
sleep 4
# no running .pid to remove
# show if it is still in memory
ps -ef |grep apache2 |egrep -v "grep"
# now get new certificate
# request just certificate, with this hostname, standalone server, non-interactive
# uncomment for real certificates, but make sure test certificate is commented
#/usr/bin/certbot certonly --test-cert --standalone -n -d <your.server.tld> 2>&1
# uncomment for test certificates
#/usr/bin/certbot certonly --test-cert --dry-run --standalone -n -d <your.server.tld> 2>&1
/usr/bin/certbot renew --force-renewal --standalone -n 2>&1
# restart apache2 (we know it will report fail, but it will actually start it)
echo "starting apache2...\n"
/bin/systemctl start apache2 2>&1
# check if it's in memory...
npid=`ps -ef |grep apache2 |grep root | egrep -v "grep" |awk '{print $2;}'`
echo "Found New Apache2 pid=($npid)\n"
# if npid is empty try restarting again...
#/bin/systemctl restart apache2 2>&1
echo "done."
echo ""
I set up the cronjob as follows:
# stop apache2, forcibly renew every 3 weeks and then restart apache2
0 1 3,18 * * /bin/touch /var/adm/ratglc_ssl_certbot.log; /home/tk/bin/ratglc 2>&1 >> /var/adm/ratglc_ssl_certbot.log
I do have other monitoring that alerts me if SSL stops working or the webserver does not come back online and so far neither of those things has happened. One thing-- systemctl reports apache2 "did not start" but it did and this script checks that. I write all output to a log for review/monitoring later.
It's not pretty but it works.
Thanks, David
Upvotes: 0
Reputation: 3166
In Debian Jessie and up (incl. Ubuntu) cron is not executed for Certbot renewal. Instead the systemd timer is used.
UPDATE: When you're using Snap (which is the recommended install method of Certbot). Off the record: I don't like Snap.
Auto renew timer is located at: /etc/systemd/system/snap.certbot.renew.timer
. Which has the content:
[Unit]
# Auto-generated, DO NOT EDIT
Description=Timer renew for snap application certbot.renew
Requires=snap-certbot-3566.mount
After=snap-certbot-3566.mount
X-Snappy=yes
[Timer]
Unit=snap.certbot.renew.service
OnCalendar=*-*-* 08:41
OnCalendar=*-*-* 14:01
[Install]
WantedBy=timers.target
As you can see the renew job service is called twice a day. Once ACME ARI extension is implemented this renew frequency might need to be increased in the future, but I digress.
Note: Do not try to modify these files, changes will be reverted back by a snap refresh.
And the service file /etc/systemd/system/snap.certbot.renew.service
, that the timer is triggering, has the following content:
[Unit]
# Auto-generated, DO NOT EDIT
Description=Service for snap application certbot.renew
Requires=snap-certbot-3566.mount
Wants=network.target
After=snap-certbot-3566.mount network.target snapd.apparmor.service
X-Snappy=yes
[Service]
EnvironmentFile=-/etc/environment
ExecStart=/usr/bin/snap run --timer="00:00~24:00/2" certbot.renew
SyslogIdentifier=certbot.renew
Restart=no
WorkingDirectory=/var/snap/certbot/3566
TimeoutStopSec=30
Type=oneshot
See the status of the timer: systemctl status snap.certbot.renew.timer
When using the Nginx installer via certbot (certbot --nginx
), the renew configuration files are located in the /etc/letsencrypt/renewal
directory. These Certbot conf files contain information that the certificate(s) are deployed to the Nginx server and reload Nginx automatically when required:
authenticator = nginx
installer = nginx
server = https://acme-v02.api.letsencrypt.org/directory
key_type = ecdsa
On distros that might not have Snap (good!), the timer should be located at: /lib/systemd/system/certbot.timer
. With the service: /lib/systemd/system/certbot.service
Which contains:
[Service]
Type=oneshot
ExecStart=/usr/bin/certbot -q renew
PrivateTmp=true
In order to list all the timers, execute the following command in the terminal:
systemctl list-timers
Hopefully Certbot is part of this:
Mon 2019-02-04 08:38:45 CET 9h left Sun 2019-02-03 15:25:41 CET 8h ago certbot.timer certbot.service
How-to install Certbot on a older Debian based distro (it may vary depending on your Linux distribution).
But within Debian Stretch for example you can install the back-port package of certbot
via:
sudo apt-get install certbot -t stretch-backports
This will install the files I showed above for you automatically! And thus automatically schedule a certbot timer for you, which runs the service, which runs again the renew.
Manually running a renew is always possible via:
sudo /usr/bin/certbot renew
Can be forced via --force-renewal
flag. For more info see the help text of renew:
/usr/bin/certbot --help renew
Files part of the certbot package (incl. but not limited by):
dpkg-query -L certbot
...
/lib/systemd/system/certbot.service
/lib/systemd/system/certbot.timer
...
Upvotes: 44
Reputation: 1187
So I settled on scheduling it to run once a day. First I tested auto-renew as the docs recommend:
sudo letsencrypt renew --dry-run --agree-tos
Then I updated the crontab:
sudo crontab -e
This is the line I added:
12 3 * * * letsencrypt renew >> /var/log/letsencrypt/renew.log
This runs the renew everday at 3:12 am. I presume the docs recommend "a random minute within the hour" to distribute the load on the renew servers. So I suppose anything other than 0, 15, 30, or 45 is preferred.
I looked into randomizing the minute in the cron setting, like Jenkins allows you to do. On original EEF page is this Example:
0 0,12 * * * python -c 'import random; import time; time.sleep(random.random() * 3600)' && /usr/local/bin/certbot-auto renew
Finally, I tested the cron command using sudo bash:
sudo bash -c "letsencrypt renew >> /var/log/letsencrypt/renew.log"
Upvotes: 41
Reputation: 7372
None of these answers worked for me in 2023, because certbot cannot renew if nginx is running on port 80.
The following entry in the crontab works:
43 6 * * * sudo certbot renew --pre-hook "sudo systemctl stop nginx" --post-hook "sudo systemctl start nginx"
Upvotes: 2
Reputation: 1697
I recently (April 2018) installed and ran certbot (version 0.22.2) on an Ubuntu 16.04 server, and a renewal cron job was created automatically in /etc/cron.d/certbot.
Here's the cron job that was created:
# /etc/cron.d/certbot: crontab entries for the certbot package
#
# Upstream recommends attempting renewal twice a day
#
# Eventually, this will be an opportunity to validate certificates
# haven't been revoked, etc. Renewal will only occur if expiration
# is within 30 days.
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
0 */12 * * * root test -x /usr/bin/certbot -a \! -d /run/systemd/system && perl -e 'sleep int(rand(3600))' && certbot -q renew
Please check this before putting a new Cron job.
Update (From @Hamish Downer's comment):
It's worth being aware that the above cron job won't run certbot renew if /run/systemd/system is present - this is because instead a systemd timer is running certbot - read more about certbot and systemd timers here.
Upvotes: 60
Reputation: 1975
Adding the following line to /etc/crontab
runs renewal attempt daily on a random minute between 00:00 and approximately 16:40:
1 1 * * * root sleep ${RANDOM:0:3}m && /home/admin/certbot-auto renew --quiet --no-self-upgrade --authenticator webroot --installer apache -w /var/www/mywebroot
Works great for more than a year now.
The renew command itself may vary for you - I used webroot as it seemed most robust at that time.
Upvotes: 2
Reputation: 419
To keep simple set a timer to validate automatically:
systemctl status certbot.timer
Upvotes: -1
Reputation: 43
for renew every 2 month:
#nano /etc/cron.d/certbot
30 03 01 */2 * echo "2" | certbot --nginx -v -d yourdomain.com
Upvotes: 0
Reputation: 3552
Ok. So being on Debian (or Ubuntu) with systemd I had probably the same problem like others - cron job not firing. I needed to make some extra steps and observations not mentioned elsewhere, so making separate answer for it.
In my case the /etc/systemd/system/
directory exists, so the job in /etc/cron.d/certbot
stops at the initial test.
BUT the /etc/systemd/system/certbot.timer
was a pointer to /dev/null
. That means it is a masked timer. When I did systemd unmask certbot.timer
the link was removed, but I had nothing to replace it with (tried locate certbot.timer
but none was installed on my system). I could also still see the timer in systemd list-timers --all
, but it was an emtpy file so removed that too using systemd disable certbot.timer
. The service in /etc/systemd/system/certbot.service
was completely absent.
So after actually cleaning all the certbot-related stuff from /etc/systemd/system/
I created the necessary files manually.
# /etc/systemd/system/certbot-renewal.service
[Unit]
Description=Certbot Renewal
[Service]
ExecStart=/usr/local/bin/certbot -q renew --post-hook "systemctl reload nginx"
# /etc/systemd/system/certbot-renewal.timer
[Unit]
Description=Run certbot twice daily
[Timer]
OnCalendar=*-*-* 00,12:00:00
RandomizedDelaySec=43200
Persistent=true
[Install]
WantedBy=timers.target
The timer file content comes from this answer.
I started and checked the whole thing by running:
sudo systemctl start certbot-renewal.timer
sudo systemctl enable certbot-renewal.timer
sudo systemctl list-timers --all
sudo journalctl -u certbot-renewal.service
Few more notes:
/usr/local/bin/certbot
instead of /usr/bin/certbot
(figured using which certbot
), don't know why.Upvotes: 8
Reputation: 3417
Normally while you run a certbot for any webserver in an Ubuntu 16.04 server it automatically creates a cron
#cat /etc/cron.d/certbot
0 */12 * * * root test -x /usr/bin/certbot -a \! -d /run/systemd/system && perl -e 'sleep int(rand(3600))' && certbot -q renew
Upvotes: 2