📚 Learning Objectives
By the end of this module, you will: - Understand certificate expiration - Set up automatic renewal - Test renewal process - Configure renewal hooks - Troubleshoot renewal issues - Monitor certificate expiration
⏰ Certificate Expiration
Let's Encrypt Certificate Lifecycle
- Validity Period: 90 days
- Recommended Renewal: Every 60 days
- Automatic Renewal: Set up to run automatically
Why Auto-Renewal?
- Certificates expire every 90 days
- Manual renewal is error-prone
- Prevents service interruption
- Ensures continuous HTTPS
🔄 Setting Up Auto-Renewal
Automatic Setup (NGINX Plugin)
If you used certbot --nginx, auto-renewal is usually configured automatically:
# Check renewal timer status
sudo systemctl status certbot.timer
# Check renewal service
sudo systemctl status certbot.service
Manual Setup
Certbot creates a systemd timer for automatic renewal:
# Check if timer exists
sudo systemctl list-timers | grep certbot
# Enable and start timer (if not running)
sudo systemctl enable certbot.timer
sudo systemctl start certbot.timer
Verify Timer Configuration
# View timer file
sudo cat /lib/systemd/system/certbot.timer
# Check timer status
sudo systemctl status certbot.timer
sudo systemctl list-timers certbot.timer
🧪 Testing Renewal
Dry Run (Test Without Renewing)
# Test renewal without actually renewing
sudo certbot renew --dry-run
# Test specific certificate
sudo certbot renew --dry-run --cert-name example.com
Expected Output:
The dry run was successful.
Force Renewal (For Testing)
# Force renewal (even if not expired)
sudo certbot renew --force-renewal
# Renew specific certificate
sudo certbot renew --cert-name example.com --force-renewal
Warning: Don't do this too often - respect rate limits!
⚙️ Renewal Configuration
Renewal Configuration Files
Certbot stores renewal configuration in:
/etc/letsencrypt/renewal/
View Renewal Configuration
# List renewal configs
sudo ls -la /etc/letsencrypt/renewal/
# View specific renewal config
sudo cat /etc/letsencrypt/renewal/example.com.conf
Example renewal configuration:
# renew_before_expiry = 30 days
version = 2.0.0
archive_dir = /etc/letsencrypt/archive/example.com
cert = /etc/letsencrypt/live/example.com/cert.pem
privkey = /etc/letsencrypt/live/example.com/privkey.pem
chain = /etc/letsencrypt/live/example.com/chain.pem
fullchain = /etc/letsencrypt/live/example.com/fullchain.pem
# Options used in the renewal request
renew_hook = systemctl reload nginx
🔧 Renewal Hooks
Pre-Hook (Before Renewal)
Runs before certificate renewal:
# In renewal config file
pre_hook = systemctl stop nginx
Renewal Hook (After Renewal)
Runs after successful renewal:
# In renewal config file
renew_hook = systemctl reload nginx
Post-Hook (Always Runs)
Runs after renewal attempt (success or failure):
# In renewal config file
post_hook = systemctl start nginx
Configure Hooks via Command Line
# Add renewal hook
sudo certbot renew --renew-hook "systemctl reload nginx"
# Add pre-hook (for standalone mode)
sudo certbot renew --pre-hook "systemctl stop nginx" --post-hook "systemctl start nginx"
Example: Standalone Mode with Hooks
# Renewal command with hooks
sudo certbot renew \
--pre-hook "systemctl stop nginx" \
--post-hook "systemctl start nginx" \
--renew-hook "systemctl reload nginx"
📅 Scheduling Renewal
Systemd Timer (Default)
Certbot uses systemd timer that runs twice daily:
# Check timer schedule
sudo systemctl list-timers certbot.timer
# View timer details
sudo systemctl cat certbot.timer
Cron Job (Alternative)
If systemd isn't available, use cron:
# Edit crontab
sudo crontab -e
# Add renewal check (runs twice daily)
0 0,12 * * * certbot renew --quiet --renew-hook "systemctl reload nginx"
Cron Schedule Explanation:
- 0 0,12 * * *: Run at 00:00 and 12:00 every day
- --quiet: Only output on errors
- --renew-hook: Reload NGINX after renewal
🔍 Monitoring Certificate Expiration
Check Certificate Expiration
# List all certificates with expiration
sudo certbot certificates
# Check specific certificate
sudo certbot certificates --cert-name example.com
# Check expiration date
sudo openssl x509 -in /etc/letsencrypt/live/example.com/cert.pem -noout -dates
Automated Expiration Check Script
Create a monitoring script:
#!/bin/bash
# /usr/local/bin/check-cert-expiry.sh
DOMAIN="example.com"
DAYS_BEFORE_EXPIRY=30
CERT_FILE="/etc/letsencrypt/live/$DOMAIN/cert.pem"
EXPIRY_DATE=$(openssl x509 -in "$CERT_FILE" -noout -enddate | cut -d= -f2)
EXPIRY_TIMESTAMP=$(date -d "$EXPIRY_DATE" +%s)
CURRENT_TIMESTAMP=$(date +%s)
DAYS_UNTIL_EXPIRY=$(( ($EXPIRY_TIMESTAMP - $CURRENT_TIMESTAMP) / 86400 ))
if [ $DAYS_UNTIL_EXPIRY -lt $DAYS_BEFORE_EXPIRY ]; then
echo "WARNING: Certificate for $DOMAIN expires in $DAYS_UNTIL_EXPIRY days"
# Send alert (email, notification, etc.)
fi
Add to cron:
# Run daily
0 9 * * * /usr/local/bin/check-cert-expiry.sh
📧 Email Notifications
Renewal Reminders
Let's Encrypt sends email reminders: - 20 days before expiration - 10 days before expiration - 1 day before expiration
Update Email Address
# Update email for account
sudo certbot update_account --email newemail@example.com
# Register new account with email
sudo certbot register --email youremail@example.com --agree-tos
🔧 Advanced Renewal Options
Renewal for Specific Certificates
# Renew specific certificate
sudo certbot renew --cert-name example.com
# Renew certificates for specific domains
sudo certbot renew --cert-path /etc/letsencrypt/live/example.com
Quiet Mode
# Only output on errors (for cron)
sudo certbot renew --quiet
Non-Interactive Renewal
# Run without user interaction
sudo certbot renew --quiet --non-interactive
Renewal with Specific Plugin
# Renew using NGINX plugin
sudo certbot renew --nginx
# Renew using standalone
sudo certbot renew --standalone
🚨 Troubleshooting Renewal
Issue: Renewal Fails
Check logs:
# Certbot logs
sudo tail -f /var/log/letsencrypt/letsencrypt.log
# System logs
sudo journalctl -u certbot.timer
sudo journalctl -u certbot.service
Common causes: - Domain DNS changed - Port 80 blocked - NGINX configuration error - Rate limit exceeded
Issue: Timer Not Running
# Check timer status
sudo systemctl status certbot.timer
# Enable and start timer
sudo systemctl enable certbot.timer
sudo systemctl start certbot.timer
# Check if timer is scheduled
sudo systemctl list-timers
Issue: NGINX Not Reloading
# Manually reload after renewal
sudo certbot renew --renew-hook "systemctl reload nginx"
# Test NGINX config first
sudo nginx -t
Issue: Rate Limit Exceeded
# Check rate limit status
# Visit: https://letsencrypt.org/docs/rate-limits/
# Wait before retrying
# Use staging server for testing
sudo certbot renew --staging
📊 Renewal Best Practices
- Test Regularly: Run
--dry-runmonthly - Monitor Logs: Check renewal logs regularly
- Use Hooks: Configure renewal hooks properly
- Backup Certificates: Backup certificate files
- Monitor Expiration: Set up expiration alerts
- Document Process: Document your renewal setup
📝 Complete Renewal Setup Example
Systemd Timer Setup
# Enable timer
sudo systemctl enable certbot.timer
sudo systemctl start certbot.timer
# Verify
sudo systemctl status certbot.timer
sudo systemctl list-timers certbot.timer
Renewal Configuration
# Test renewal
sudo certbot renew --dry-run
# Configure renewal hooks (if needed)
# Edit /etc/letsencrypt/renewal/example.com.conf
# Add: renew_hook = systemctl reload nginx
Monitoring Script
Create monitoring and alerting for certificate expiration.
📝 Exercises
- Check if auto-renewal is enabled
- Test renewal with
--dry-run - Verify renewal timer is scheduled
- Configure renewal hooks
- Check certificate expiration dates
- Create expiration monitoring script
- Test forced renewal (with caution)
- Review renewal logs
✅ Checklist
- [ ] Auto-renewal enabled and working
- [ ] Renewal timer scheduled
- [ ] Tested renewal with
--dry-run - [ ] Renewal hooks configured
- [ ] Monitoring expiration dates
- [ ] Email notifications set up
- [ ] Documented renewal process
- [ ] Tested renewal process
➡️ Next Steps
Proceed to Module 5: Troubleshooting to learn how to troubleshoot common Let's Encrypt issues.