Let's Encrypt Certificate Renewal Failed
Troubleshoot and fix failed Let's Encrypt certificate renewals with Certbot, common errors and solutions
Let's Encrypt certificates expire after 90 days. Automatic renewal failures can silently take your site offline. This guide covers the most common renewal errors and how to fix them.
Check Certificate Status
View All Certificates
sudo certbot certificatesCheck Expiration Date
openssl x509 -in /etc/letsencrypt/live/yourdomain.com/fullchain.pem -noout -datesSample output:
notBefore=Jan 15 10:30:00 2025 GMT
notAfter=Apr 15 10:30:00 2025 GMTCommon Errors and Solutions
Error: Connection Refused / Port 80 Blocked
Cause: Nginx/Apache not running, or port 80 not accessible during renewal.
Solution: Use --nginx or --apache mode instead of standalone:
# For Nginx
sudo certbot renew --nginx
# For Apache
sudo certbot renew --apache
# Force renewal if needed
sudo certbot renew --force-renewal --nginxWith webroot mode, ensure Nginx/Apache is running and can serve /.well-known/acme-challenge/ directory during renewal.
Error: Too Many Certificates (Rate Limit)
Cause: Let's Encrypt enforces limits: 5 certificates per domain per 7 days.
Solution: Test with staging environment first:
# Test renewal against staging (no rate limit)
sudo certbot renew --staging --dry-run
# Once tested, do real renewal
sudo certbot renewError: Domain Validation Failed
Cause: DNS does not point to your server.
Solution: Verify DNS resolution:
dig yourdomain.com A
nslookup yourdomain.com
curl -I https://yourdomain.comEnsure A record points to your VPS public IP.
Error: Error Creating New Order
Cause: Server clock is out of sync (NTP issue).
Solution: Restart NTP sync:
# Check current time
date
# Restart systemd-timesyncd
sudo systemctl restart systemd-timesyncd
# Verify time is correct
timedatectl status
# Retry renewal
sudo certbot renew --force-renewalManual Forced Renewal
Force renewal even if certificate is not expiring soon:
sudo certbot renew --force-renewalPre and Post Renewal Hooks
Certbot can run scripts before/after renewal to restart services or perform cleanup.
Create Renewal Hooks
# Pre-renewal hook (stop services)
sudo mkdir -p /etc/letsencrypt/renewal-hooks/pre
sudo tee /etc/letsencrypt/renewal-hooks/pre/stop-services.sh > /dev/null <<'EOF'
#!/bin/bash
systemctl stop nginx
EOF
sudo chmod +x /etc/letsencrypt/renewal-hooks/pre/stop-services.sh
# Post-renewal hook (start services)
sudo mkdir -p /etc/letsencrypt/renewal-hooks/post
sudo tee /etc/letsencrypt/renewal-hooks/post/start-services.sh > /dev/null <<'EOF'
#!/bin/bash
systemctl start nginx
EOF
sudo chmod +x /etc/letsencrypt/renewal-hooks/post/start-services.shTest Hooks
sudo certbot renew --dry-runVerify Automatic Renewal
Check if Certbot timer is enabled and running:
sudo systemctl status certbot.timerView upcoming timer runs:
sudo systemctl list-timers | grep certbotSample output:
NEXT LEFT LAST TRIGGER PASSED UNIT ACTIVATES
Wed 2025-04-09 06:47:00 UTC 8h left Mon 2025-04-07 10:00:00 UTC yes certbot.timerWildcard Certificate with DNS Challenge
For wildcard domains (*.yourdomain.com), use DNS challenge:
sudo certbot certonly --manual --preferred-challenges dns \
-d "*.yourdomain.com" \
-d "yourdomain.com"Certbot will ask you to add a TXT record to your DNS. Wait for DNS propagation before confirming:
dig _acme-challenge.yourdomain.com TXTTroubleshooting Logs
View detailed renewal logs:
# Current renewal status
sudo journalctl -u certbot -f
# Check renewal history
cat /var/log/letsencrypt/letsencrypt.log | tail -50Dry Run Test
Always test renewal without actually renewing:
sudo certbot renew --dry-runIf dry run succeeds, actual renewal will work.
Let's Encrypt certificates expire after 90 days. If automatic renewal is broken and unnoticed, your site will go offline. Check certificate expiration dates weekly and monitor renewal logs.
Quick Troubleshooting Checklist
- Verify domain DNS points to VPS:
dig yourdomain.com A - Test renewal with
--dry-run:sudo certbot renew --dry-run - Check server time is correct:
timedatectl status - Ensure web server (Nginx/Apache) is running
- Verify port 80 is open from public internet:
curl http://yourdomain.com - Check certificate expiration:
openssl x509 -in /etc/letsencrypt/live/yourdomain.com/fullchain.pem -noout -dates - Review logs:
sudo tail -f /var/log/letsencrypt/letsencrypt.log