SSL certificate expired - what to do
· 6 min read
In brief: SSL certificate expiry causes browsers to block access with the message "Your connection is not private". Conversion drops to zero until you renew the certificate. This article is a quick procedure on what to do right now and how to prevent it.
In brief: SSL certificate expiry causes browsers to block access with the message "Your connection is not private". Conversion drops to zero until you renew the certificate. This article is a quick procedure on what to do right now and how to prevent it.
What the visitor sees
An expired certificate triggers a full-screen browser warning:
- Chrome / Edge: "Your connection is not private" (NET::ERR_CERT_DATE_INVALID)
- Firefox: "Warning: Potential Security Risk Ahead" (SEC_ERROR_EXPIRED_CERTIFICATE)
- Safari: "This Connection Is Not Private"
A regular visitor clicks "Back". Over 95 % of organic traffic simply leaves. Bot crawlers (Googlebot, Bingbot) stop indexing and after a few days you start losing positions in search.
What to do if it expired right now
- Identify who issued the cert. In the terminal:
openssl s_client -connect mywebsite.com:443 -servername mywebsite.com < /dev/null 2>/dev/null | openssl x509 -noout -issuer -dates - Let's Encrypt (free, 90-day validity): typically via
certbot renewor via the hosting panel (One-click renewal). - Commercial cert (DigiCert, Sectigo, GlobalSign): log into the issuer's admin panel, generate a new CSR, complete domain validation (DNS TXT or email).
- Deploy the new cert to the reverse proxy (nginx, Caddy, Traefik) and restart / reload the process.
- Verify via SSL Labs or our SSL check tool, that the cert is served correctly and the chain is complete.
Heads up: Don't forget the intermediate cert - without it modern browsers can pull the chain via AIA, but older clients and some API libraries will fail.
Automatic renewal: Let's Encrypt + certbot
The simplest prevention is to fully automate renewal. Let's Encrypt cert renews every 90 days via certbot:
# /etc/cron.d/certbot-renew
0 3 * * * root certbot renew --quiet --deploy-hook "systemctl reload nginx"
This cron runs daily at 3:00 AM. Certbot internally checks whether the cert is approaching expiry (30 days in advance by default). If yes, it renews and reloads nginx on success. Otherwise it does nothing.
Caddy and Traefik: fully automatic
If you use Caddy or Traefik as reverse proxy, the ACME challenge is built into the binary. Just mark the domain in the config and the server requests and renews the cert by itself:
# Caddyfile
mywebsite.com {
reverse_proxy localhost:3000
}
No certbot, no cron. Caddy calls the Let's Encrypt API in the background and manages the renewal cycle.
Commercial certs: 1-3 year validity
Since September 2020 all publicly trusted certs have a max lifetime of 397 days (CA/B Forum baseline). Some companies still prefer commercial CAs because of:
- Extended Validation (EV) shows the organization in the address bar (Chrome has stopped displaying it prominently since 2019).
- Wildcard for many subdomains although Let's Encrypt now supports wildcards via DNS-01.
- Warranty financial liability of the CA in case of compromise.
- Compliance / audit some industries have external requirements.
For most sites Let's Encrypt or another free CA (ZeroSSL, Buypass) is enough.
Expiry monitoring as a safety net
Even if you have automatic renewal, expiry monitoring works as insurance. Renewal can fail because of:
- Rate limit from the CA (Let's Encrypt: 5 duplicates / 7 days)
- DNS change that breaks the ACME challenge
- Firewall rule blocking port 80 (HTTP-01 challenge)
- Crash of certbot or the cron that nobody noticed
ePulz.io tracks the expiry of every monitored endpoint and sends an alert 30, 14, 7, 3 and 1 day before expiry. One green signal that the cert renewed in time - and you have certainty that the automation works.
Activate SSL monitoring
Alerts 30/14/7/3/1 days before expiry. No configuration, no DNS changes. 7 days free.
Try ePulz.io free - 7 days, no credit card needed.
Create account