Let's Encrypt Auto-Renewal Setup for Ubuntu Servers

11 min read 2,132 words
Let's Encrypt Auto-Renewal: Making Sure Your SSL Never Expires featured image

How Let's Encrypt Certificate Renewal Works

Let's Encrypt certificates are valid for 90 days. This shorter validity period limits the potential damage if a private key is compromised and encourages automated renewal practices. Certbot, the official Let's Encrypt client, handles renewal automatically on most Ubuntu systems when configured correctly.

If you are new to Let's Encrypt or have not yet set up your initial certificate, reviewing the setup guide for Let's Encrypt on Ubuntu helps you understand the complete process before configuring auto-renewal.

Certbot Auto-Renewal Configuration on Ubuntu

When you install Certbot with apt install certbot python3-certbot-nginx or python3-certbot-apache, it installs a systemd timer that runs the renewal check twice per day by default. This behaviour is standard on Ubuntu 18.04 and later systems.

Verify the timer is active with this command.

sudo systemctl status certbot.timer

The timer runs certbot renew, which checks all installed certificates. If any certificate is within 30 days of expiry, Certbot attempts to renew it. The renew command only requests a new certificate when renewal is genuinely needed, so on most days no new certificate is issued.

View when the timer is scheduled to run next.

sudo systemctl list-timers

Testing Your Renewal Setup

Before relying on auto-renewal in a production environment, test that it works correctly. Running the dry-run command confirms renewal functionality without issuing new certificates.

sudo certbot renew --dry-run

If the dry-run succeeds, your auto-renewal configuration is working as expected. If it fails, resolve the errors before the certificate expires. A failed dry-run usually indicates a configuration problem that will also prevent production renewal from succeeding.

Testing is particularly important after making changes to your web server configuration, such as updating Nginx or Apache settings, changing document roots, or modifying firewall rules.

Common Renewal Problems and How to Fix Them

Several issues frequently cause renewal failures on Ubuntu servers. Identifying and resolving them promptly prevents certificate expiration and the security warnings that follow.

Port 80 Is Blocked

Let's Encrypt uses the ACME HTTP-01 challenge for domain verification. This requires port 80 to be accessible from the internet. If a firewall blocks it or a reverse proxy intercepts traffic before it reaches Certbot, renewal fails silently or with a connection error.

Check your firewall rules to ensure port 80 is open.

sudo ufw status
sudo iptables -L INPUT -n | grep 80

If you use UFW and need to open port 80, the command is straightforward.

sudo ufw allow 80/tcp

Many Ubuntu servers run web applications behind an Nginx reverse proxy. If this matches your setup, the reverse proxy configuration guide covers how to handle SSL certificate challenges correctly with proxy forwarding in place.

Web Server Configuration Changed

If you modified the Nginx or Apache configuration after Certbot installed the certificate, the challenge location configuration may have been removed or moved. Without the correct challenge location, Let's Encrypt cannot verify your domain and renewal fails.

For Nginx, ensure this location block exists in your site configuration.

location /.well-known/acme-challenge/ {
    root /var/www/html;
}

For Apache, the equivalent configuration should include the .well-known directory in your document root or webroot path. If you run Apache as your primary web server, the Apache security configuration guide covers recommended practices for maintaining SSL certificate verification alongside hardened server settings.

Web Root Path Changed

Certbot needs to write challenge files to the path specified in your web server configuration. If you changed the document root after installing the certificate, update the challenge location accordingly. Mismatches between the configured path and the actual path prevent Certbot from writing verification files.

DNS No Longer Points to This Server

If you use the DNS-01 challenge or if the domain's A record changed, Let's Encrypt cannot reach your server to verify the challenge. Verify your DNS configuration before troubleshooting other renewal issues.

dig A yourdomain.com +short

This should return your server's IP address. If the result is empty or points to a different server, update your DNS records before attempting renewal.

Out of Disk Space

Certbot needs to write the challenge file to disk. If the partition is full, renewal fails silently or with a write error. Check available disk space on the relevant partition.

df -h /var/www

Ensure sufficient space is available before attempting renewal. Low disk space can also affect other parts of your server, so it is worth investigating why space ran low in the first place.

