ExpiryPing
← Back to Blog

June 16, 2026 · 5 min read

Why Let's Encrypt Auto-Renewal Fails (And How to Catch It)

Let's Encrypt is supposed to renew certificates automatically. When it silently fails, your site goes down with a security warning. Here are the most common failure modes and how to catch them before your visitors do.

Let's Encrypt was supposed to make expired certificates a thing of the past. Set up certbot, let it run, never think about SSL again.

Except it fails. Quietly. And the first sign is usually a client or a visitor telling you their browser is showing a security warning on your site.

If you're here because a renewal just failed, the fixes are below. If you're here to prevent it, skip to the monitoring section.

Why Auto-Renewal Fails Silently

The dangerous part isn't that renewal fails. It's that it fails without telling anyone. Certbot runs on a timer, the renewal errors out, and the error goes into a log file nobody reads. The certificate keeps working until the day it expires, then the site breaks.

Here are the failure modes that cause it.

1. The Renewal Timer Stopped Running

Certbot installs a systemd timer or cron job to handle renewals. If that timer gets disabled, removed during a server migration, or the server was rebuilt without reinstalling it, renewals simply never run.

Check it:

  • Run systemctl list-timers | grep certbot to confirm the timer is active
  • Run certbot renew --dry-run to test renewal without making changes

If the timer is gone, the certificate will expire on schedule with zero warning.

2. The HTTP-01 Challenge Can't Reach Your Server

Let's Encrypt verifies you control the domain by requesting a file at /.well-known/acme-challenge/. If anything blocks that path, validation fails.

Common causes:

  • A firewall rule added after the initial setup
  • An nginx or Apache config change that redirects all HTTP to HTTPS before the challenge completes
  • A CDN or reverse proxy intercepting the request
  • Port 80 closed entirely

The certificate was issued fine the first time, so this often appears months later after an unrelated config change.

3. DNS-01 Challenge Failures

If you use wildcard certificates, you need the DNS-01 challenge, which requires creating a TXT record. This breaks when:

  • The DNS provider API credentials expired or were rotated
  • You migrated nameservers and the renewal plugin still points at the old provider
  • The TXT record update is slow to propagate and the validation times out

Wildcard certs are the most fragile to auto-renew because they depend on an external API that can change underneath you.

4. The Certificate Renewed But the Server Didn't Reload

This one is insidious. Certbot successfully fetches a new certificate, but nginx or Apache keeps serving the old one from memory because nothing reloaded the service. The cert on disk is valid; the cert being served is expired.

The fix is a deploy hook:

  • Add --deploy-hook "systemctl reload nginx" to your renewal config

Without it, renewal can succeed and your site can still go down.

5. Rate Limiting

Let's Encrypt enforces rate limits — currently 5 duplicate certificates per week. If a misconfigured script requests certificates in a loop, you can hit the limit and be locked out of renewing the one you actually need until the window resets.

The Common Thread

Every one of these failures shares the same property: the certificate keeps working right up until it expires. There is no error visible to anyone unless they're actively reading server logs.

That's why "we use auto-renewal" is not the same as "we're protected." Auto-renewal handles the happy path. It does nothing to tell you when the happy path breaks.

How to Actually Catch It

The only reliable defense is to monitor the certificate from the outside — the same way a visitor's browser sees it.

External monitoring checks the actual certificate being served, not the one sitting in a file on disk. So if renewal succeeds but the server never reloaded, external monitoring still catches the expired cert because it sees what the public sees.

A good setup checks every certificate daily and alerts you well before expiry — 30, 14, 7, and 1 day out — so a single failed renewal becomes an email, not an outage.

That's what I built ExpiryPing for. It connects to your domain the same way a browser does, reads the certificate expiry date, and alerts you by email and Slack before anything expires. It catches the silent failures — including the renewed-but-not-reloaded case that internal checks miss — because it only looks at what's actually being served.

No credentials, no agents, no access to your server. You add the hostname, it watches. Free for up to 3 domains, paid plans from $19/month.

Auto-renewal is great when it works. External monitoring is how you find out when it doesn't.

Monitor your SSL certificates and domains

ExpiryPing alerts you at 30, 14, 7, and 1 day before anything expires. No credentials required. Free for 3 domains.

Start Free