How to get warned before your SSL/TLS certificate expires
Updated 7 August 2026 · by Cassian Wei · 2 min read
"But Let's Encrypt renews automatically" — until the renewal timer was lost in a server migration, the DNS challenge broke when you switched providers, or the cert on that one internal subdomain was never on auto-renew at all. An expired certificate takes your site down with a full-page browser warning, and it always happens on a weekend.
Why certificates still expire in production
- Renewal broke silently. The certbot systemd timer isn't running, the ACME account key is gone, or an HTTP challenge is blocked by a new firewall rule. Renewal failures usually only log locally.
- The DNS challenge fails. Wildcard certs renew via DNS records; an API token that expired or a nameserver migration breaks it without any visible error on the site.
- Forgotten hosts. The main site is fine, but
api.,mail., a staging box, or a non-443 service (database, MQTT, LDAPS) carries a cert nobody tracks. - Manually issued certs. Anything bought for 1 year with a calendar reminder in an ex-employee's inbox.
Check expiry by hand
echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null \ | openssl x509 -noout -enddate # notAfter=Nov 3 12:00:00 2026 GMT
Good for a one-off audit — useless as a process, because the failure mode is precisely "nobody ran the check".
Monitor it automatically
Watchpup has a dedicated tls monitor kind: a real TLS handshake
against your host once a day, reading the certificate's actual validity dates (works with
self-signed and internal certs too, and with any port — not just 443):
curl -X POST https://watchpup.watchpup.workers.dev/api/monitors \
-H 'authorization: Bearer wp_...' -H 'content-type: application/json' \
-d '{"kind":"tls","name":"site cert","target":"example.com","warn_days":14}'
You're alerted when the certificate enters the warning window (default 14 days before expiry — enough time to fix renewal calmly), when it's expired, or when the host stops speaking TLS at all. The alert names the issuer and the exact date.
A sane setup
- One
tlsmonitor per distinct certificate: apex,api.,mail.example.com:465, staging. (Wildcards: one monitor covers all hosts sharing the cert.) - Set
warn_dayslonger than your renewal cycle's slack — 14 is right for 90-day Let's Encrypt certs, 30 for annually renewed ones. - Add a
domainmonitor too: an expired domain registration is the same disaster one level up. See the domain-expiry guide. - Route these alerts to a channel someone actually reads — email, Slack, Discord, Telegram or ntfy push.
Free tier: 15 monitors, no card. There's a live TLS monitor on the demo status page.
Watchpup is free uptime & cron monitoring — 1-minute checks, heartbeats, TLS/domain expiry, status pages, alerts everywhere. Sign up, try the live demo, or read more guides.