DNS-01 Challenge for Certificates Behind Load Balancers

The HTTP-01 challenge requires port 80 to be publicly accessible. If your web server sits behind a load balancer, CDN, or other infrastructure where port 80 is not directly reachable from the internet, the HTTP-01 challenge will fail. In these cases, the DNS-01 challenge provides an alternative verification method.

The DNS-01 challenge proves you control the domain by creating a TXT record in your DNS configuration. Certbot can automate this if your DNS provider has a supported API.

certbot certonly \
  --dns-cloudflare \
  --dns-cloudflare-credentials /root/.secrets/cloudflare.ini \
  -d yourdomain.com \
  -d "*.yourdomain.com"

The credentials file should be protected with appropriate permissions to prevent unauthorised access.

chmod 600 /root/.secrets/cloudflare.ini
# cloudflare.ini
dns_cloudflare_api_key = your_api_key

DNS-01 challenge certificates are typically issued for wildcard domains, meaning one certificate covers all subdomains. This reduces the number of certificates you need to manage, which simplifies ongoing maintenance.

When using DNS-01 challenges, ensure your DNS provider's API credentials are stored securely and backed up. Compromise of these credentials could allow an attacker to request certificates for your domain.

Forcing Renewal Before Expiry

Sometimes you need to renew a certificate before the 30-day window. Use the --force-renewal flag to trigger immediate renewal.

sudo certbot renew --force-renewal

This is useful when you have made changes to your web server configuration and want to verify the certificate is correctly linked. It also helps when you need to propagate a new certificate to a load balancer immediately after making infrastructure changes.

Be aware that Let's Encrypt has rate limits on certificate issuance. Forcing renewal frequently may cause you to hit these limits, temporarily blocking new certificate requests for up to a week.

Reloading Services After Renewal

Certbot can automatically reload Nginx or Apache after a successful renewal using the --post-hook directive. Without this, the web server continues serving the old certificate until it is restarted or reloaded. Visitors may see certificate warnings for up to 24 hours after renewal if you skip this step.

Add the post-hook to your Certbot configuration.

# In /etc/letsencrypt/cli.ini or certbot renewal config
post_hook = systemctl reload nginx

For a specific renewal configuration, edit the relevant file.

# /etc/letsencrypt/renewal/yourdomain.com.conf
post_hook = systemctl reload nginx
authenticator = nginx
webroot = /var/www/html

Replace nginx with apache2 if you use Apache. Test the post-hook configuration by running the dry-run and confirming the reload command executes without errors.

Managing Multiple Domain Certificates

If your certificate covers multiple domains (the primary domain plus additional SAN entries), Certbot renews all of them together when the primary domain approaches its renewal window.

Check which domains are included in a certificate.

sudo certbot certificates
# Example output
Certificate Name: yourdomain.com
Serial Number: 1234abcd
Domains: yourdomain.com www.yourdomain.com api.yourdomain.com
Expiry Date: 2026-08-20 12:00:00+00:00
Certificate Path: /etc/letsencrypt/live/yourdomain.com/fullchain.pem

If you add a new subdomain after the certificate is issued, you need to reissue the certificate with the new domain included. Certbot does not automatically add new domains to existing certificates.

sudo certbot certonly --nginx -d yourdomain.com -d www.yourdomain.com -d newdomain.yourdomain.com

When adding subdomains, remember to update your DNS records to point to your server before requesting the new certificate. Let's Encrypt verifies each domain listed before issuing the certificate.

Monitoring Certificate Expiry

Even with auto-renewal configured correctly, monitoring ensures you know about problems before they cause certificate expiration. Several approaches help you stay informed about the status of your certificates.

Check Expiry Date with OpenSSL

You can check the expiry date of any certificate directly using OpenSSL.

echo | openssl s_client -servername yourdomain.com -connect yourdomain.com:443 2>/dev/null | \
  openssl x509 -noout -enddate

Use the Certbot Certificates Command

List all certificates managed by Certbot and their expiry dates.

sudo certbot certificates

Run this regularly to confirm all certificates are present and have reasonable expiry dates. Scheduling a weekly reminder to check manually adds a human checkpoint to your automated setup.

Set Up Automated Expiry Monitoring

