Common Issues

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 certificates

Check Expiration Date

openssl x509 -in /etc/letsencrypt/live/yourdomain.com/fullchain.pem -noout -dates

Sample output:

notBefore=Jan 15 10:30:00 2025 GMT
notAfter=Apr 15 10:30:00 2025 GMT

Common 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 --nginx

With 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 renew

Error: 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.com

Ensure 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-renewal

Manual Forced Renewal

Force renewal even if certificate is not expiring soon:

sudo certbot renew --force-renewal

Pre 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.sh

Test Hooks

sudo certbot renew --dry-run

Verify Automatic Renewal

Check if Certbot timer is enabled and running:

sudo systemctl status certbot.timer

View upcoming timer runs:

sudo systemctl list-timers | grep certbot

Sample 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.timer

Wildcard 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 TXT

Troubleshooting Logs

View detailed renewal logs:

# Current renewal status
sudo journalctl -u certbot -f

# Check renewal history
cat /var/log/letsencrypt/letsencrypt.log | tail -50

Dry Run Test

Always test renewal without actually renewing:

sudo certbot renew --dry-run

If 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

On this page