What visitors see right now
Chrome and Edge show NET::ERR_CERT_DATE_INVALID, Firefox reports SEC_ERROR_EXPIRED_CERTIFICATE, Safari simply says the connection is not private. All three display an interstitial that most visitors will not click through. For a landing page that is annoying; for a shop it means zero revenue until the certificate is renewed.
Worse is what you do not see: mobile apps, payment providers, webhooks and cron jobs on other systems validate certificates strictly and abort without any warning page. An expired certificate on an API can stop orders, synchronisations and logins without anyone seeing an error in a browser.
Immediate steps
Before renewing anything, find out which host actually terminates TLS. With a CDN like Cloudflare, a load balancer or a reverse proxy in front of the web server, the certificate on the origin is often not the one the browser sees. Renew in the wrong place and nothing changes.
- Use the SSL checker or openssl to see which certificate the browser receives and where it comes from (issuer, expiry date, hostnames in the SAN).
- Identify the terminating host: proxy, load balancer, CDN or the web server itself.
- Renew there: certbot renew for Let's Encrypt, the certificate section of Plesk, cPanel or your hosting panel, or the vendor portal for purchased certificates.
- Reload the service so it actually reads the new certificate, for example nginx -s reload or systemctl reload apache2.
- Verify from outside, not just locally. The problem is solved only when the check shows the new expiry date.
openssl s_client -connect www.example.com:443 -servername www.example.com </dev/null 2>/dev/null | openssl x509 -noout -dates -issuer -subjectWhy auto-renewal failed
Almost every expired Let's Encrypt certificate once had working automation that silently stopped at some point. The causes repeat, so it pays to find yours, otherwise you will be back here in 90 days.
- HTTP-01 challenge broken: the domain now points to a different server, or a redirect catches /.well-known/acme-challenge/.
- DNS-01 challenge broken: after a DNS migration the ACME client no longer has permission to create TXT records in the new zone.
- Port 80 blocked: a new firewall rule or provider change only allows 443, but HTTP-01 needs port 80.
- Cron or systemd timer not running: after a server migration the timer was never set up, or the job runs as a user without write permissions.
- Rate limits: too many failed attempts or too many certificates for the same domain in a short time.
- CAA record: a CAA entry only allows a specific CA, and Let's Encrypt is not on the list.
- Outdated ACME account or client: old certbot versions and retired API endpoints eventually stop working.
The ACME client log almost always names the cause in plain text. For certbot it lives in /var/log/letsencrypt/, and a dry run with certbot renew --dry-run tells you immediately whether the challenge works again.
Check the chain and intermediates
It is not always the leaf certificate that expired. Sometimes it is the intermediate certificate in the chain the server sends. Browsers with an up-to-date certificate store often build a valid chain on their own; older Android versions, Java clients and curl on old systems do not. The result: everything works on your laptop, but not at the client.
So always check the full chain, not just the first certificate. With Let's Encrypt, fullchain.pem belongs in the server configuration, not cert.pem. The SSL checker shows every level of the chain with its own expiry date.
openssl s_client -connect www.example.com:443 -servername www.example.com -showcerts </dev/null 2>/dev/null | grep -E "s:|i:|Verify return code"Lifetimes are shrinking, automation is mandatory
Let's Encrypt has always issued 90-day certificates and now offers much shorter ones as well. The CA/Browser Forum has decided to reduce the maximum lifetime of public certificates in steps, down to 47 days by 2029. This applies to all public CAs, including purchased certificates.
That is the end of manual renewal. A certificate that someone uploads to a panel once a year will be due every six weeks within a few years. If you still renew by hand, plan the switch to ACME now, while no expiry is pressing.
Prevention: monitoring with thresholds
Automation alone is not enough, because automation can fail silently. What helps is an independent external check that reads the certificate actually being served and warns in time. Staggered thresholds work well: 30 days as early information, 14 days as a sign that automation is apparently not kicking in, 7 days as an alarm.
Let's Encrypt normally renews 30 days before expiry. A certificate that has not been renewed with 14 days left very likely has a problem, and you have two weeks to fix it calmly instead of being called by the client on a weekend.
Frequently asked questions
- The certificate is renewed but the browser still shows the warning. Why?
- Usually the service was not reloaded and still serves the old certificate from memory. Check with openssl from outside what is actually being served. If the new certificate is visible, it is the browser cache or a CDN that still holds the old one.
- Can I renew early without any downtime?
- Yes. The new certificate is issued in parallel and activated on reload; visitors notice nothing. There is no reason to wait until the last day.
- Does a certificate with a longer lifetime help?
- Only in the short term. Maximum lifetimes are shrinking for all public CAs, and a one-year certificate just moves the problem to a date nobody remembers. Short lifetimes with working automation are more reliable.