
Table of Contents
By Khimananda Oli | Last reviewed: August 2026
Shipping a site over plain HTTP in 2026 means browsers slap a "Not Secure" label on it, search rankings suffer, and any login or form is exposed on the wire. Paying a certificate authority yearly for a basic domain-validated cert is no longer necessary. To set up free SSL with Let's Encrypt and Certbot you install one tool, run one command, and get a trusted TLS certificate that renews itself every 60 days. This guide walks through install, issuance, forced HTTPS, wildcard certificates, and — the part most tutorials skip — actually verifying that auto-renewal works before you forget about it. If you also need the server itself provisioned, pair this with our DevOps and cloud services.
sudo certbot --nginx -d example.com -d www.example.com. Certbot proves domain control with the HTTP-01 challenge, writes the TLS certificate, edits your Nginx config to serve HTTPS and redirect HTTP, and installs a systemd timer that auto-renews the certificate.What is Let's Encrypt and how does Certbot fit in?
Let's Encrypt is a free, automated, non-profit certificate authority that issues domain-validated TLS certificates trusted by every major browser. It never charges, but its certificates are deliberately short-lived — valid for 90 days — which forces automation instead of manual yearly renewals. Certbot is the official ACME client that talks to Let's Encrypt on your behalf: it requests the certificate, proves you own the domain, installs the files, and wires up renewal.
Before you start, confirm three prerequisites:
- A registered domain whose DNS
A/AAAArecord points at your server's public IP. - Ports 80 and 443 open in your firewall and security group — the HTTP-01 challenge needs inbound port 80.
- Nginx installed and serving your site over HTTP, with a valid
server_namematching the domain.
How do you install Certbot on Ubuntu in 2026?
The Certbot project recommends the snap package because it always ships the latest release with its dependencies bundled. On a current Ubuntu server:
sudo snap install core && sudo snap refresh core
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot If you prefer the distribution package (simpler, but a slightly older version), the apt route works fine for HTTP-01 issuance:
sudo apt update
sudo apt install certbot python3-certbot-nginx The python3-certbot-nginx package installs the Nginx plugin, which lets Certbot read and edit your server blocks automatically. Confirm the install with certbot --version.
How do you issue a free SSL certificate with the HTTP-01 challenge?
The single command below asks Certbot to obtain a certificate and configure Nginx in one pass. The --nginx plugin finds the matching server block, temporarily serves the ACME token, and rewrites the config once the certificate is signed:
sudo certbot --nginx -d example.com -d www.example.com Certbot asks for an email (used for expiry warnings and account recovery) and whether you agree to the ACME terms. It then runs the HTTP-01 challenge: Let's Encrypt hands Certbot a random token, Certbot serves it at http://example.com/.well-known/acme-challenge/<token>, and Let's Encrypt fetches that URL over port 80 to confirm you control the domain. On success it writes the certificate to /etc/letsencrypt/live/example.com/.
If you want the certificate files without letting Certbot touch your config, use the certonly mode instead and edit Nginx yourself:
sudo certbot certonly --nginx -d example.com -d www.example.com How do you force HTTPS and configure Nginx correctly?
When you run the --nginx plugin, Certbot offers to add the redirect for you. If you manage the config by hand, a clean two-block setup sends all HTTP traffic to HTTPS and points Nginx at the issued certificate:
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
http2 on;
server_name example.com www.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
root /var/www/example.com/public;
index index.php index.html;
} Always test the syntax before reloading so a typo never takes the site down:
sudo nginx -t && sudo systemctl reload nginx How do you get a wildcard certificate with the DNS-01 challenge?
The HTTP-01 challenge validates one hostname at a time and cannot issue a wildcard certificate such as *.example.com. Wildcards require the DNS-01 challenge, where you prove domain control by publishing a special TXT record instead of serving a file. Here is how the two challenges compare:
- HTTP-01 — serves a token over port 80; simplest; one certificate per listed hostname; cannot do wildcards.
- DNS-01 — publishes a
_acme-challengeTXT record; works behind a firewall with no open port 80; the only method that issues wildcards.
With a DNS provider plugin (Cloudflare, Route 53, DigitalOcean and others), the whole flow is automated. Using Cloudflare as an example, store an API token, then request the wildcard:
sudo certbot certonly \
--dns-cloudflare \
--dns-cloudflare-credentials /root/.secrets/cloudflare.ini \
-d example.com -d '*.example.com' Without a plugin you can still use the manual mode, which pauses and prints the TXT record for you to add by hand before continuing:
sudo certbot certonly --manual --preferred-challenges dns \
-d example.com -d '*.example.com' How do you verify Let's Encrypt auto-renewal actually works?
This is where most setups quietly break: the certificate was issued, everyone moved on, and 90 days later the site goes down. Modern Certbot installs a systemd timer (or a cron job on older systems) that runs twice a day and renews any certificate within 30 days of expiry. Confirm the timer is active:
sudo systemctl list-timers | grep certbot
systemctl status snap.certbot.renew.timer Then do a dry run against the Let's Encrypt staging servers — this rehearses the full renewal without touching your rate limits or replacing the live certificate:
sudo certbot renew --dry-run A successful dry run ending in "Congratulations, all simulated renewals succeeded" means the timer will do the right thing unattended. To reload Nginx automatically after each real renewal, add a deploy hook so the new certificate is picked up without manual intervention:
sudo certbot renew --deploy-hook "systemctl reload nginx" You can list every certificate Certbot manages, with its expiry date, at any time:
sudo certbot certificates What common Certbot errors should you watch for?
A few issues account for most failed issuances. Check these first before opening a support thread:
- Port 80 blocked — the HTTP-01 challenge fails with a connection timeout. Open port 80 in your firewall and cloud security group, even if you only serve HTTPS afterwards.
- DNS not propagated — Let's Encrypt validates against the public DNS record; wait for the
Arecord to propagate before issuing. - Rate limits — Let's Encrypt caps duplicate certificates per week. Use
--dry-runand the staging environment while testing so you never burn a live limit. - Wrong
server_name— the Nginx plugin can only find and edit a block whoseserver_namematches the-ddomains exactly.
Conclusion
Free SSL with Let's Encrypt and Certbot is genuinely a two-minute job once the prerequisites are in place: install Certbot, run certbot --nginx, force the HTTPS redirect, and confirm the renewal timer with a dry run so the certificate keeps rotating on its own. Add the DNS-01 challenge only when you need a wildcard. Lock it in today, and your site stays trusted, encrypted, and ranked without another thought. If you would rather have your servers hardened and TLS automated end to end, get in touch or browse the DevOps case studies for how this looks in production.