Let's Encrypt SSL with Certbot for Nginx: Full Guide
Run on the server with one command (check the script contents below first):
curl -sSL https://cp.lv/scripts/besplatnyj-ssl-lets-encrypt.sh | sudo bash…or with wget:
wget -qO- https://cp.lv/scripts/besplatnyj-ssl-lets-encrypt.sh | sudo bashScript contents besplatnyj-ssl-lets-encrypt.sh:
#!/usr/bin/env bash
# Issue a Let's Encrypt certificate for Nginx
set -e
export DEBIAN_FRONTEND=noninteractive
DOMAIN=example.com
[email protected]
# 1. Open ports 80 and 443
sudo ufw allow 'Nginx Full' || true
# 2. Install certbot with the Nginx plugin
sudo apt-get update
sudo apt-get install -y certbot python3-certbot-nginx
# 3. Issue the certificate and set up the HTTPS redirect (non-interactive)
sudo certbot --nginx -d ${DOMAIN} -d www.${DOMAIN} \
--non-interactive --agree-tos -m ${EMAIL} --redirect
# 4. Check the Nginx config and automatic renewal
sudo nginx -t && sudo systemctl reload nginx
sudo certbot renew --dry-run
echo "Done: HTTPS is enabled for ${DOMAIN}, automatic renewal is configured."
Let’s Encrypt is a non-profit certificate authority that issues TLS certificates at no charge: the certificate itself costs nothing, and the certbot utility issues and renews it automatically. Here is how to enable HTTPS for an Nginx site in a few minutes.
What you need first
- A domain whose A record points to your server IP.
- A working Nginx server block with the correct
server_name. - Open ports 80 and 443:
sudo ufw allow 'Nginx Full'
Port 80 is mandatory — Let’s Encrypt uses it to verify domain ownership (the HTTP-01 challenge).
If the server block does not exist yet, open the config in an editor (nano, vim or mcedit):
sudo nano /etc/nginx/sites-available/example.com
A minimal HTTP config for the domain validation (certbot will add the HTTPS part later):
server {
listen 80;
server_name example.com www.example.com;
root /var/www/example.com;
index index.html;
}
Or write the whole config with a single command — copy it and paste it into the console (the quotes around 'EOF' matter, so that Nginx $ variables are left alone):
sudo tee /etc/nginx/sites-available/example.com > /dev/null << 'EOF'
server {
listen 80;
server_name example.com www.example.com;
root /var/www/example.com;
index index.html;
}
EOF
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
Step 1. Install certbot
The recommended way is snap — it always carries a current version:
sudo snap install core && sudo snap refresh core
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
The apt alternative (if snap is unavailable):
sudo apt install certbot python3-certbot-nginx -y
Step 2. Issue the certificate
The Nginx plugin finds the right server block itself, issues the certificate and writes the HTTPS settings:
sudo certbot --nginx -d example.com -d www.example.com
Certbot asks for an email (for expiry notices) and for agreement with the terms. When asked about the redirect, choose the option that redirects HTTP to HTTPS. After a successful issue, the certificate is stored in /etc/letsencrypt/live/example.com/.
Step 3. What certbot adds to the config
After the issue, these lines appear in the server block:
listen 443 ssl;
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;
Plus a separate block redirecting port 80 to HTTPS. Verify and reload:
sudo nginx -t
sudo systemctl reload nginx
Step 4. Check auto-renewal
Let’s Encrypt certificates are valid for 90 days. Certbot installs a systemd timer that renews them automatically. Check the timer and run a renewal rehearsal:
systemctl list-timers | grep certbot
sudo certbot renew --dry-run
If --dry-run finishes without errors, the real renewal will work too. Nothing has to be done by hand.
Step 5. Verify HTTPS
Open https://example.com — a padlock appears in the address bar. You can check the chain and the expiry date from the console:
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -dates
Useful certbot commands
| Task | Command |
|---|---|
| List certificates | sudo certbot certificates |
| Renew now | sudo certbot renew |
| Revoke a certificate | sudo certbot revoke --cert-name example.com |
| Add a domain | sudo certbot --nginx -d example.com -d shop.example.com |
FAQ
Is a Let’s Encrypt certificate really issued at no cost? Yes, the Let’s Encrypt authority issues and renews certificates without payment — that is its model. You only pay for the server the site runs on.
What do I do if certbot says “challenge failed”?
Most often the domain A record does not point to the server yet, or port 80 is closed. Check DNS (dig example.com) and the firewall rules.
A 90-day certificate — do I have to renew it manually?
No. Certbot installs a renewal timer. Verify it with certbot renew --dry-run and that is enough.
Can I issue a wildcard certificate (*.example.com)? Yes, but it requires the DNS-01 challenge and a plugin for your DNS provider, because the HTTP check does not work for subdomains.
HTTPS is mandatory for any site today: it affects both user trust and rankings. You can deploy a site with a certificate on the plans from the VPS hosting page, and for shops and CMSes there is WordPress VPS.