I had an SSL certificate expire on a site once. Not catastrophic, but users were seeing scary browser warnings and I only found out from an email complaint. Let's Encrypt certificates expire every 90 days by design, and manually renewing them is absolutely the wrong approach.
Certbot handles auto-renewal and — when configured correctly — you never have to think about certificate expiration again. It runs a renewal check twice a day, renews certificates 30 days before expiration, and reloads the web server automatically. The tricky part is just verifying it's actually set up to run, and understanding why a renewal might fail.
This guide covers Certbot installation, obtaining certificates, confirming auto-renewal is working, and the port-80 requirement that causes most renewal failures.
I manage SSL certificates for sites running on Tencent Cloud Lighthouse with Certbot. The setup takes 10 minutes and eliminates certificate expiry incidents permanently. A practical advantage specific to Lighthouse: the console-level firewall panel makes it easy to quickly verify that port 80 is open before running Certbot (it requires port 80 to be accessible for domain validation), and the OrcaTerm terminal lets you run
certbot renew --dry-runto test the renewal process from any browser without a local SSH client.
- Key Takeaways
Let's Encrypt issues: cert valid 90 days
Certbot renews at: 60 days (30 days before expiry)
Timeline:
Day 0: Certificate issued
Day 60: Certbot auto-renewal runs → new cert valid until Day 150
Day 90: Old cert would have expired (but we already renewed)
Certbot installs a systemd timer (or cron job) that runs twice daily. Each run checks whether any certificates expire within 30 days and renews them if needed. Since renewal attempts fail silently when the cert isn't due yet, running it frequently doesn't cause issues.
| Requirement | Notes |
|---|---|
| Cloud server | Tencent Cloud Lighthouse Ubuntu 22.04 |
| A domain name | With DNS A record pointing to your server |
| Port 80 open | Certbot's HTTP challenge requires port 80 |
| Nginx or Apache | We'll show both |
sudo apt update
sudo apt install -y certbot
# Nginx plugin
sudo apt install -y python3-certbot-nginx
# Apache plugin
sudo apt install -y python3-certbot-apache
# Verify
certbot --version
# certbot 2.x.x
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
Certbot:
sudo certbot --apache -d yourdomain.com -d www.yourdomain.com
Certbot starts its own temporary web server to handle the challenge:
# Stop Nginx/Apache first (Certbot needs port 80)
sudo systemctl stop nginx
sudo certbot certonly --standalone -d yourdomain.com -d www.yourdomain.com
# Start Nginx again
sudo systemctl start nginx
Certbot places a challenge file in your web root:
sudo certbot certonly --webroot \
-w /var/www/yourdomain \
-d yourdomain.com \
-d www.yourdomain.com
Your Nginx must serve /.well-known/acme-challenge/ from the webroot:
location ~ /.well-known/acme-challenge/ {
root /var/www/yourdomain;
allow all;
}
sudo certbot certonly --nginx -d yourdomain.com
Manual Nginx HTTPS configuration:
server {
listen 443 ssl http2;
server_name yourdomain.com;
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
# Your other config...
}
sudo systemctl status certbot.timer
# Should show: Active: active (waiting)
sudo certbot renew --dry-run
This simulates the entire renewal process:
If --dry-run succeeds with no errors, real auto-renewal will work.
sudo certbot certificates
Output example:
Found the following certs:
Certificate Name: yourdomain.com
Domains: yourdomain.com www.yourdomain.com
Expiry Date: 2026-07-18 10:00:00+00:00 (VALID: 89 days)
Certificate Path: /etc/letsencrypt/live/yourdomain.com/fullchain.pem
Private Key Path: /etc/letsencrypt/live/yourdomain.com/privkey.pem
If auto-renewal failed or you want to renew immediately:
# Renew all certificates due for renewal
sudo certbot renew
# Force renew a specific certificate (even if not expired)
sudo certbot renew --cert-name yourdomain.com --force-renewal
# Reload Nginx after renewal
sudo systemctl reload nginx
Certbot runs scripts in /etc/letsencrypt/renewal-hooks/ automatically:
# Reload Nginx after every renewal
sudo nano /etc/letsencrypt/renewal-hooks/post/reload-nginx.sh
#!/bin/bash
systemctl reload nginx
sudo chmod +x /etc/letsencrypt/renewal-hooks/post/reload-nginx.sh
Now Nginx reloads automatically after every successful certificate renewal.
A wildcard certificate (*.yourdomain.com) covers all subdomains:
sudo certbot certonly \
--manual \
--preferred-challenges dns \
-d "*.yourdomain.com" \
-d yourdomain.com
Certbot will ask you to add a TXT record to your DNS:
_acme-challenge.yourdomain.com TXT "some-random-value"
Add the record in your DNS provider's panel, wait for propagation (30-60 seconds), then press Enter.
Automated wildcard renewal requires a DNS plugin. If your DNS provider is supported:
# Example: Cloudflare DNS plugin
sudo apt install python3-certbot-dns-cloudflare
# Create credentials file
sudo nano /etc/letsencrypt/cloudflare.ini
# dns_cloudflare_api_token = YOUR_TOKEN
sudo chmod 600 /etc/letsencrypt/cloudflare.ini
# Obtain wildcard cert with auto-renewal
sudo certbot certonly \
--dns-cloudflare \
--dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \
-d "*.yourdomain.com" \
-d yourdomain.com
Each domain gets its own certificate. Certbot manages them all:
sudo certbot --nginx -d site1.com -d www.site1.com
sudo certbot --nginx -d site2.com -d www.site2.com
sudo certbot --nginx -d app.site1.com
List all managed certificates:
sudo certbot certificates
# Shows each certificate separately with its expiry
All certificates auto-renew independently via the single systemd timer.
sudo openssl x509 -noout -dates -in /etc/letsencrypt/live/yourdomain.com/cert.pem
# notBefore=...
# notAfter=...
echo | openssl s_client -servername yourdomain.com -connect yourdomain.com:443 2>/dev/null | \
openssl x509 -noout -dates
Uptime Kuma has a "Certificate Expiry" monitor type — set it to alert you if the certificate expires within 14 days. Belt and suspenders alongside Certbot's auto-renewal.
Certbot's HTTP challenge (the default) requires port 80 to be accessible. If you:
...then renewal will fail silently until the certificate expires.
Test:
sudo certbot renew --dry-run
If you see Connection refused or Timeout during connect, port 80 is blocked.
Fixes:
sudo ufw allow httpcertbot --preferred-challenges dnscertbot --preferred-challenges tls-sniCommon scenario: you close port 80 after obtaining the cert (to "improve security"). Certbot can't renew. Solution: keep port 80 open with an HTTP→HTTPS redirect — it's needed for renewals.
# List all certificates
sudo certbot certificates
# Test renewal
sudo certbot renew --dry-run
# Force renew a certificate
sudo certbot renew --cert-name yourdomain.com --force-renewal
# Delete a certificate
sudo certbot delete --cert-name yourdomain.com
# View renewal timer
sudo systemctl status certbot.timer
sudo systemctl list-timers certbot.timer
# View renewal log
sudo cat /var/log/letsencrypt/letsencrypt.log | tail -50
# Check certificate expiry from command line
sudo openssl x509 -noout -dates -in /etc/letsencrypt/live/DOMAIN/cert.pem
# Reload Nginx after manual renewal
sudo certbot renew && sudo systemctl reload nginx
| Issue | Likely Cause | Fix |
|---|---|---|
| Connection refused | Service not running or wrong port | Check systemctl status SERVICE and verify firewall rules |
| Permission denied | Wrong file ownership or permissions | Check file ownership with ls -la and use chown/chmod to fix |
| 502 Bad Gateway | Backend service not running | Restart the backend service; check logs with journalctl -u SERVICE |
| SSL certificate error | Certificate expired or domain mismatch | Run sudo certbot renew and verify domain DNS points to server IP |
| Service not starting | Config error or missing dependency | Check logs with journalctl -u SERVICE -n 50 for specific error |
| Out of disk space | Logs or data accumulation | Run df -h to identify usage; clean logs or attach CBS storage |
| High memory usage | Too many processes or memory leak | Check with htop; consider upgrading instance plan if consistently high |
| Firewall blocking traffic | Port not open in UFW or Lighthouse console | Open port in Lighthouse console firewall AND sudo ufw allow PORT |
How long does it take to set up Certbot SSL on a cloud server?
With the appropriate Lighthouse application image (if available), setup takes 10–30 minutes. Manual installation from a plain Ubuntu image typically takes 30–90 minutes following this guide.
What server specifications do I need for Certbot SSL?
Check the prerequisites section of this guide for specific requirements. As a general rule: start with the minimum recommended spec, monitor actual usage, and upgrade from the Lighthouse console if needed.
How do I keep Certbot SSL updated?
Follow the update procedure specific to how it was installed (package manager, Docker pull, or binary replacement). Take a Lighthouse snapshot before any major update as a safety net.
How do I back up Certbot SSL data?
Use Lighthouse snapshots for full-server recovery plus the application's own export/backup mechanism for granular recovery. Both together provide comprehensive backup coverage.
htop and expand the server spec or attach CBS storage as needed.Get HTTPS on your server today:
👉 Tencent Cloud Lighthouse — Ubuntu VPS with full root access for Certbot
👉 View current pricing and promotions
👉 Explore all active deals and offers