SSL Certificate One-Click Setup (Certbot)
Many site owners take a long way around when getting a free SSL certificate: downloading certificate files from a dashboard, uploading them by hand, or agonizing over which paid certificate to buy. With Certbot and Let's Encrypt, one command issues the certificate and wires it into Nginx or Apache, with renewal handled automatically. Here is the complete workflow.
Let's explain the principle first so you understand what each command does. Let's Encrypt is a free, automated certificate authority built on the ACME protocol: Certbot acts as the client and proves to Let's Encrypt that "you really control this domain"; once verified, the certificate is issued. There is no human review, so you can request and renew as often as needed. The only cost is the 90-day validity — which many people initially find annoying, but it is precisely what makes the system safe: with short-lived certificates, even a leaked private key only exposes a three-month window. Installing Certbot adds a systemd timer that checks and renews automatically every 60 days, with no manual work.
Install Certbot
# Install Certbot (Nginx mode)
apt install certbot python3-certbot-nginx -y
# Issue a certificate (auto-configures Nginx)
certbot --nginx -d example.com -d www.example.com
# Test renewal (verify without actually renewing)
certbot renew --dry-run
# List issued certificates
certbot certificates
The certbot --nginx mode does three things: detects the Nginx site config, temporarily modifies it to complete HTTP validation, and writes the certificate paths into the server block. If you worry about it breaking your config, back up the files under /etc/nginx/sites-available/ first with cp. You can also run plain certbot certonly without --nginx, but then you have to fill in the certificate paths and Nginx config yourself, which is error-prone.
How to Get a Wildcard Certificate
A second-level domain has one certificate per subdomain, and requesting them one by one gets tedious. A wildcard certificate covers all subdomains with *.example.com, but it requires DNS validation instead of HTTP validation:
# Manual DNS validation
certbot certonly --manual --preferred-challenges dns \
-d *.example.com -d example.com
# Or use a DNS plugin for automatic validation (Cloudflare example)
# First configure ~/.cloudflare/credentials
certbot certonly --dns-cloudflare \
--dns-cloudflare-credentials ~/.cloudflare/credentials \
-d *.example.com -d example.com
Why must wildcards use DNS validation? HTTP validation requires "every subdomain to reach this server on port 80", which is impossible for *.example.com since it points at countless subdomains. DNS validation instead makes Let's Encrypt check a special TXT record, _acme-challenge; being able to add that record in your DNS console proves domain control. The manual flow waits for the TXT record to propagate (usually a few minutes), while a DNS plugin does it automatically. If your DNS provider has no plugin and you want to avoid manual steps, tools like acme.sh support many more providers.
The Nginx SSL Configuration
After the certificate is issued, the Nginx site config looks roughly 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;
# Modern TLS configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
}
# HTTP to HTTPS redirect
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$server_name$request_uri;
}
Two details are easy to miss here. First, point the certificate paths at /etc/letsencrypt/live/<domain>/ rather than the archive directory, because the files under live are symlinks that automatically point at the new certificate after renewal — no restart needed. If you copied the certificate files to another path by hand, they go stale after renewal. Second, keep only TLSv1.2 and TLSv1.3 in ssl_protocols; TLSv1.0/1.1 lost browser support back in 2020 and leaving them enabled just makes you a scanner target. For a higher security rating, add an HSTS header so browsers always use HTTPS.
Auto-Renewal
Let's Encrypt certificates are valid for only 90 days, so auto-renewal is not optional. Installing Certbot adds a systemd timer that checks daily:
# Show the renewal timer
systemctl list-timers | grep certbot
# Trigger a renewal check
certbot renew --force-renewal
# Check the renewal log
grep -i "renew\|success" /var/log/letsencrypt/letsencrypt.log
The most reliable way to check that renewal works is to run certbot renew --dry-run every so often — it simulates the whole renewal without actually renewing. If the server clock drifts or DNS resolution hiccups, renewal fails, so consider alerting on renewal failures. One reminder: HTTP-validation renewals also depend on port 80. If Nginx is restarted during the renewal window or the firewall blocks port 80, renewal fails — another reason to keep port 80 open.
Troubleshooting Reference
| Error | Solution |
|---|---|
Could not bind to port 80 |
Stop the service on port 80 first, e.g. systemctl stop nginx |
Too many certificates |
Let's Encrypt allows 50 certs/week/domain; avoid repeated reissues |
DNS problem: NXDOMAIN |
Confirm the domain resolves to this server |
| Renewal failed | Check port 80 reachability and DNS resolution |
Scenario and Recommendations
If the site sits behind a CDN, set the SSL mode to Full (Strict) in Cloudflare, otherwise you may see broken chains or redirect loops. For example: your origin has a Let's Encrypt certificate and the CDN serves HTTPS with its own certificate, but if the origin link is set to Flexible, the CDN fetches from the origin over HTTP — the browser shows a padlock while the content actually travels in plaintext. Full (Strict) requires the origin certificate to be genuinely valid, keeping the whole chain encrypted. In general, the free Let's Encrypt certificate is more than enough for personal sites and most small-to-medium sites; only consider a paid OV/EV certificate if your business has strict compliance requirements and needs a one-year validity — see the SSL certificate types guide for the differences.
For the full setup, see the Let's Encrypt SSL setup guide and Certbot automation. After launch, redirect HTTP to HTTPS and set up expiry monitoring so a lapsed certificate never takes the site down.
References
Reference: Certbot official documentation https://certbot.eff.org/
Reference: Let's Encrypt documentation https://letsencrypt.org/docs/
Reference: SSL Labs online test https://www.ssllabs.com/ssltest/
Reference: Mozilla SSL configuration generator https://ssl-config.mozilla.org/