On June 4, 2025, Let's Encrypt sent its last expiration-notice email. If you relied on those reminders as your safety net, that net is gone. Their own advice was to use a third-party monitor instead.
A lot of people read that and shrugged. Certbot renews automatically, right? The cron job runs, the cert renews, nothing to worry about. That confidence is exactly the problem. The expiry emails weren't there for the happy path. They were there for the day automation quietly broke and nobody noticed.
Why renewal automation fails silently
Automated renewal works until it doesn't, and the failure mode is almost always quiet. A few of the common ones:
The DNS-01 challenge stops validating. You set up a wildcard cert with a DNS challenge. Six months later someone rotates the API token for your DNS provider, or migrates the zone, or tightens the IAM permissions. Certbot can no longer write the TXT record. Renewal fails. There's a line in a log file somewhere, and that's it.
You hit a rate limit. Let's Encrypt caps certificates per registered domain per week. If something in your pipeline starts re-issuing in a loop, or you spin up a lot of subdomains at once, you can exhaust the limit and get denied at exactly the wrong moment.
Certbot renews but the web server never reloads. This is the nastiest one because every log says success. Certbot writes a fresh cert to disk. The --deploy-hook that's supposed to run systemctl reload nginx is missing, or it errored, or someone edited the renewal config and dropped it. Nginx keeps the old certificate in memory and keeps serving it. Certbot reports success. The renewal timer reports success. Your monitoring, if it's watching the cron job, reports success. And the cert on the wire expires anyway.
That last case is the one that should change how you think about this. The renewal succeeded. The problem is that success on disk is not success on the wire.
Monitor the served cert, not the cron job
Here's the distinction that matters. There are two things you could watch:
- The renewal process: did certbot exit 0, did the timer fire, is there a new file in
/etc/letsencrypt/live/. - The served certificate: what does the server actually hand a client when it opens a TLS connection right now.
Watching the renewal process tells you the machine you know about did the thing you expected. It tells you nothing about the load balancer in front of it, the CDN edge, the reverse proxy that didn't reload, the second server in the pool that everyone forgot about, or the cert that a colleague deployed by hand two years ago.
Watching the served cert tells you the only thing your users actually experience: what comes back over the connection. If you check that, every one of the silent failures above shows up, because they all end the same way. The wire still has the old cert.
The one-liner you can run today
You don't need anything installed beyond openssl, which is already on every server and most laptops. Here's the check:
echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null | openssl x509 -noout -enddate
That opens a real TLS connection to example.com on port 443, pulls the certificate the server actually presents, and prints its expiry date:
notAfter=Sep 12 08:14:22 2026 GMT
The -servername flag is important. It sends SNI, so on a host with multiple certs you get the right one instead of the default. Change the port and you can check anything that speaks TLS: :465 for SMTP submission, :993 for IMAPS, :636 for LDAPS, :8443 for whatever admin panel is hiding there.
Run it, put it in a script, loop it over your domains. It's genuinely useful and it costs nothing.
Where the one-liner runs out
The one-liner answers one question: when does the leaf cert expire. That's a real question, but it's not the whole job.
- It doesn't check the chain. The leaf can be valid for months while an intermediate expires next week. The command reads
notAfteron the leaf and stops. - It doesn't tell you the cert changed. If someone reissues or replaces the cert, the expiry date moves and you're none the wiser. You won't notice an unexpected certificate showing up until you go looking.
- It doesn't validate the hostname. A cert can be valid and current and simply not cover the name you asked for.
- It doesn't alert. A script that prints a date into a terminal nobody is watching is not monitoring. Someone has to look.
- It doesn't remember. No history, no trend, no record of when the cert last rotated or what fingerprint it had last week.
You can build all of that yourself. Cron plus openssl plus a diff of yesterday's fingerprint plus a Slack webhook plus a way to suppress duplicate alerts plus a dashboard. People do. Then they maintain it, and the monitoring script itself becomes a thing that can silently break, which puts you right back where you started.
Closing the gap
The point of a dedicated monitor is to check the certificate the server actually serves, on a schedule, from outside your infrastructure, and to tell you before it becomes an outage.
That means validating the full chain, so an expiring intermediate gets caught even when the leaf is fine. Matching the hostname and SANs. Recording the fingerprint so an unexpected change is visible immediately. Working on any TLS port, not just 443. And alerting through a channel you actually read, with sensible lead time. The old Let's Encrypt reminders gave you a heads-up. A monitor with thresholds at 30, 14, 7, and 1 day gives you four, and escalates as the deadline gets closer.
One more thing that matters more than it sounds: a good monitor tells you when everything is fine. A weekly all-clear digest means silence is never ambiguous. If you didn't get the digest, the monitor is down, and that's a signal too. With the old emails, no news meant nothing. Now no news should mean something.
Certbot is great. Automation is the right default. But automation without verification is just hope with a cron schedule. The expiry emails are gone. Check the wire.
CertPost does exactly this: it opens a live TLS connection, validates the whole chain, tracks the fingerprint, and alerts before expiry across email, Slack, Discord, and webhooks. Three certs are free forever if you want to try it on the domains you'd lose sleep over.
