An expired SSL certificate makes every browser block the site with a security warning. Fix it by renewing the certificate with your CA and reinstalling it on the server, then automate renewal so it can't lapse again. With certificate lifetimes shrinking to 47 days by 2029, automation is no longer optional.
What does an expired certificate do?
A TLS certificate is valid only between two dates — a "not before" and a "not after" timestamp baked into the certificate itself. The moment the clock passes the "not after" date, the certificate is expired, and every modern browser treats the connection as untrusted.
There is no grace period and no soft warning: Chrome, Firefox, Edge, and Safari all replace your page with a full-screen interstitial before any content loads.
In Chrome the visitor sees "Your connection is not private" with the subcode NET::ERR_CERT_DATE_INVALID under Advanced. Other browsers show their own wording for the same condition. The effect is the same everywhere — the site is effectively offline.
Search crawlers that hit an expired certificate may drop the page, and any API or webhook that calls your domain over HTTPS will fail its TLS handshake. An expired certificate is not a cosmetic problem; it is a full outage for anything that depends on the hostname.
The cause is almost always mundane: a renewal that was supposed to happen automatically didn't, or a manual certificate that nobody remembered to replace. The fix is equally concrete, and it splits cleanly by who you are.
If you're just visiting
If you landed here because a site you wanted to read is showing this warning, the short answer is that you cannot fix it. The certificate lives on the site's server, and only the people who run that server can renew it. Nothing you change in your own browser will make a genuinely expired certificate trusted again.
Before assuming the site is at fault, rule out the one local cause: your own device clock. A TLS certificate is judged against your computer's current time, so if your clock is set days or years off, a perfectly valid certificate looks expired and you get the same warning on every HTTPS site at once.
Turn on automatic date and time in your system settings and reload. If the warning only appears on one site, the problem is on their end.
When it is genuinely the site's certificate, the most useful thing you can do is tell the owner — a quick note saying "your SSL certificate expired and the site is showing a security warning" is often the first they hear of it. In the meantime, never click Proceed to bypass the warning on a page where you would log in or enter a card number. The block exists precisely because the connection can no longer be verified.
If you own the site
Your certificate has expired and visitors are being turned away. The fix is three steps — renew, reinstall, verify — followed by the step that actually matters long term: automate so this never happens again.
1. Renew the certificate
If you use a free, automated CA such as Let's Encrypt, renewal is a single command. Certbot will request a fresh certificate, prove control of the domain, and write the new files to disk:
# Let's Encrypt via certbot — renew now
sudo certbot renew --force-renewal
# or issue/renew for a specific host
sudo certbot certonly --nginx -d example.com -d www.example.comIf you bought a certificate from a commercial CA (DigiCert, Sectigo, GlobalSign and the like), log in to their dashboard, renew the order, and complete domain validation. They will re-issue the certificate, which you then download as a leaf certificate plus an intermediate (chain) bundle. Keep your existing private key, or generate a new key and CSR if the CA requires one.
2. Reinstall on the server
A renewed certificate does nothing until the web server is pointed at the new files and reloaded. For nginx, the certificate directives reference the full chain (your leaf plus the intermediates) and the private key:
# nginx — point at the new files, then reload
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # leaf + intermediates
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
}
# test config, then reload (no downtime)
sudo nginx -t && sudo systemctl reload nginxFor Apache, the equivalent directives live in your SSL virtual host:
# Apache (httpd-ssl.conf or the vhost)
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/example.com/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/example.com/chain.pem
# test config, then reload
sudo apachectl configtest && sudo systemctl reload apache23. Verify from outside
Always confirm the fix from somewhere other than the server itself, because local caches and trust stores can mask a problem visitors still see. Check the new expiry date and that the full chain is being served:
# show the dates the live server is presenting
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
| openssl x509 -noout -datesThe notAfter line should now be in the future. If it still shows the old date, the server is serving a cached or stale certificate — see the gotcha below.
4. Automate renewal — the step that matters
Renewing by hand is exactly how you got here. The durable fix is to make renewal automatic and to alert yourself if it ever fails. Certbot installs a systemd timer (or cron job) that attempts renewal twice a day and only acts when a certificate is within 30 days of expiry. Confirm it is active and use a deploy hook so the web server reloads automatically the moment a new certificate lands:
# confirm the renewal timer is running
systemctl list-timers | grep certbot
# dry-run the whole renewal path without changing anything
sudo certbot renew --dry-run
# reload the server automatically after every successful renewal
sudo certbot renew --deploy-hook "systemctl reload nginx"Automation is no longer a nice-to-have. The CA/Browser Forum's ballot SC-081 sets a schedule that cuts the maximum validity of a public TLS certificate to just 47 days by 15 March 2029. At that length a certificate must be renewed roughly eight times a year — a cadence no team can reliably hit by hand.
And the problem is already widespread: AppViewX reports that up to 25% of TLS certificates are expired at any given time. Treat the timer plus a deploy hook as the real fix; the renewal you ran above is only the emergency patch.
Want to check your certificate's expiry and chain right now?
Check your certificate →For peace of mind beyond a single check, add ongoing monitoring so an expiring certificate pages you before browsers do. A scheduled full scan watches your certificate's expiry date (and the rest of your TLS configuration) continuously, so a stalled renewal becomes an alert in your inbox rather than an outage your customers report.
Why does the site still show expired after I renewed?
systemctl reload nginx (or the Apache equivalent). Even then, a CDN, load balancer, or reverse proxy sitting in front of your origin may hold its own copy of the certificate and keep serving the expired one from cache. If openssl shows a fresh date at the origin but visitors still see the warning, renew or update the certificate at the edge (Cloudflare, Fastly, your ALB) too, and clear its TLS cache. The certificate is only fixed once every layer that terminates HTTPS is serving the new one.Once the new certificate is installed at every layer and automated renewal is verified, an expired-certificate outage stops being a recurring emergency and becomes something you simply don't think about again.
For the wider context, see the pillar guide to SSL/TLS errors, and for the specific Chrome warning an expired certificate produces, read how to fix NET::ERR_CERT_DATE_INVALID.