Is your site still serving traffic over plain HTTP? Or do you have an expired SSL certificate making visitors see “Not Secure” warnings? This is a real problem. We see it every day in projects that come to us: sites configured once and never touched again, certificates expiring on a Sunday, users abandoning the cart because the browser screams “connection not private”.
At Meteora Web, we've been handling this for years. We come from accounting and financial statements, so we know exactly what an expired certificate costs: lost sales, lost trust, lost SEO ranking. In this guide we cut straight to the point: how to set up SSL/TLS on Nginx with Let's Encrypt and Certbot, and more importantly how to automate the renewal – because doing it manually is a beginner's mistake.
SSL/TLS: Why it's no longer optional
If you think HTTPS is only for e-commerce sites, think again. Since 2014 Google has used it as a ranking factor. Since 2018 Chrome marks any HTTP site as “Not Secure”. In 2026 there is no excuse: Let's Encrypt has made certificates free, automatic and universal.
A site without HTTPS pays twice: it loses Google rankings and loses visitor trust. We measure it on our clients: after switching to HTTPS, average session duration increases and bounce rate drops.
What you risk by neglecting encryption
- Data security: passwords, cookies, payment data travel in plain text. An attacker on a public Wi-Fi can intercept them with tools like Wireshark.
- SEO ranking: Google penalizes HTTP sites. If a competitor has HTTPS and you don't, you lose positions without doing anything wrong.
- Content integrity: without TLS, a man-in-the-middle attack can modify your page content – inject malware, redirect to phishing.
- Regulatory compliance: GDPR and privacy laws require adequate data protection measures. HTTPS is considered the bare minimum.
Let's Encrypt & Certbot: The duo that democratized HTTPS
Let's Encrypt is a free, automated, and open Certificate Authority. It issues certificates valid for 90 days – deliberately short to push automation. Certbot is the official client that talks to Let's Encrypt via the ACME protocol.
Sponsored Protocol
Why 90 days? To force you to implement automatic renewal. An annual certificate lulls you into thinking you'll renew it manually, then the day comes when you forget, and the site goes down.
How the ACME protocol works
ACME (Automatic Certificate Management Environment) lets your server prove to Let's Encrypt that it controls the domain. The most common challenge is http-01: Certbot creates a file at http://yourdomain/.well-known/acme-challenge/, Let's Encrypt verifies it, and issues the certificate. With Nginx, Certbot can automatically modify the configuration to solve the challenge.
Sponsored Protocol
Step-by-step installation and configuration with Nginx
We assume a Linux server (Ubuntu/Debian or CentOS/RHEL) with Nginx already installed and the domain pointed to the server.
Prerequisites
- Nginx installed and running
- Port 80 open (firewall, security group)
- Domain with A/AAAA record pointing to your server IP
- sudo access to the server
Install Certbot
On Ubuntu/Debian:
sudo apt update
sudo apt install certbot python3-certbot-nginx
On CentOS/RHEL (with EPEL):
sudo dnf install epel-release
sudo dnf install certbot python3-certbot-nginx
Why python3-certbot-nginx? It contains the plugin that interacts directly with Nginx: it modifies configs and handles the ACME challenge without you touching files manually.
Obtain the certificate
Run the main command, specifying your domain:
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
Certbot will ask for an email address for renewal notices (important) and whether you want to redirect all HTTP traffic to HTTPS. Answer “2” to enable automatic redirection.
Warning: if you have a custom Nginx configuration, Certbot will modify it. We always recommend making a backup first:
sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/default.backup
Configure Nginx for SSL
After running Certbot, your site configuration should look similar to this (minimal example):
Sponsored Protocol
server {
listen 443 ssl http2;
server_name yourdomain.com www.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
root /var/www/html;
index index.html;
}
server {
listen 80;
server_name yourdomain.com www.yourdomain.com;
return 301 https://$server_name$request_uri;
}
Verify that Nginx reloads without errors:
sudo nginx -t
sudo systemctl reload nginx
Automatic renewal: the real advantage
The certificate lasts 90 days. You can't afford to renew it manually every three months. Certbot automatically installs a systemd timer (or a cron job) that runs twice a day (it actually checks if the certificate expires within 30 days and renews it if needed).
Check the systemd timer or cron
On systems with systemd (Ubuntu, modern CentOS):
sudo systemctl list-timers | grep certbot
# or
sudo systemctl status certbot.timer
You should see an active timer that triggers certbot.service. If not, enable it:
sudo systemctl enable certbot.timer
sudo systemctl start certbot.timer
On older systems or when using cron:
Sponsored Protocol
sudo crontab -e
# add the line:
0 0 * * * /usr/bin/certbot renew --quiet
Test the renewal
Don't wait 30 days to see if it works. Simulate the renewal with:
sudo certbot renew --dry-run
If the command completes without errors, automatic renewal is ready. We run this on every new server and check it periodically. One client had a broken renewal because the certificate was installed with a different plugin – we discovered it immediately with --dry-run.
Best practices and additional security
Certbot already generates a secure configuration (it includes the options-ssl-nginx.conf file). But there are extra tweaks we always apply:
HSTS (HTTP Strict Transport Security)
This tells the browser to always connect via HTTPS, even if the user types http://. Add this to your server block:
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;
Caution: with includeSubDomains, make sure all subdomains support HTTPS, otherwise they will become unreachable.
OCSP Stapling
Improves load times and privacy:
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
Perfect Forward Secrecy and modern ciphers
Let's Encrypt already suggests modern ciphers, but verify you aren't using weak ones. You can use:
Sponsored Protocol
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
Clean HTTP → HTTPS redirect
The redirect generated by Certbot works fine, but if you prefer to manage it manually, make sure it's a 301 and not a 302.
In summary — what to do now
- Install Certbot with the Nginx plugin on your server.
- Obtain the certificate with
sudo certbot --nginx -d yourdomain.com. - Verify the config with
sudo nginx -tand reload Nginx. - Check the renewal timer with
sudo systemctl status certbot.timer. - Test renewal with
sudo certbot renew --dry-run. - Apply best practices: HSTS, OCSP Stapling, updated ciphers.
- Monitor expiration periodically with tools like
check-sslor simply by watching Search Console for security errors.
If you have a complex infrastructure or prefer a helping hand, at Meteora Web we do this every day. When a server's automatic SSL renewal broke, we fixed and automated it without taking the client offline. The digital divide is bridged with clean, solid configurations.
For a complete overview of Nginx in production, read the Definitive Nginx Pillar Guide.