ThisCalculator

Everyday

Let’s Encrypt SSL Auto Renewal on Linux VPS

Updated · Standard formula, shown below

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

  1. 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-nginx or python3-certbot-apache), install that too.
  2. 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.
  3. 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.
  4. 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 see certbot.timer, it’s already active. If not, create a timer file /etc/systemd/system/certbot.timer with:
  5. # /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
  6. Create the service unit – Create /etc/systemd/system/certbot.service with:
  7. # /etc/systemd/system/certbot.service
    [Unit]
    Description=Certbot renewal
    
    [Service]
    Type=oneshot
    ExecStart=/usr/bin/certbot renew --quiet
    
  8. Enable and start the timer – Run sudo systemctl daemon-reload, then sudo systemctl enable certbot.timer and sudo systemctl start certbot.timer. Verify with systemctl status certbot.timer.
  9. 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" or apache2 if you need to reload the web server after renewal (though plugins usually handle this).
  10. Verify renewal works – After setting up the timer or cron, run sudo certbot renew --dry-run again to confirm. Then check the timer’s last run: systemctl list-timers | grep certbot.
  11. Check logs – Certbot logs to /var/log/letsencrypt/letsencrypt.log. Review this periodically to ensure renewals are happening. You can also use sudo certbot certificates to see expiry dates.
  12. 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).

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 --staging before going live.
  • Set up email notifications – Add --email you@example.com during 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_client to 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.com can 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.timer for errors. Ensure the service file path is correct. Run systemctl start certbot.service manually to see any errors.
  • Renewal succeeds but website still shows old certificate – Reload your web server: sudo systemctl reload nginx or apache2. 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-cloudflare if 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.