An expired TLS certificate takes a site from "working" to "scary red browser warning" at the stroke of a timestamp — and it's entirely avoidable. The fix is fast; the real goal is making sure it never expires again.
1. Confirm the expiry
echo | openssl s_client -connect example.com:443 2>/dev/null \ | openssl x509 -noout -dates # notAfter=... is the expiry. Or check a local file: openssl x509 -enddate -noout -in /etc/letsencrypt/live/example.com/cert.pem
Make sure you're reading the certificate the server is actually serving — a renewed file on disk does nothing until the server reloads it (step 3).
2. Renew it
With Let's Encrypt / certbot: certbot renew renews anything near expiry, or certbot renew --force-renewal to force it now. For a commercial CA, generate a CSR, get the new cert issued, and drop it in place. Renewal fails most often because the HTTP-01 challenge can't reach the server — make sure port 80 is open and pointed at this host.
3. Reload the server — the step people forget
The running web server holds the old cert in memory. After renewal: nginx -t && systemctl reload nginx (or systemctl reload apache2). Re-run the step-1 check against the live port to confirm the new notAfter date is being served.
4. Make it never happen again
certbot installs a systemd timer / cron job that auto-renews — verify it with systemctl list-timers | grep certbot and test the renewal path with certbot renew --dry-run. Add expiry monitoring so a silent failure pages you weeks early, not the browser.
Practise it under the clock
Expired-certificate incidents show up in the simulator with an SLA ticking. Work them in a full incident response shift.