Let’s Encrypt on Nginx – The Quick‑and‑Dirty Guide
If your site is still serving traffic over plain HTTP, this article will show you how to slap a free SSL/TLS certificate onto Nginx in under 20 minutes. No fancy wizardry, just the bare essentials and a few sanity checks that make life easier down the line.
Why bother with Let’s Encrypt?
Modern browsers are picky: any HTTPS site without a valid cert is flagged as “not secure.” Even if you’re only running a staging environment or a local blog, an invalid cert can break API calls, cause mixed‑content warnings, and drive away users (or at least make them click the “I’ll come back later” button). Let’s Encrypt gives you free, automatically‑renewed certificates that work everywhere.
What you need
- A server running Ubuntu 22.04 or Debian 12 with root access
- Nginx already listening on port 80 (and port 443 once you’re done)
- A domain name pointing at the server’s public IP
- Basic familiarity with the command line
Got all that? Great, let’s dive in.
Install Certbot and its Nginx plugin
sudo apt update sudo apt install -y certbot python3-certbot-nginx
Why this matters:
certbot is the official Let's Encrypt client. The python3-certbot-nginx package brings an automated configuration helper that knows how to patch your Nginx files for you, saving a few keystrokes and preventing typos.
Ask Let’s Encrypt for a certificate
sudo certbot --nginx -d example.com -d www.example.com
Replace example.com with your own domain. The --nginx flag tells Certbot to use the built‑in Nginx authenticator, which will temporarily spin up an HTTP challenge listener on port 80.
What you’re really doing:
Certbot contacts the Let's Encrypt server, proves that you control the domain (via a temporary file served over HTTP), and receives a signed cert pair. It then hands the cert files to Nginx and rewrites your config so HTTPS is enabled automatically.
> I’ve seen this happen after a bad driver update on a Windows machine that made the WSL networking stack glitch. The temporary HTTP challenge simply failed, causing the entire renewal to stall—so double‑check that port 80 is truly open before you run Certbot.
Verify Nginx configuration
sudo nginx -t
If everything looks good, reload:
sudo systemctl reload nginx
Why check?
A mis‑spelled directive in the new ssl_* lines will break the server. The quick test catches that before your users see a 500 error.
Test the HTTPS connection
Open https://example.com in a browser, or use:
curl -I https://example.com
You should see a 200 OK response and an expires header indicating the certificate is fresh. The ssl_error line in the Nginx log will be gone.
Set up automatic renewal
Let’s Encrypt certificates expire every 90 days, but Certbot installs a daily cron job that runs twice per day. Test it manually once:
sudo certbot renew --dry-run
If you see “All renewals succeeded,” you’re good to go.
Why the dry‑run?
It forces Certbot to run through the renewal process without touching the live certs, so you can confirm that Nginx will reload automatically after a successful renewal. A broken renewal script is a silent nightmare until the next 90 days.
Optional: Enforce HTTP => HTTPS redirect
If you want all traffic forced over TLS:
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
Add this block (or uncomment the existing one in your Certbot‑generated file) and reload Nginx again. Now anyone hitting http://example.com is sent straight to HTTPS.
TL;DR
1. Install Certbot (sudo apt install certbot python3-certbot-nginx)
2. Get a cert (sudo certbot --nginx -d example.com -d www.example.com)
3. Test config (sudo nginx -t && sudo systemctl reload nginx)
4. Verify HTTPS (browser or curl -I https://example.com)
5. Check renewal (sudo certbot renew --dry-run)
That’s it—your Nginx is now speaking encrypted, and you’ve got a cron job keeping the certificate fresh.
Enjoy that clean “Secure” badge in your browser bar, and rest easy knowing your site won’t be flagged as insecure on the next visit.