SSL certificate auto renewal cronjob

I was trying to automate ssl renewal using cronjob and also maintain the required data in database, so we can also manually update if the renewal date is valid.

I have two queries regarding this.
Firstly, is there anyway to remove random delayed generation while using the certbot renew line.
Secondly, is there any way acquire remaining days for renewal as "certbot certificates" command gives detailed output.

Your help will be highly appreciated.

1 Like

It depends how you installed Certbot. The random delay is usually part of the scheduled task itself (cron, systemd timer, etc). It should be possible in all cases to remove it. That said:

If you offer client software that automatically configures a periodic batch job, please make sure to run at a randomized second during the day, rather than always running at a specific time. This ensures that Let’s Encrypt doesn’t receive arbitrary spikes of traffic at the top of the hour or minute. Since Let’s Encrypt needs to provision capacity to meet peak load, reducing traffic spikes can help keep our costs down.

This is not just a theoretical concern: there have been times where users on this forum have complained about certificate renewal failures and it turned out the common pattern was that they were all running at the top of the hour, at midnight, etc.

I don't think there's any elegant way to do this. The default value of renew_before_expiry hardcoded into Certbot is 30 days, so you would need to subtract the two.

2 Likes

Probably the easiest I can think of is to use openssl or the like on the actual cert file. Something like

openssl x509 -noout -enddate -in /etc/letsencrypt/live/example.com/cert.pem

Which you might be able to parse, or if you're building some shell script where you want to do something only if it's within a certain time (measured in seconds) to expiration, you can use -checkend instead to set openssl's exit code:

if openssl x509 -noout -checkend 2592000 -in /etc/letsencrypt/live/example.com/cert.pem
then
  #Not close to expiration
  exit 0
fi
# Close to expiration; do something here

Or something else along those lines. Usually, though, you can just let certbot do its thing and handle renewing while close to expiration itself.

3 Likes

image
Respected sir,
I am talking about this Non interactive renewal delay.
This was not even in cronjob, I just renewed using script

1 Like

Whoops, totally forgot that exists. Sorry!

--no-random-sleep-on-renew
1 Like

This is what I do.
try to renew my certs,
HUP sendmail ,
reload dovecot,
reload nginx

My crontab looks like this:

    19	4	*	*	3 	/usr/local/bin/certbot renew >> /var/log/certbot-out.log

    20	4	*	*	3 	pkill -HUP sendmail 

    21	4	*	*	3 	/usr/local/sbin/dovecot reload

   22	4	*	*	3 	/usr/local/sbin/nginx -s reload 

My log file:
`


The following certs are not due for renewal yet:
/etc/letsencrypt/live/so.slo.me/fullchain.pem expires on 2021-05-18 (skipped)
No renewals were attempted.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/so.slo.me.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

The following certs are not due for renewal yet:
/etc/letsencrypt/live/so.slo.me/fullchain.pem expires on 2021-05-18 (skipped)
No renewals were attempted.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/so.slo.me.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
new certificate deployed without reload, fullchain is
/etc/letsencrypt/live/so.slo.me/fullchain.pem
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Congratulations, all renewals succeeded. The following certs have been renewed:
/etc/letsencrypt/live/so.slo.me/fullchain.pem (success)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

1 Like

As @_az mentioned, if you don't include --no-random-sleep-on-renew, Certbot, when run from a cron job, may delay a random number of seconds (which may amount to several minutes' delay) before actually beginning its work. The goal of this is to smooth out Let's Encrypt's CA load because so many people like to run cron jobs exactly at midnight, or at the beginning of an hour.

Therefore, Certbot may not actually have finished its work in only 1 minute or 2 minutes after it's started.

There are a couple of things about what you're doing in your crontab that aren't exactly aligned with how we intended Certbot to be used.

(1) The 19 4 * * 3 idea: With certbot renew, Certbot only attempts to renew certificates that are expiring in less than 30 days. Therefore, you can run certbot renew (and we've suggested running it) much more frequently than once per week, because most times it will take no action at all (since no local certificate is close to expiring).

(2) The subsequent pkill and reload tasks. We built a feature into Certbot called deploy-hook, which will make it run a script of your choice when it's done renewing a certificate, and only if the certificate was actually renewed. The script is meant to do things like copying the new certificate into some location (if necessary), and restarting daemons that use it (if necessary). In this case, you could use something like

--deploy-hook "pkill -HUP sendmail" --deploy-hook "/usr/local/sbin/dovecot reload" --deploy-hook "/usr/local/sbin/nginx -s reload"

in your Certbot command, which would cause all three of these to be run directly by Certbot itself, once it was done obtaining the new certificate, only if it actually obtained one. This avoids restarting the services unnecessarily when there's no new certificate, and is more compatible with the prospect of running certbot renew much more frequently.

If you do want to keep your current version, you might want to add a much longer delay in between the certbot renew command and the process restart commands (like 20 minutes or 30 minutes). But I think using the renew-hook as we designed it would be much simpler and more reliable.

2 Likes

I sincerely appreciate the information and your patience.
you make a great point about the times,
and I will be changing it.

When I began using certbot, the crontab recommendation was not so refined or clear.

I know what you mean about everybody running jobs at midnight, I used to work in hosting.
I moved mine to be polite to you.

As far as the frequency, that is intentional. From a system perspective, certbot itself could fail,
and cause other problems. I have seen "croinjobs gone wild" too may times.

I like the deploy-hooks, I had no idea it was available.
this is what I've been using on another box. :slight_smile:

#!/usr/bin/env python3

import socket, ssl, subprocess, sys, time

cert_host= sys.argv[1]

cert_port = int(sys.argv[2])

cert_services= [ ['pkill','-HUP','sendmail'],
                 ['/usr/local/sbin/dovecot' ,'reload'],
                 ['/usr/local/sbin/nginx', '-s', 'reload']
                 ]

certbot_cmd = ['certbot', 'renew']


context = ssl.create_default_context()
conn = context.wrap_socket(socket.socket(socket.AF_INET)
                           ,server_hostname= cert_host)
try:
        conn.connect((cert_host, cert_port))
        cert = conn.getpeercert()
        timestamp = ssl.cert_time_to_seconds(cert['notAfter'])
        days_left= (timestamp - time.time()) / 86400

        if days_left > 11:
                print( 'The Cert was not renewed,')
                print(f'it is valid until {cert["notAfter"]}')
        else:
                subp=subprocess.run(certbot_cmd)
                [subprocess.run(srv) for srv in cert_services]
except:
        print(f'unable to get cert from host {cert_host} on port {cert_port}')


This is the oldest certbot log on that server

    -rw-r--r--  1 root  wheel   755B Jan 29  2019 letsencrypt.log.203

You should take that as compliment.
I haven't had to give it much attention at all. I forget it's even there .

I really appreciate you taking the time to reply, thank you.

Adrian

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.