Automated SSL Certificate Renewal for Docker Nginx
Prerequisites
- Docker and Docker Compose installed
- Nginx running in Docker container
- Certbot installed on host
- Sudo access
Step 1: Configure Passwordless Sudo
Install certbot
sudo apt install certbotAllow certbot to run without password prompts:
# Create sudoers entry
echo "$USER ALL=(ALL) NOPASSWD: /usr/bin/certbot, /usr/bin/docker" | sudo tee /etc/sudoers.d/$USER-nopasswd
# Set permissions
sudo chmod 440 /etc/sudoers.d/$USER-nopasswd
# Test it works
sudo certbot --versionStep 2: Test Renewal
Find your paths and test the renewal process:
# Find your docker-compose.yml path
# Example: /home/user/myapp/docker-compose.yml
# Find your nginx container name
docker ps | grep nginx
# Example: nginx_prod, nginx, myapp_nginx
# Run dry-run test (doesn't actually renew)
sudo certbot renew --dry-run
--pre-hook "docker compose -f /path/to/docker-compose.yml stop nginx_container"
--post-hook "docker compose -f /path/to/docker-compose.yml start nginx_container"
Example with real paths:
sudo certbot renew --dry-run
--pre-hook "docker compose -f /home/yocto-admin/builds/ymB6__kg9/0/yocto.dev/pmpassport/docker-compose.yml stop nginx"
--post-hook "docker compose -f /home/yocto-admin/builds/ymB6__kg9/0/yocto.dev/pmpassport/docker-compose.yml start nginx"Step 3: Add Cron Job
Automate daily renewal checks:
# Edit crontab
crontab -e
# Add this line (replace with your actual paths):
0 2 * * * sudo certbot renew --pre-hook "docker compose -f /path/to/docker-compose.yml stop nginx_container" --post-hook "docker compose -f /path/to/docker-compose.yml start nginx_container" >> /var/log/certbot-renew.log 2>&1
# Save and exit
Real example:
0 2 * * * sudo certbot renew --pre-hook "docker compose -f /home/yocto-admin/builds/ymB6__kg9/0/yocto.dev/pmpassport/docker-compose.yml stop nginx" --post-hook "docker compose -f /home/yocto-admin/builds/ymB6__kg9/0/yocto.dev/pmpassport/docker-compose.yml start nginx" >> /var/log/certbot-renew.log 2>&1
Verify it was added:
crontab -lHow It Works
- Cron runs daily at 2 AM
- Certbot checks if renewal is needed (within 30 days of expiry)
- If not needed: Does nothing
- If needed: Stops nginx → Renews certificate → Starts nginx
- Logs everything to:
/var/log/certbot-renew.log
Monitoring
Check if renewal happened
cat /var/log/certbot-renew.log
Check certificate expiry
sudo certbot certificates
Force renewal (for testing)
sudo certbot renew --force-renewal
--pre-hook "docker compose -f /path/to/docker-compose.yml stop nginx"
--post-hook "docker compose -f /path/to/docker-compose.yml start nginx"
Quick Troubleshooting
“Certificate not yet due for renewal”
→ Normal. Certbot only renews within 30 days of expiry.
“Port 80 already in use”
→ Check your nginx container name: docker ps
Cron not running
→ Test manually: Run the exact cron command from terminal
Complete Example
# Step 1: Configure sudo
echo "yocto-admin ALL=(ALL) NOPASSWD: /usr/bin/certbot, /usr/bin/docker" | sudo tee /etc/sudoers.d/yocto-admin-nopasswd
sudo chmod 440 /etc/sudoers.d/yocto-admin-nopasswd
# Step 2: Test
sudo certbot renew --dry-run
--pre-hook "docker compose -f /home/yocto-admin/builds/ymB6__kg9/0/yocto.dev/pmpassport/docker-compose.yml stop nginx"
--post-hook "docker compose -f /home/yocto-admin/builds/ymB6__kg9/0/yocto.dev/pmpassport/docker-compose.yml start nginx"
# Step 3: Automate
crontab -e
# Add:
0 2 * * * sudo certbot renew --pre-hook "docker compose -f /home/yocto-admin/builds/ymB6__kg9/0/yocto.dev/pmpassport/docker-compose.yml stop nginx" --post-hook "docker compose -f /home/yocto-admin/builds/ymB6__kg9/0/yocto.dev/pmpassport/docker-compose.yml start nginx" >> /var/log/certbot-renew.log 2>&1







