Introduction
A few years ago, adding HTTPS to your website cost money — sometimes hundreds of dollars per year for an SSL certificate. Many small websites and developers skipped it entirely, leaving their users exposed.
Then in 2016, Let's Encrypt changed everything.
Today, there is no excuse for a website without HTTPS. Let's Encrypt provides free, trusted, automatically renewing SSL certificates to anyone with a domain name. It powers over 300 million websites worldwide and is trusted by every major browser.
This guide explains what SSL is, why it matters, how Let's Encrypt works, and exactly how to install it on an Nginx server running on Ubuntu.
What Is SSL and Why Does It Matter?
SSL (Secure Sockets Layer) — more accurately called TLS (Transport Layer Security) today, though the term SSL stuck — is a protocol that encrypts the connection between a visitor's browser and your web server.
Without SSL, data travels across the internet in plain text. Anyone between the visitor and your server — their ISP, a coffee shop router, a malicious actor on the same network — can read that data. This includes:
- Login credentials
- Credit card numbers
- Personal information
- Form submissions
- Session cookies
With SSL, all of that data is encrypted. Even if intercepted, it is unreadable without the decryption key.
The Padlock in the Browser
You have seen it thousands of times — the padlock icon in the browser address bar next to a URL that starts with https://. That padlock means:
- The connection between the browser and server is encrypted
- The server's identity has been verified by a trusted Certificate Authority
- Data cannot be intercepted or tampered with in transit
Without SSL, modern browsers display a "Not Secure" warning in the address bar. This alone drives visitors away and destroys trust in your website.
SSL Is Not Optional Anymore
Beyond security, SSL affects your website in several concrete ways:
Search Engine Rankings: Google confirmed in 2014 that HTTPS is a ranking signal. Two otherwise identical websites — one with HTTPS, one without — the HTTPS site ranks higher.
Browser Warnings: Chrome, Firefox, and Safari all display prominent "Not Secure" warnings on HTTP sites, especially on pages with login forms or payment fields.
HTTP/2: The modern HTTP/2 protocol — which makes websites significantly faster — requires HTTPS in all major browsers. No SSL means no HTTP/2.
User Trust: Studies consistently show that users abandon websites that display security warnings. For any website handling user data, SSL is non-negotiable.
What Is a Certificate Authority?
Your browser doesn't just trust any SSL certificate. It maintains a list of trusted Certificate Authorities (CAs) — organisations that have been vetted and approved to issue certificates.
When you install an SSL certificate, you are essentially telling browsers: "A trusted organisation has verified that I own this domain. You can trust this connection."
Traditionally, Certificate Authorities charged for this service — anywhere from $10 to $1,000+ per year depending on the certificate type. The revenue model made sense: the CA did the work of verifying your identity and browsers trusted their signature.
Let's Encrypt disrupted this entirely. It is a non-profit Certificate Authority — backed by Mozilla, Google, Cisco, and others — that issues certificates for free, automatically, and without any manual verification process.
What Is Let's Encrypt?
Let's Encrypt is a free, automated, open Certificate Authority launched in 2016 by the Internet Security Research Group (ISRG).
Its certificates are:
- Free — no cost, ever
- Trusted — recognised by all major browsers and operating systems
- Automatic — issuance and renewal are fully automated
- Open — the process is transparent and publicly audited
The only meaningful difference between a Let's Encrypt certificate and a paid certificate is the validation level. Let's Encrypt issues Domain Validated (DV) certificates, which verify you control the domain but do not verify your organisation's legal identity. For the vast majority of websites — blogs, SaaS applications, APIs, portfolios — DV certificates are perfectly sufficient.
If you run a bank or a large e-commerce platform that wants to display your company name in the browser bar, you might want an Extended Validation (EV) certificate from a paid CA. For everything else, Let's Encrypt is the right choice.
How Let's Encrypt Works
Let's Encrypt uses a protocol called ACME (Automatic Certificate Management Environment) to automate the entire certificate lifecycle.
Here is the process, simplified:
Step 1 — Domain Ownership Verification
Before issuing a certificate for example.com, Let's Encrypt needs to verify you actually control that domain. It does this through a challenge.
The most common challenge type is the HTTP-01 challenge:
- Let's Encrypt tells your server to place a specific file at a specific URL — for example
http://example.com/.well-known/acme-challenge/randomtoken - Let's Encrypt then fetches that URL from its servers
- If the file is there with the correct content, domain ownership is proven
- The certificate is issued
This entire process happens in seconds and is fully automated by Certbot.
Step 2 — Certificate Issuance
Once domain ownership is verified, Let's Encrypt issues a certificate valid for 90 days. This short validity period is intentional — it limits the window of exposure if a certificate is ever compromised, and it forces automation of renewal.
Step 3 — Automatic Renewal
Certbot installs a systemd timer (or cron job) that runs twice daily. It checks whether any certificate is within 30 days of expiring. If so, it automatically renews it — re-running the challenge, obtaining a new certificate, and reloading Nginx — all without any manual intervention.
In practice, your certificates renew themselves every 60-70 days, long before the 90-day expiry.
What Is Certbot?
Certbot is the official client tool for Let's Encrypt, maintained by the Electronic Frontier Foundation (EFF). It is the software you install on your server that:
- Communicates with Let's Encrypt's ACME servers
- Handles the domain ownership challenge automatically
- Obtains and installs the SSL certificate
- Configures Nginx (or Apache) to use it
- Sets up automatic renewal
Without Certbot, you would need to manually interact with Let's Encrypt's API. Certbot makes the entire process a single command.
Prerequisites Before Running Certbot
Before you can install an SSL certificate, three things must be true:
1. Your Domain Must Point to Your Server
Let's Encrypt verifies domain ownership by making an HTTP request to your domain. If your domain's DNS is not pointing to your server's IP address, the challenge will fail and no certificate will be issued.
Check your DNS records at your registrar. You need:
| Record | Type | Value |
|---|---|---|
example.com |
A | Your server IP |
www.example.com |
A | Your server IP |
api.example.com |
A | Your server IP |
DNS changes can take anywhere from a few minutes to 48 hours to propagate, depending on your registrar and TTL settings. You can verify DNS has propagated using:
dig example.com +short
Or use an online tool like dnschecker.org.
2. Nginx Must Be Running and Configured
Certbot needs Nginx to be running with a server block configured for your domain. The server block does not need SSL yet — Certbot adds that. It just needs to exist and be active.
3. Port 80 Must Be Open
Certbot uses port 80 (HTTP) to complete the domain challenge. Your firewall must allow incoming traffic on port 80. If you followed the server setup guide in this series, UFW already has port 80 open.
Installing Certbot on Ubuntu with Nginx
Step 1 — Install Certbot
sudo apt install -y certbot python3-certbot-nginx
The python3-certbot-nginx plugin allows Certbot to automatically modify your Nginx configuration to enable SSL — you do not need to edit any config files manually.
Step 2 — Obtain Your First Certificate
sudo certbot --nginx -d example.com -d www.example.com
What the flags mean:
-
--nginx— use the Nginx plugin to automatically configure SSL -
-d example.com— issue certificate for this domain -
-d www.example.com— include this as an additional domain on the same certificate
You can include multiple -d flags to cover multiple subdomains on one certificate:
sudo certbot --nginx -d example.com -d www.example.com -d api.example.com
Step 3 — Answer the Prompts
Certbot will ask you a few questions:
Enter email address: you@example.com
Agree to terms of service: Y
Share email with EFF: N (your choice)
Redirect HTTP to HTTPS: 2 (Always redirect — recommended)
Choose option 2 for the redirect. This automatically adds an Nginx rule that sends all HTTP traffic to HTTPS, so visitors who type http://example.com are seamlessly redirected to https://example.com.
Step 4 — What Certbot Does Automatically
After you answer the prompts, Certbot:
- Contacts Let's Encrypt servers
- Places a challenge file in your web root
- Let's Encrypt verifies the file
- Certificate is issued and saved to
/etc/letsencrypt/live/example.com/ - Certbot modifies your Nginx config to enable SSL on port 443
- Certbot adds the HTTP to HTTPS redirect on port 80
- Nginx is reloaded
Your site is now serving HTTPS. The entire process takes under 60 seconds.
What Your Nginx Config Looks Like After Certbot
Before Certbot, your Nginx server block looked like this:
server {
listen 80;
server_name example.com www.example.com;
root /var/www/example.com/public;
...
}
After Certbot runs, it transforms it into:
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name example.com www.example.com;
root /var/www/example.com/public;
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;
...your existing config...
}
The first server block catches all HTTP traffic and redirects it to HTTPS. The second handles all HTTPS traffic with your SSL certificate.
Where Certbot Stores Your Certificates
/etc/letsencrypt/
├── live/
│ └── example.com/
│ ├── fullchain.pem ← Your certificate + intermediate chain
│ ├── privkey.pem ← Your private key (keep this secret)
│ ├── cert.pem ← Your certificate only
│ └── chain.pem ← Intermediate certificates only
├── archive/
│ └── example.com/ ← Historical certificates (all versions)
└── renewal/
└── example.com.conf ← Renewal configuration
Important: The files in live/ are actually symbolic links pointing to the latest version in archive/. When Certbot renews your certificate, it creates new files in archive/ and updates the symlinks — so your Nginx config never needs to change.
Never delete anything in /etc/letsencrypt/ unless you know exactly what you are doing.
Automatic Certificate Renewal
This is where Let's Encrypt's real power shows. Certbot installs a systemd timer that runs twice daily:
# Check the timer status
sudo systemctl status certbot.timer
You will see it is active and scheduled to run at random times twice per day. The randomisation prevents all Certbot installations worldwide from hitting Let's Encrypt's servers simultaneously.
When the timer runs, Certbot checks each certificate. If any certificate expires within 30 days, it renews it automatically. In practice your certificates renew around the 60-day mark — well before the 90-day expiry.
Test Renewal Without Actually Renewing
sudo certbot renew --dry-run
This simulates the entire renewal process without actually changing anything. Run this after installation to confirm renewal will work when the time comes.
Expected output:
Congratulations, all simulated renewals succeeded:
/etc/letsencrypt/live/example.com/fullchain.pem (success)
Managing Multiple Domains
If you host multiple websites on one server, you can have separate certificates for each domain:
# Certificate for your main app
sudo certbot --nginx -d example.com -d www.example.com
# Certificate for your API
sudo certbot --nginx -d api.example.com
# Certificate for another site
sudo certbot --nginx -d anotherdomain.com -d www.anotherdomain.com
Each domain gets its own certificate stored separately in /etc/letsencrypt/live/. Certbot manages renewal for all of them automatically.
List all your certificates:
sudo certbot certificates
Output:
Found the following certs:
Certificate Name: example.com
Domains: example.com www.example.com
Expiry Date: 2026-11-14 (VALID: 89 days)
Certificate Path: /etc/letsencrypt/live/example.com/fullchain.pem
Certificate Name: api.example.com
Domains: api.example.com
Expiry Date: 2026-11-14 (VALID: 89 days)
Certificate Path: /etc/letsencrypt/live/api.example.com/fullchain.pem
Testing Your SSL Installation
After installing your certificate, verify it is working correctly.
Test in Your Browser
Visit https://example.com and click the padlock icon. You should see:
- Connection is secure
- Certificate is valid
- Issued by: Let's Encrypt
Test with SSL Labs
SSL Labs provides a free, detailed SSL analysis of your domain. It checks:
- Certificate validity
- Certificate chain
- Protocol support (TLS 1.2, TLS 1.3)
- Cipher strength
- Known vulnerabilities
A properly configured Let's Encrypt certificate with default Certbot settings typically scores A on SSL Labs.
Test from the Command Line
curl -I https://example.com
Expected output:
HTTP/2 200
server: nginx
...
The HTTP/2 200 confirms both HTTPS and HTTP/2 are working.
Common Problems and Solutions
Challenge Failed — Domain Not Pointing to Server
Error:
Challenge failed for domain example.com
Cause: DNS is not pointing to your server yet, or DNS has not propagated.
Solution:
# Check what IP your domain resolves to
dig example.com +short
# It must match your server IP
curl ifconfig.me
Wait for DNS propagation and try again.
Port 80 Is Blocked
Error:
Connection refused on port 80
Cause: Your firewall is blocking HTTP.
Solution:
sudo ufw allow http
sudo ufw status
Nginx Configuration Error
Error:
nginx: configuration file test failed
Solution:
sudo nginx -t
Fix whatever error it reports before running Certbot again.
Certificate Already Exists
If you run Certbot for a domain that already has a certificate, it will ask whether to renew, expand, or reinstall. Choose:
- Renew — get a fresh certificate for the same domains
- Expand — add new domains to the existing certificate
- Reinstall — reinstall the existing certificate without changes
Rate Limits
Let's Encrypt has rate limits to prevent abuse:
| Limit | Value |
|---|---|
| Certificates per domain per week | 5 |
| Duplicate certificates per week | 5 |
| Failed validations per hour | 5 |
In practice you will never hit these limits in normal use. They only matter if you are repeatedly requesting certificates for the same domain due to testing or errors.
If you do hit a rate limit, you must wait before trying again. To avoid this during testing, use Let's Encrypt's staging environment:
sudo certbot --nginx --staging -d example.com
Staging certificates are not trusted by browsers but have much higher rate limits. Use staging to test your setup, then run without --staging for the real certificate.
Revoking a Certificate
If your private key is ever compromised, revoke the certificate immediately:
sudo certbot revoke --cert-path /etc/letsencrypt/live/example.com/cert.pem
Then obtain a new certificate:
sudo certbot --nginx -d example.com
The Bigger Picture — HTTPS Everywhere
Let's Encrypt's mission is to make HTTPS universal. Before it existed, the friction and cost of SSL certificates meant that millions of websites transmitted user data in plain text. Today there is no technical or financial barrier to HTTPS.
If you are building a web application, an API, or any internet-facing service, HTTPS is not a feature — it is a baseline requirement. Let's Encrypt removes every excuse not to have it.
Quick Reference — Certbot Commands
# Install Certbot
sudo apt install -y certbot python3-certbot-nginx
# Obtain certificate for a domain
sudo certbot --nginx -d example.com -d www.example.com
# List all certificates
sudo certbot certificates
# Test renewal (dry run)
sudo certbot renew --dry-run
# Force renewal immediately
sudo certbot renew --force-renewal
# Revoke a certificate
sudo certbot revoke --cert-path /etc/letsencrypt/live/example.com/cert.pem
# Delete a certificate
sudo certbot delete --cert-name example.com
# Check renewal timer
sudo systemctl status certbot.timer
# Test staging (no rate limits)
sudo certbot --nginx --staging -d example.com
Summary
Here is everything covered in this guide:
- SSL encrypts the connection between your visitor and server — it is mandatory for any modern website
- Let's Encrypt is a free, trusted, automated Certificate Authority that issues 90-day certificates
- Certbot is the tool that talks to Let's Encrypt, installs your certificate, configures Nginx, and renews automatically
- Domain ownership is verified via the HTTP-01 challenge — Let's Encrypt checks a file on your server
- Certificates auto-renew every 60 days via a systemd timer — zero manual work required
- Always run
certbot renew --dry-runafter setup to confirm renewal works - Use
--stagingfor testing to avoid rate limits - SSL Labs gives you an independent grade of your SSL configuration
When your domain is pointed to your server and Nginx is configured, running Let's Encrypt takes less than two minutes. There is genuinely no reason to run any website without it.
Top comments (0)