Monitoring SSL certificate expiry

Updated November 3, 2026

An expired certificate takes a site down as surely as a crashed server: browsers show a full-page warning, API clients refuse to connect, and mobile apps break. Automatic renewal made this rarer, not impossible. Renewal jobs fail quietly, and certificates are getting shorter. Here’s how to check expiry, find out why renewal stopped, and get a warning days before it matters.

Why this matters more every year

Check when a certificate expires

From any machine with OpenSSL, for the certificate the site actually serves:

echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
  | openssl x509 -noout -enddate -issuer -subject

On a server with certbot, for the certificates it manages:

sudo certbot certificates

If the two disagree, certbot renewed the certificate but the web server is still serving the old one.

Why automatic renewal stops

Test renewal without changing anything:

sudo certbot renew --dry-run

Reload the web server after renewal

A deploy hook runs only when a certificate was actually renewed:

sudo certbot renew --deploy-hook "systemctl reload nginx"

To make it permanent, put a script in /etc/letsencrypt/renewal-hooks/deploy/. certbot runs every executable file there after each successful renewal.

Watch the renewal job

certbot exits with 0 when nothing needs renewing yet, so a ping after it means “the job ran and nothing went wrong”. If your system uses the certbot timer, add the ping to its service with sudo systemctl edit certbot.service:

[Service]
ExecStartPost=/usr/bin/curl -fsS -m 10 --retry 3 -o /dev/null https://ping.heartcron.com/<uuid>

Or, with plain cron instead of the timer:

17 */12 * * * certbot renew --quiet --deploy-hook "systemctl reload nginx" && curl -fsS -m 10 --retry 3 -o /dev/null https://ping.heartcron.com/<uuid>

Give the check a 12-hour period and a grace period of a few hours. If the job disappears or certbot starts failing, you’ll know weeks before the certificate expires instead of on the day. See monitoring systemd timers for reporting failures right away with OnFailure.

Watch the certificate itself

A job that runs fine doesn’t prove the site serves a fresh certificate: the reload may be missing, or the certificate may come from a CDN or a load balancer you don’t renew yourself. So check from outside too. In Heartcron, add an SSL check for the host and choose how many days ahead to warn, for example 14. Heartcron connects to the site the way a browser does and alerts you when the certificate it serves is about to expire or already invalid.

Add a check for every name that serves its own certificate: example.com, api.example.com, the mail server, a status page on a custom domain. While you’re there, a domain check warns before the domain registration itself runs out, which takes everything down at once.

More guides