Dev.to Security πŸ” Cybersecurity πŸ‘ 0 πŸ“– 4 min read

Your SSL certificate expired. Here is what to do in the next 20 minutes

The call usually comes from the client: "The site says it is not secure." Every browser is showing a full-page warning, nobody can get past it, and the shop has been taking zero orders since midnight. An expired certific

The call usually comes from the client: "The site says it is not secure." Every browser is showing a full-page warning, nobody can get past it, and the shop has been taking zero orders since midnight. An expired certificate is a complete outage with a scary message attached.

Here is the order of operations. The first part gets the site back. The second part makes sure you never have this conversation again.

Minute 0: confirm it is actually expiry

Run this from any machine:

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

You get notBefore, notAfter and the issuer. If notAfter is in the past, it is expiry. If the dates are fine but browsers still complain, skip to the chain section below, because the problem is a missing intermediate or a hostname mismatch, not expiry.

Also check whether the site is behind Cloudflare or another proxy. If Cloudflare is in front with "Full" SSL mode, the certificate visitors see is Cloudflare's and it renews itself. The expired one is on the origin, and the fix is the same but the urgency is lower; set Cloudflare to "Full" rather than "Full (strict)" for an hour if you need breathing room.

Minute 2: find out how the certificate was issued

Look at the issuer from the command above.

  • Let's Encrypt (R10, R11, E5, E6 and similar): something automated was supposed to renew it and did not. Log into the server and find the client: certbot, acme.sh, Caddy, Traefik, a cPanel AutoSSL, or a hosting panel.
  • A commercial CA (DigiCert, Sectigo, GlobalSign): someone bought it a year ago and the renewal email went to an inbox nobody reads. You need to buy or renew and install manually.
  • Hosting-managed (Kinsta, WP Engine, Cloudways, SiteGround): open their panel; usually there is a "renew" or "reissue" button and support can force it.

Minute 5: renew with Let's Encrypt

On a server with certbot:

sudo certbot renew --force-renewal
sudo systemctl reload nginx   # or apache2

If that fails, read the error. The common causes:

  1. DNS changed. The domain now points at Cloudflare or a new host, and the HTTP-01 challenge is hitting the wrong server. Use the DNS-01 challenge or run certbot where the traffic actually lands.
  2. Port 80 is closed. HTTP-01 needs port 80 open from the internet. A well-meaning firewall change broke it.
  3. Rate limited. Let's Encrypt allows 5 duplicate certificates a week. If a broken cron has been retrying for days, you have hit it. Wait, or issue for a slightly different set of names (add www.).
  4. The cron or systemd timer is gone. systemctl list-timers | grep certbot should show one. If not, sudo systemctl enable --now certbot.timer.

With Caddy or Traefik, restart the service and read the log; they renew on start.

Minute 10: renew a commercial certificate

Log in to the CA, renew, and generate a new CSR on the server:

openssl req -new -newkey rsa:2048 -nodes -keyout example.com.key -out example.com.csr

Complete validation (email or DNS), download the certificate and the intermediate bundle, install both, and reload the web server. Do not skip the bundle; that is how you end up with a certificate that works in Chrome on your machine and fails on Android.

Minute 15: verify the chain, not just the dates

echo | openssl s_client -servername example.com -connect example.com:443 -showcerts 2>/dev/null | grep -E "s:|i:"

You should see the leaf, then one or two intermediates, ending in a root the client trusts. "unable to get local issuer certificate" means an intermediate is missing. Test from a second device on mobile data; corporate networks cache certificates in ways that hide problems.

Then open the site in a private window. If the warning is gone, tell the client, and write down what broke.

Never again: three layers of protection

1. Fix the automation. Whatever renewal mechanism failed, make it fail loudly. With certbot, add a --deploy-hook that pings a heartbeat URL on success, so silence means trouble. With a hosting panel, turn on their expiry email and route it to a shared inbox.

2. Monitor expiry from the outside. Automation fails silently more often than people expect. An external SSL monitor reads the certificate your visitors see and alerts at 30, 14 and 3 days before expiry. Any monitoring tool with certificate checks will do; what matters is that the alert lands in a channel somebody actually reads, and that it covers every hostname, including the forgotten staging and mail ones.

3. Put it on the client report. A line that says "SSL certificate: valid, 61 days remaining" in the monthly report makes the client feel looked after and makes you check it once a month without thinking about it.

A note on 90-day and 47-day certificates

The industry is moving to shorter certificate lifetimes. Let's Encrypt is 90 days today and the CA/Browser Forum has agreed a path towards 47-day certificates by 2029. That makes automation mandatory and makes external monitoring the only sane safety net: if renewal breaks, you have days, not months, before visitors see a warning. Set it up now, while the last outage is fresh.

I work on Tenium, an uptime monitoring tool for people who look after many client sites. This article is general advice and does not require it.

πŸ“° Read the original article on Dev.to Security

Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes β€” full credit and traffic to the original publisher.