A simple script can check all certificates and send alerts when any is approaching expiry.

#!/bin/bash
# /root/scripts/check_cert_expiry.sh

for cert in /etc/letsencrypt/live/*/fullchain.pem; do
    expiry=$(openssl x509 -noout -enddate -in "$cert" | cut -d= -f2)
    expiry_epoch=$(date -d "$expiry" +%s)
    now_epoch=$(date +%s)
    days_left=$(( (expiry_epoch - now_epoch) / 86400 ))
    domain=$(basename $(dirname "$cert"))

    if [ "$days_left" -lt 14 ]; then
        echo "ALERT: $domain certificate expires in $days_left days"
    fi
done

Make the script executable and schedule it to run daily.

chmod +x /root/scripts/check_cert_expiry.sh
# Add to crontab - run daily at 9 AM
0 9 * * * /root/scripts/check_cert_expiry.sh | mail -s "SSL Expiry Check" admin@yourdomain.com

Replace the email address with your own and ensure your server can send mail. Some administrators prefer to use monitoring services or Slack integrations instead of email for alerts.

Why SSL Certificate Renewal Matters for Business Websites

Beyond the technical setup, understanding why certificate renewal matters helps maintain focus on the task. Expired SSL certificates cause browsers to display security warnings that deter visitors, damage trust, and can affect search rankings. For business websites, an expired certificate represents both a security risk and a potential loss of customer confidence.

Web servers running without proper SSL maintenance can also expose the underlying application to additional risks. If your server runs a full LAMP stack for business applications, the LAMP stack setup guide covers initial configuration and security considerations that work alongside proper certificate management.

Keeping Your Certificates Valid

Auto-renewal for Let's Encrypt certificates on Ubuntu is reliable when configured correctly. The key steps are installing Certbot properly, testing the renewal process with dry-run, configuring post-hooks to reload your web server, and setting up monitoring to catch problems early.

Most renewal failures stem from a small number of common causes: blocked port 80, changed web server configuration, missing challenge directories, or DNS issues. Addressing these systematically keeps your certificates valid without ongoing manual intervention.

If you have followed the initial setup guide and this renewal configuration but still encounter issues, preparing details about your server setup, current error messages, and recent changes helps diagnose the problem efficiently when you get in touch.

Frequently Asked Questions

How often does Certbot check for certificate renewal?
By default, Certbot's systemd timer runs twice per day, every 12 hours. Each run checks whether any certificate is within 30 days of expiry. If renewal is needed, Certbot attempts to renew and reload the relevant services automatically.
What happens if my certificate expires before renewal runs?
If auto-renewal fails and the certificate expires, visitors to your website see security warnings. The website remains accessible, but browsers flag it as insecure. To recover, run sudo certbot renew after fixing any configuration issues, then reload your web server.
Can I renew certificates for multiple domains in one command?
Yes. Certbot renews all domains covered by a single certificate together. If you have separate certificates for different domains, each certificate is renewed independently based on its own expiry date. Use sudo certbot certificates to see all managed certificates and their included domains.
Do I need to restart Nginx after renewal?
You need to reload Nginx for the new certificate to take effect. Without reloading, the old certificate remains in use. Configuring a post-hook as described earlier automates this process. Without automation, run sudo systemctl reload nginx after manual renewal.
Is the dry-run test safe to run in production?
Yes. The --dry-run flag performs all the steps of a real renewal except the actual certificate issuance. It does not modify any certificates or trigger Let's Encrypt rate limits. Run it whenever you want to verify your renewal configuration without affecting your current certificates.
What should I do if Certbot fails to renew but the dry-run succeeds?
Check that the conditions during the dry-run match your production environment. Differences often include DNS changes, firewall rules that temporarily block port 80, or web server configuration changes that removed the ACME challenge location. Review your logs with sudo certbot renew --dry-run and compare against recent server changes.
How do I handle certificate renewal when using a reverse proxy?
When your application runs behind Nginx or Apache acting as a reverse proxy, the proxy must forward ACME challenge requests to the backend or handle them directly. The reverse proxy SSL setup guide covers this scenario in detail, including how to configure Certbot to work correctly with proxy forwarding rules.