Let’s Encrypt SSL Auto Renewal on Linux VPS
This guide walks you through setting up automatic renewal for Let’s Encrypt SSL certificates on a Linux VPS. You’ll install Certbot, configure a renewal timer or cron job, and verify that your certificates renew without manual intervention. This ensures your HTTPS sites stay valid without you having to remember to renew every 90 days.
What You’ll Need
- A Linux VPS (Ubuntu, Debian, CentOS, or similar) with root or sudo access.
- A domain name pointing to your VPS’s public IP address.
- Port 80 (HTTP) and 443 (HTTPS) open in your firewall.
- An existing web server (Apache, Nginx, or a standalone server) running on the VPS.
- Basic familiarity with the command line.
Step-by-Step
- Install Certbot – Use your package manager. On Ubuntu/Debian:
sudo apt update && sudo apt install certbot. On CentOS/RHEL:sudo yum install certbot. If you use a web server plugin (e.g.,python3-certbot-nginxorpython3-certbot-apache), install that too. - Obtain an initial certificate – Run Certbot with the appropriate plugin. For Nginx:
sudo certbot --nginx -d example.com -d www.example.com. For Apache:sudo certbot --apache -d example.com. For a standalone setup (no web server):sudo certbot certonly --standalone -d example.com. Follow the prompts; this creates your first certificate and sets up automatic renewal hooks if you use the plugin. - Test the renewal command manually – Run
sudo certbot renew --dry-run. This simulates renewal without actually changing anything. It verifies that your domain is reachable and that the renewal process works. If it fails, see Troubleshooting below. - Set up automatic renewal with a systemd timer (recommended for most distros) – Certbot’s package usually includes a systemd timer. Check if it exists:
systemctl list-timers | grep certbot. If you seecertbot.timer, it’s already active. If not, create a timer file/etc/systemd/system/certbot.timerwith: - Create the service unit – Create
/etc/systemd/system/certbot.servicewith: - Enable and start the timer – Run
sudo systemctl daemon-reload, thensudo systemctl enable certbot.timerandsudo systemctl start certbot.timer. Verify withsystemctl status certbot.timer. - Alternatively, set up a cron job – If you prefer cron, add a line to your crontab (
sudo crontab -e):0 0 * * * /usr/bin/certbot renew --quiet(runs daily at midnight). Add--deploy-hook "systemctl reload nginx"orapache2if you need to reload the web server after renewal (though plugins usually handle this). - Verify renewal works – After setting up the timer or cron, run
sudo certbot renew --dry-runagain to confirm. Then check the timer’s last run:systemctl list-timers | grep certbot. - Check logs – Certbot logs to
/var/log/letsencrypt/letsencrypt.log. Review this periodically to ensure renewals are happening. You can also usesudo certbot certificatesto see expiry dates. - Test a real renewal (optional) – To force a renewal, run
sudo certbot renew --force-renewal. This will issue a new certificate immediately. Do this only if you’re comfortable, as it may hit rate limits (5 per domain per week).
# /etc/systemd/system/certbot.timer [Unit] Description=Run certbot renewal twice daily [Timer] OnCalendar=*-*-* 00,12:00:00 RandomizedDelaySec=3600 Persistent=true [Install] WantedBy=timers.target
# /etc/systemd/system/certbot.service [Unit] Description=Certbot renewal [Service] Type=oneshot ExecStart=/usr/bin/certbot renew --quiet
Common Mistakes
- Forgetting to open port 80 – Let’s Encrypt validation uses HTTP-01 challenge on port 80. If it’s closed, renewal fails.
- Using the wrong web server plugin – If you installed Certbot without the plugin for your server, it may fall back to standalone mode, which fails if port 80 is already in use.
- Not reloading the web server after renewal – Some setups require a reload to pick up the new certificate. Plugins usually do this automatically, but if you use a custom setup, add a deploy hook.
- Setting the timer to run too infrequently – Renewal must happen within 90 days. Running twice a day is safe and recommended; daily is fine. Weekly is risky if the server is down during the renewal attempt.
- Ignoring the dry-run output – If the dry-run fails, the real renewal will fail too. Always run it before moving on.
Tips
- Use a staging environment for testing – Certbot has a staging server with higher rate limits. Test with
--stagingbefore going live. - Set up email notifications – Add
--email you@example.comduring initial setup to receive expiry warnings. - Keep your system clock accurate – Use NTP to sync time; certificate validation depends on accurate timestamps.
- Monitor certificate expiry – Use a service like UptimeRobot or a simple cron script that checks
openssl s_clientto alert you if a certificate is about to expire. - Use the webroot method if you have multiple domains – For complex setups,
certbot certonly --webroot -w /var/www/html -d example.comcan be more flexible.
Troubleshooting
- Dry-run fails with “Invalid response from http://…” – Check that port 80 is reachable from the internet (use
curl -I http://example.com). If you’re using a firewall, allow it. Also ensure your web server is running and serving the correct domain. - “Too many certificates” error – Let’s Encrypt has rate limits. Wait a week or use the staging server for testing. If you need to renew immediately, you can request a rate-limit increase, but that’s rare.
- Timer doesn’t run – Check
systemctl status certbot.timerfor errors. Ensure the service file path is correct. Runsystemctl start certbot.servicemanually to see any errors. - Renewal succeeds but website still shows old certificate – Reload your web server:
sudo systemctl reload nginxorapache2. If you use a custom setup, add a deploy hook. - Certbot says “No renewals were attempted” – This is normal if the certificate is not within 30 days of expiry. To test, use
--force-renewal. - Port 80 is used by another service – Use the webroot method or stop the other service temporarily during renewal. Or use DNS-01 challenge with a plugin like
certbot-dns-cloudflareif you control DNS.
Frequently Asked Questions
How often does Certbot renew certificates?
Certbot checks for renewal twice a day by default with the systemd timer. It only actually renews if the certificate is within 30 days of expiry, so you won’t get new certificates every day.
Do I need to stop my web server for renewal?
No, if you use the Nginx or Apache plugin, renewal is seamless. If you use standalone mode, you must stop the server temporarily, but that’s not recommended for production.
What happens if renewal fails?
Certbot will retry on the next timer run. If it fails repeatedly, you’ll receive an email if you provided one. The old certificate remains valid until it expires, but after that, your site will show a security warning.
Can I use this with multiple domains on one server?
Yes, you can include all domains in one certificate: certbot --nginx -d example.com -d www.example.com -d blog.example.com. Renewal will renew all of them together.
Is it safe to run certbot renew manually?
Yes, it’s safe. It will only renew certificates that are due. To force a renewal, use --force-renewal, but be aware of rate limits.
How do I know my certificate is being renewed automatically?
Check the logs at /var/log/letsencrypt/letsencrypt.log for “Certificate not yet due for renewal” or “Renewal successful” entries. Also, run certbot certificates to see expiry dates.
Related
Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.