I remember the first time a browser showed me that "Not Secure" warning on a site I'd just built. I knew HTTPS existed, but I'd assumed it was one of those things that cost money and required paperwork. So I'd just skipped it.
Then I found out about Let's Encrypt — free, automated, and trusted by every browser on earth. I felt a bit silly for having avoided HTTPS for so long. Getting a certificate now takes about five minutes and it renews itself automatically every 90 days.
This guide walks through getting Let's Encrypt set up on an Nginx server, configuring auto-renewal, and handling the edge cases that come up in real deployments.
I run this on Tencent Cloud Lighthouse with Ubuntu 22.04 and Nginx. A few things that make SSL configuration practical here: the console-level firewall makes it easy to confirm port 80 is open (a requirement for Let's Encrypt validation) without editing UFW rules, and OrcaTerm lets you run the Certbot commands directly from the browser without needing your local SSH client. If you want to test your Certbot setup on a throwaway server first, Lighthouse instances provision in under 2 minutes and can be released when done.
Key Takeaways
- Let's Encrypt provides free, browser-trusted SSL certificates
- Certbot auto-renews certificates — set it up once and forget about it
- Port 80 must be open for domain validation and HTTP redirects
- Test renewal without making changes:
sudo certbot renew --dry-run- Wildcard certificates (
*.domain.com) require DNS validation
Let's Encrypt is a free, automated Certificate Authority (CA). It issues Domain Validation (DV) certificates — the standard HTTPS padlock you see on most websites.
The process:
You do this once. After that, HTTPS management is hands-off.
| Requirement | Notes |
|---|---|
| A domain name | With an A record pointing to your server IP |
| Nginx installed | See the Nginx setup guide if needed |
| Port 80 and 443 open | In both UFW and Lighthouse console firewall |
| DNS propagated | The domain must resolve to your server before Certbot runs |
Check DNS is ready:
dig +short yourdomain.com
# Should return your server's IP
Or use an online tool like whatsmydns.net.
sudo apt update
sudo apt install -y certbot python3-certbot-nginx
Verify the installation:
certbot --version
# certbot 2.x.x
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
Certbot will:
The Nginx config after Certbot runs will look something like this (Certbot adds the SSL sections):
server {
server_name yourdomain.com www.yourdomain.com;
root /var/www/yourdomain;
index index.html;
location / {
try_files $uri $uri/ =404;
}
listen 443 ssl;
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;
}
server {
listen 80;
server_name yourdomain.com www.yourdomain.com;
return 301 https://$host$request_uri;
}
# Test your domain's SSL configuration
curl -I https://yourdomain.com
# Should return HTTP/2 200 (or 301 redirect)
# Check certificate details
sudo certbot certificates
Also verify in a browser — you should see a padlock with no warnings.
Use SSL Labs to test your configuration quality. A properly configured Let's Encrypt + Nginx setup typically scores A or A+.
Certbot installs a systemd timer (or cron job on older systems) that runs twice daily to check if any certificates need renewal.
Test the renewal process without actually renewing:
sudo certbot renew --dry-run
If this succeeds, automatic renewal is working. Your certificates will renew automatically 30 days before expiration.
Check the renewal timer:
sudo systemctl status certbot.timer
View certificate expiry dates:
sudo certbot certificates
A wildcard certificate (*.yourdomain.com) covers all subdomains. This is useful if you have many subdomains or add them frequently.
Wildcard certificates require DNS validation instead of HTTP validation, so you'll need to add a TXT record to your DNS:
sudo certbot certonly \
--manual \
--preferred-challenges dns \
-d "*.yourdomain.com" \
-d yourdomain.com
Certbot will prompt you to add a _acme-challenge.yourdomain.com TXT record. Add it in your DNS provider's panel, wait for propagation, then press Enter.
For automated wildcard renewal, use a DNS plugin if your DNS provider is supported:
# Example: Cloudflare DNS plugin
sudo apt install python3-certbot-dns-cloudflare
# Then configure with your API credentials
You can have certificates for multiple independent domains on the same server:
# Certificate for site one
sudo certbot --nginx -d site1.com -d www.site1.com
# Certificate for site two
sudo certbot --nginx -d site2.com -d www.site2.com
# Certificate for an app subdomain
sudo certbot --nginx -d app.site1.com
Each domain gets its own certificate file in /etc/letsencrypt/live/. Certbot manages all of them and renews each independently.
The most common Certbot error is running it before DNS has finished propagating:
Error: Failed to authenticate, Could not connect to yourdomain.com
Let's Encrypt needs to reach your server at the domain you're requesting a certificate for. If the domain still points to the old server (or nowhere), certificate issuance fails.
Before running Certbot:
# Verify your domain resolves to your server
dig +short yourdomain.com
nslookup yourdomain.com
# Should show your server's IP
DNS changes can take anywhere from a few minutes to 48 hours to fully propagate. In practice, most DNS providers update within 5–15 minutes, but patience helps here.
If you're in a hurry and your DNS provider supports it, set a low TTL (60 seconds) before making the change.
| Issue | Likely cause | Fix |
|---|---|---|
certbot renew --dry-run fails |
Port 80 blocked | Check UFW allows HTTP; check Lighthouse console firewall |
| "DNS problem: NXDOMAIN looking up A" | Domain doesn't resolve | Verify DNS A record is set and propagated |
| Certificate showing as expired | Auto-renewal failed | Check systemctl status certbot.timer; run renewal manually |
| Wrong domain on certificate | Certbot ran before DNS change | Revoke and re-issue: certbot delete --cert-name domain.com |
| Nginx 500 after renewal | Nginx not reloaded | sudo systemctl reload nginx after manual renewal |
Manual renewal (if auto-renewal isn't working):
sudo certbot renew
sudo systemctl reload nginx
Check renewal logs:
sudo cat /var/log/letsencrypt/letsencrypt.log
Is Let's Encrypt SSL really free?
Yes — Let's Encrypt certificates are completely free, trusted by all major browsers, and auto-renewing. The only requirement is that you control the domain and the server is publicly accessible on port 80 for domain validation.
How long does a Let's Encrypt certificate last?
90 days. Certbot sets up automatic renewal and renews certificates when they're 30 days from expiry. Once configured, you never need to manually renew.
What happens if my SSL certificate expires?
Browsers show a security warning and block access. To prevent this, verify Certbot's renewal timer is running: sudo systemctl status certbot.timer.
Can I get SSL for multiple domains with one certificate?
Yes — add multiple -d flags to the Certbot command: certbot --nginx -d domain.com -d www.domain.com. You can also get wildcard certificates with DNS validation.
Set up your server with a free SSL certificate:
👉 Tencent Cloud Lighthouse — Cloud server with full root access
👉 View current pricing and promotions
👉 Explore all active deals and offers