Set Up Free SSL with Let's Encrypt and Certbot (2026 Guide)

Khimananda Oli 8 min read Database
Set Up Free SSL with Let's Encrypt and Certbot (2026 Guide)

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.

Certbotyour serverNginx webrootserves token/.well-known/Let's EncryptACME CAvalidates + issues1. request + token2. fetch token3. issue certificateThe HTTP-01 challenge proves you control the domain over port 80 before a certificate is signed
The ACME HTTP-01 challenge: Certbot serves a token from your Nginx webroot, Let's Encrypt fetches it to confirm domain control, then signs the free SSL 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/AAAA record 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_name matching 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
Browserhttp://Nginx :80return 301 to httpsNginx :443 sslfullchain.pem + privkey.pemhttp2 onSiteencrypted301Every plain HTTP hit is redirected once, then served over TLS with the Let's Encrypt certificate
HTTP to HTTPS on Nginx: the port 80 block issues a 301 redirect, and the port 443 block serves the site with the Let's Encrypt certificate over HTTP/2.

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-challenge TXT 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
Issuedvalid 90 dayssystemd timerchecks twice dailyRenewwithin 30 daysof expiryReloadNginxcycle repeats — the certificate never expires while the timer runs
The Certbot auto-renewal lifecycle: a certificate valid for 90 days is renewed by the systemd timer inside the 30-day window, then Nginx reloads — no manual step ever.

What common Certbot errors should you watch for?

A few issues account for most failed issuances. Check these first before opening a support thread:

  1. 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.
  2. DNS not propagated — Let's Encrypt validates against the public DNS record; wait for the A record to propagate before issuing.
  3. Rate limits — Let's Encrypt caps duplicate certificates per week. Use --dry-run and the staging environment while testing so you never burn a live limit.
  4. Wrong server_name — the Nginx plugin can only find and edit a block whose server_name matches the -d domains 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.

Frequently Asked Questions

Yes. Let's Encrypt is a non-profit certificate authority that issues domain-validated TLS certificates at no cost, with no trial period or hidden fees. It is funded by sponsors and donations, and its certificates are trusted by every major browser and operating system.

Each certificate is valid for 90 days. The short lifetime is intentional — it encourages automation and limits the damage if a key is ever compromised. Certbot's renewal timer renews certificates automatically once they are within 30 days of expiry, so the short window is invisible in practice.

The Certbot project recommends snap because it always delivers the newest release with bundled dependencies. The apt package is simpler and fine for basic HTTP-01 issuance, but it can lag behind, which matters if you need the latest DNS plugins or ACME features.

HTTP-01 is the validation method where Certbot serves a random token at a /.well-known/acme-challenge/ URL over port 80. Let's Encrypt fetches that URL to confirm you control the domain before signing the certificate. It is the default and simplest challenge for a single host.

Install Certbot and the Nginx plugin, then run sudo certbot --nginx -d example.com -d www.example.com. Certbot completes the HTTP-01 challenge, writes the certificate, edits your server block to serve HTTPS, and offers to redirect all HTTP traffic to HTTPS automatically.

Yes, when you use the --nginx plugin. Certbot locates the server block matching your domains, installs the certificate paths, and can add the HTTP-to-HTTPS redirect for you. Use certonly instead if you want only the certificate files and prefer to edit Nginx by hand.

Add a port 80 server block that runs return 301 https://$host$request_uri, and serve the real site from a port 443 ssl block. Certbot can add this redirect during issuance. Always run nginx -t before reloading so a config typo never takes the site offline.

Yes, but only through the DNS-01 challenge, not HTTP-01. A wildcard such as *.example.com covers every subdomain. You prove control by publishing a _acme-challenge TXT record, which a DNS provider plugin like Cloudflare or Route 53 can automate.

HTTP-01 serves a token over port 80 and validates one hostname at a time. DNS-01 publishes a TXT record and works even when port 80 is closed or the server sits behind a firewall. DNS-01 is also the only challenge that can issue wildcard certificates.

Run sudo certbot renew --dry-run to rehearse the full renewal against the staging servers without replacing the live certificate. Then confirm the systemd timer with systemctl list-timers | grep certbot. A successful dry run means unattended renewal will work.

Not on modern systems. Certbot installs a systemd timer that runs twice a day and renews certificates within 30 days of expiry. Only older setups without systemd rely on a cron entry. Either way, no manual renewal command is needed.

Use a deploy hook: certbot renew --deploy-hook "systemctl reload nginx". The hook runs only when a certificate is actually renewed, so Nginx picks up the new certificate automatically without a wasteful reload on every timer check.

The most common cause is port 80 being blocked by a firewall or cloud security group, since Let's Encrypt must reach the token over HTTP. Other causes include DNS not yet propagated to the server IP or a server_name that does not match the requested domain.

Let's Encrypt caps how many certificates you can request for the same domains in a rolling week to protect its service. While testing, use --dry-run and the staging environment so failed experiments never count against the live production limits.

Yes. Certbot has an Apache plugin, a standalone mode that runs its own temporary web server, and a webroot mode for any server. The certificate files are identical; only the installation and reload step differ between web servers.