How to Get a Free SSL Certificate with Let's Encrypt and Certbot

Browsers now flag any site without HTTPS as "Not secure", and plenty of things — password fields, service workers, some APIs — simply refuse to work without it. Let's Encrypt gives certificates away for free, and Certbot gets one, installs it into Nginx and renews it every three months without you touching anything.
Quick reference
| Task | Command |
|---|---|
| Install Certbot | sudo apt install certbot python3-certbot-nginx -y |
| Get and install a certificate | sudo certbot --nginx -d example.com -d www.example.com |
| Check renewal works | sudo certbot renew --dry-run |
| List certificates | sudo certbot certificates |
| Certificate files | /etc/letsencrypt/live/example.com/ |
Before you start
Let's Encrypt has to be able to reach your server from the internet to prove you own the domain. You need:
- A domain name with an A record pointing at your public IP.
- Ports 80 and 443 forwarded from your router to the server.
- An Nginx server block for that domain (tutorial 26) with the right server_name.
- The firewall open: sudo ufw allow 'Nginx Full'.
Check from outside (your phone on mobile data) that http://example.com reaches your server before going further.
1. Install Certbot
sudo apt install certbot python3-certbot-nginx -y
The second package is the Nginx plugin that edits your config for you.
2. Get the certificate
sudo certbot --nginx -d example.com -d www.example.com
It asks for an email (for expiry warnings), agreement to the terms, and whether to share your email (no). Then it:
- proves you own the domain by placing a file Let's Encrypt fetches over port 80,
- gets the certificate,
- edits your server block to use it, and
- adds a redirect so http:// visitors are sent to https://.
Browse to https://example.com. Padlock.
3. Check it will renew
Certificates last 90 days. Certbot installed a timer that renews them automatically when they have 30 days left. Prove it works:
sudo certbot renew --dry-run
If that finishes without errors, you never need to think about it again. systemctl list-timers | grep certbot shows the schedule.
Several sites
Run the same command once per site, or list all the names at once with multiple -d flags. sudo certbot certificates lists what you've got.
What Certbot added to your config
Open /etc/nginx/sites-available/example.com and you'll see a second server block listening on 443 with ssl_certificate lines pointing into /etc/letsencrypt/live/. If you ever rebuild the config by hand, keep those lines.
Troubleshooting
"Challenge failed" / "Connection refused". Let's Encrypt couldn't reach port 80. Check the router port forward, the firewall, and that the DNS A record points at your current public IP (curl ifconfig.me shows it).
"DNS problem: NXDOMAIN". The domain doesn't resolve yet. New DNS records can take up to an hour.
Your ISP blocks port 80. Use the DNS challenge instead: sudo certbot certonly --manual --preferred-challenges dns -d example.com and add the TXT record it asks for. (For automatic renewal with DNS, look at the certbot-dns-* plugins for your registrar.)
"Too many certificates already issued". You've hit the rate limit by re-running too often. Wait a week, and use --dry-run or the staging server (--test-cert) when experimenting.
Mixed-content warnings after switching. Your pages load images or scripts with http:// links. Change them to https:// or protocol-relative //.
Wrapping up
Domain pointing at you, ports 80 and 443 open, one certbot --nginx command. Run the dry-run renewal once to prove it, and your site stays on HTTPS indefinitely for nothing.
