DEV Community

Cover image for Free SSL With Let's Encrypt: Certbot, Auto-Renewal, and the Test Everyone Skips
FlatlinerAtheist | CLI-NERDS
FlatlinerAtheist | CLI-NERDS

Posted on Originally published at clinerds.com

Free SSL With Let's Encrypt: Certbot, Auto-Renewal, and the Test Everyone Skips

There was a time when putting HTTPS on a small website meant paying for a certificate, generating a CSR, and renewing the whole thing every year before it expired at the worst possible moment. Let's Encrypt ended that era: free certificates, issued in minutes, renewed automatically by a robot that never forgets. If you are still running plain HTTP in 2026, the only thing between you and HTTPS is about fifteen minutes.

This is the setup I use on Ubuntu/Debian with nginx or Apache, plus the renewal test that almost everyone skips — and then gets surprised by ninety days later.

What you need first

  • A domain pointing at your server's public IP (an A record). Let's Encrypt verifies you control the domain by connecting to it, so DNS has to be live before you start. If you just changed the record, propagation can take a while — this is why that happens.
  • Ports 80 and 443 open in your firewall. The HTTP-01 challenge needs port 80 specifically, and a lot of failed issuances are just UFW or a cloud security group blocking it.
  • nginx or Apache already serving your site on port 80.

Check DNS from your laptop, not from the server, so you see what the internet sees:

dig +short A example.com
dig +short A www.example.com
Enter fullscreen mode Exit fullscreen mode

Install Certbot and get the certificate

On Ubuntu/Debian:

sudo apt update
sudo apt install -y certbot python3-certbot-nginx   # nginx
# or: sudo apt install -y certbot python3-certbot-apache  # Apache
Enter fullscreen mode Exit fullscreen mode

Then the actual magic, one command:

sudo certbot --nginx -d example.com -d www.example.com
# Apache: sudo certbot --apache -d example.com -d www.example.com
Enter fullscreen mode Exit fullscreen mode

Certbot reads your existing server config, proves domain control over port 80, downloads the certificate, and rewrites your virtual host to serve HTTPS with the new certificate paths. It also offers to redirect HTTP to HTTPS — say yes. That is the entire process.

I still remember doing this the manual way with CSRs and PEM bundles and feeling vaguely scammed by how uneventful the Certbot version is. Unremarkable is exactly what you want from security infrastructure.

What just happened on disk

Certificates live in /etc/letsencrypt/live/example.com/:

  • fullchain.pem — certificate plus intermediate chain (this is what servers send)
  • privkey.pem — your private key, permissions 0600, never share it, never commit it

Your nginx config now references those paths, and Certbot installed a systemd timer for renewal. Confirm the timer exists:

systemctl list-timers | grep certbot
Enter fullscreen mode Exit fullscreen mode

Certificates last 90 days, and the timer renews them automatically around the 60-day mark. No cron entries to invent, no calendar reminders.

The renewal test everyone skips

Auto-renewal is only a promise until you have seen it work. Run a dry run:

sudo certbot renew --dry-run
Enter fullscreen mode Exit fullscreen mode

If that ends with "Congratulations, all simulated renewals succeeded", you are genuinely done. If it fails, you just saved yourself a certificate-expiry incident in two months — fix it now while nothing is on fire.

The two failures I see most often:

  1. Port 80 got closed later. People harden the firewall after setup and forget the challenge needs HTTP. Keep port 80 open and let it redirect to HTTPS.
  2. Something else took over the web server config. A control panel or a hand-edited virtual host can confuse the renewal hook. --dry-run surfaces this immediately.

After a real renewal, Certbot reloads nginx/Apache for you. If you run something else that reads the certificate — a mail server, a proxy — use a deploy hook so it also reloads:

sudo certbot renew --deploy-hook "systemctl reload nginx"
Enter fullscreen mode Exit fullscreen mode

(You only need the hook once; Certbot remembers it for future renewals.)

Verify from the outside

Do not trust your own server to grade itself:

curl -I https://example.com
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -noout -dates
Enter fullscreen mode Exit fullscreen mode

The curl should return your site with no certificate errors, and the openssl output shows the exact validity window. For a second opinion, SSL Labs' free scan (ssllabs.com/ssltest) gives you a letter grade and points out protocol issues — a useful five-minute check after any TLS change.

One redirect detail worth doing while you are here: send all HTTP traffic to HTTPS and, if you care about a canonical domain, pick one of example.com vs www.example.com and redirect the other. Split versions of your site confuse both users and search engines.

When Let's Encrypt is not the right tool

Two common exceptions. If your server must stay unreachable from the internet, use the DNS-01 challenge instead — Certbot supports it through DNS provider plugins, and it also enables wildcard certificates (*.example.com), which HTTP-01 cannot issue. And if you are behind Cloudflare, decide deliberately whether you want their proxy handling TLS; in that setup you still want a certificate on your origin, and "Full (strict)" mode, not "Flexible".

For everyone else: install Certbot, run one command, test the renewal once, and go back to building your site. HTTPS stopped being a project years ago — it is a checklist item now.

Top comments (0)