Back to Learning Center
DevOps

Let's Encrypt Renewal Failed: Troubleshooting Guide

7 min read·Updated June 2026·By CertNotify Team

Let's Encrypt certificates expire every 90 days. Certbot handles renewal automatically — until it doesn't. When renewal fails silently, you discover it when your site shows a certificate error to all visitors. Here's how to diagnose and fix every common failure scenario.

Run Renewal Manually First

Always start by running renewal manually to see the actual error:

# Run as root / sudo
sudo certbot renew --dry-run

The --dry-run flag tests without actually renewing. Remove it for real renewal. Certbot's error output will tell you exactly what failed.

# Check renewal logs
sudo cat /var/log/letsencrypt/letsencrypt.log | tail -100

Error: Connection Refused / Port 80 Blocked

Error: Challenge failed for domain example.com
Connection refused

The HTTP-01 challenge requires port 80 to be accessible from the internet. Check:

# Check if port 80 is listening
sudo ss -tlnp | grep :80

# Check firewall
sudo ufw status
sudo ufw allow 80/tcp

If you're using Cloudflare or a load balancer that strips port 80, switch to DNS-01 challenge (see below).

Error: ACME Challenge File Not Found

Error: 404 Not Found
/.well-known/acme-challenge/xxxxx

The challenge file is created but your web server is not serving it. Common causes:

Web root mismatch

Ensure --webroot-path matches your actual web root (e.g., /var/www/html)

Nginx rewrite rules

Add an exception before catch-all rewrites: location ^~ /.well-known/acme-challenge/ { root /var/www/html; }

PHP/app catching all routes

Ensure /.well-known/ is excluded from application routing

Error: Rate Limit Exceeded

Error: too many certificates already issued

Let's Encrypt rate limits: 50 certificates per registered domain per week, 5 duplicate certificates per week. If you hit limits: wait until the limit resets, use the staging environment for testing (--staging flag), and avoid re-issuing when renewals will suffice.

Switch to DNS-01 Challenge

DNS-01 works even when port 80 is blocked, behind Cloudflare, or for wildcard certificates:

# Install Cloudflare DNS plugin (example)
sudo pip install certbot-dns-cloudflare

# Create credentials file
sudo mkdir -p /etc/letsencrypt/cloudflare
echo "dns_cloudflare_api_token = YOUR_TOKEN" | sudo tee /etc/letsencrypt/cloudflare/credentials.ini
sudo chmod 600 /etc/letsencrypt/cloudflare/credentials.ini

# Issue wildcard certificate
sudo certbot certonly --dns-cloudflare --dns-cloudflare-credentials /etc/letsencrypt/cloudflare/credentials.ini -d "*.yourdomain.com" -d "yourdomain.com"

Verify Auto-Renewal is Set Up

# Check if systemd timer is active (modern systems)
sudo systemctl status certbot.timer

# Or check cron
sudo crontab -l | grep certbot

# Manual cron entry if missing
0 3 * * * /usr/bin/certbot renew --quiet --post-hook "systemctl reload nginx"

Renewal Checklist

Port 80 accessible from the internet (or DNS-01 configured)
Web root path matches actual document root
Systemd timer or cron job running certbot renew
Post-hook reloads web server after renewal
Monitoring alerts set up for 30 and 7 days before expiry

Use our free SSL Certificate Checker to immediately verify whether your current certificate is valid and how many days remain before expiry.

Don't Rely on Certbot Alone

Certbot failures can be silent. Set up external certificate monitoring as a safety net — CertNotify checks your certificates every 24 hours and alerts you before expiry, independent of your renewal setup.

Monitor Your Certificates Free