📋 Table of Contents
Websites without SSL are marked "Not Secure" by browsers and penalized in Google's ranking. Let's Encrypt solves this with a free SSL certificate, and Certbot automates the entire installation and renewal process on your VPS running Nginx.
1. What is Certbot and Let's Encrypt?
Let's Encrypt is a non-profit Certificate Authority (CA) founded by the Internet Security Research Group (ISRG), with support from EFF, Mozilla, Cisco, and Akamai. It issues free SSL/TLS certificates using the ACME Protocol (Automated Certificate Management Environment).
Certbot is the official ACME client developed by the Electronic Frontier Foundation (EFF). It integrates directly with Let's Encrypt and can:
- Automatically request new certificates
- Modify Nginx or Apache configuration to enable HTTPS
- Renew certificates before they expire
- Manage certificates for multiple domains simultaneously
2. Prerequisites
| Requirement | Details | Notes |
|---|---|---|
| OS | Ubuntu 20.04/22.04/24.04 or Debian 11/12 | Ubuntu LTS recommended |
| Web Server | Nginx installed and running | version 1.14+ |
| Domain | A record pointing to VPS IP | Wait for DNS propagation |
| Ports | 80 (HTTP) and 443 (HTTPS) open | Both required |
| Access | root or sudo user | – |
Verify your domain's DNS is pointing to your VPS:
dig +short example.com A
# Should return your VPS IP address
3. Install Certbot on Ubuntu/Debian
The recommended method is via snap, which ensures you always get the latest Certbot version:
# Update package list
sudo apt update
# Install snap (if not present)
sudo apt install snapd -y
# Install and refresh core snap
sudo snap install core
sudo snap refresh core
# Install Certbot
sudo snap install --classic certbot
# Create symlink for global access
sudo ln -s /snap/bin/certbot /usr/bin/certbot
Verify the installation:
certbot --version
# certbot 2.x.x
apt install certbot, remove it first and reinstall via snap to ensure you have the latest version.
4. Configure Nginx Before Obtaining a Certificate
Certbot needs Nginx to recognise your domain's server_name before issuing a certificate. Check your config file:
sudo nano /etc/nginx/sites-available/example.com
Minimal Nginx config (before SSL):
server {
listen 80;
server_name example.com www.example.com;
root /var/www/example.com;
index index.html index.php;
location / {
try_files $uri $uri/ =404;
}
}
Enable the config and reload Nginx:
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
Open firewall ports:
sudo ufw allow 'Nginx Full'
sudo ufw status
5. Obtain an SSL Certificate
Request a certificate and let Certbot automatically modify your Nginx config:
sudo certbot --nginx -d example.com -d www.example.com
Certbot will prompt you for:
- Email address: For expiry notifications
- Terms of Service: Press A to agree
- Share email with EFF: Y or N
- Redirect HTTP → HTTPS: Press 2 to redirect all traffic
After Certbot modifies your Nginx config, it will look like this:
server {
listen 443 ssl;
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;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
6. Verify SSL and HTTPS Redirect
Check installed certificates:
sudo certbot certificates
Test HTTPS redirect:
curl -I http://example.com
# Expect: HTTP/1.1 301 Moved Permanently
# Location: https://example.com/
curl -I https://example.com
# Expect: HTTP/2 200
Test SSL quality at SSL Labs (ssllabs.com/ssltest). A properly configured Let's Encrypt + Nginx setup typically achieves Grade A.
7. Configure Automatic Renewal
When installed via snap, Certbot sets up a systemd timer automatically. Verify it:
sudo systemctl status snap.certbot.renew.timer
Test that auto-renewal works without affecting live certificates:
sudo certbot renew --dry-run
Alternatively, use cron:
# Open crontab
sudo crontab -e
# Add this line (runs at 00:00 and 12:00 daily)
0 0,12 * * * certbot renew --quiet --post-hook "systemctl reload nginx"
--post-hook "systemctl reload nginx" flag reloads Nginx immediately after successful renewal so the new certificate takes effect without waiting for a server restart.
8. Wildcard SSL with DNS Challenge
Wildcard certificates (*.example.com) cover all subdomains but require a DNS-01 challenge:
sudo certbot certonly --manual --preferred-challenges dns \
-d "example.com" -d "*.example.com"
Certbot will ask you to add a TXT record to your DNS:
- Add a DNS TXT record:
_acme-challenge.example.com→ the value Certbot provides - Wait for DNS propagation (5–30 minutes)
- Press Enter to verify
9. Common Troubleshooting
Error: Connection refused / Port 80 closed
sudo ufw allow 80
sudo ufw allow 443
sudo ufw reload
Error: DNS not resolving
Wait for DNS propagation to complete. Test with:
nslookup example.com 8.8.8.8
Error: Too many certificates
Let's Encrypt limits 5 certificates per domain per week. Use the --staging flag for testing:
sudo certbot --nginx -d example.com --staging
Certificate expired, auto-renewal not working
# Check logs
sudo journalctl -u snap.certbot.renew.service
# Force manual renewal
sudo certbot renew --force-renewal
Nginx shows 404 after SSL installation
Verify the root path in Nginx config is correct and index.html exists:
sudo nginx -t
sudo systemctl reload nginx
Frequently Asked Questions (FAQ)
Summary
Installing Let's Encrypt SSL with Certbot on a VPS running Nginx is straightforward. The key steps are: install Certbot via snap → configure Nginx server_name → run certbot --nginx → test auto-renewal with --dry-run. Once done, your VPS website has free HTTPS that renews itself indefinitely.