How to Install an SSL Certificate on Nginx
Updated
This guide shows how to install a free Let's Encrypt SSL certificate on an Nginx web server, redirect all HTTP traffic to HTTPS, and confirm the certificate chain is correct. It works on Ubuntu, Debian, CentOS, Rocky Linux and any other system running Nginx.
1. Get your certificate files
Create a free MTFreeSSL account, generate a certificate for your domain and download the ZIP. It contains:
| File | What it is | Used by Nginx? |
|---|---|---|
fullchain.pem | Your certificate followed by the intermediate CA certificate | Yes — ssl_certificate |
private.key | The private key for your certificate | Yes — ssl_certificate_key |
certificate.pem | Your domain certificate only | No |
ca-bundle.pem | The intermediate CA certificate only | No |
Nginx needs the full chain, not just certificate.pem. Using only the domain
certificate causes "certificate not trusted" errors on some browsers and on most API clients.
2. Upload the files to your server
Copy the two files to a directory only root can read:
sudo mkdir -p /etc/ssl/example.com
sudo cp fullchain.pem private.key /etc/ssl/example.com/
sudo chmod 600 /etc/ssl/example.com/private.key
Never place the private key inside your web root, and never share it.
3. Configure the Nginx server block
Edit your site config (for example /etc/nginx/sites-available/example.com or
/etc/nginx/conf.d/example.com.conf) and add an HTTPS server block:
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name example.com www.example.com;
ssl_certificate /etc/ssl/example.com/fullchain.pem;
ssl_certificate_key /etc/ssl/example.com/private.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
root /var/www/example.com;
index index.html;
}
On Nginx older than 1.25.1, remove http2 on; and write listen 443 ssl http2; instead.
4. Redirect HTTP to HTTPS
Add (or replace) the port 80 block so every visitor ends up on HTTPS. Keep the
/.well-known/acme-challenge/ location if you plan to renew using file verification:
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
location /.well-known/acme-challenge/ {
root /var/www/example.com;
}
location / {
return 301 https://$host$request_uri;
}
}
5. Test and reload Nginx
sudo nginx -t
sudo systemctl reload nginx
nginx -t must report syntax is ok before you reload. If it complains that it cannot load
the key, check the file path and that the key and certificate belong together.
6. Verify the certificate
Open https://example.com in a browser and click the padlock, or check from the command line:
openssl s_client -connect example.com:443 -servername example.com </dev/null | openssl x509 -noout -subject -issuer -dates
The issuer should be a Let's Encrypt intermediate and the dates should match your download.
Troubleshooting
- "key values mismatch" — the private key does not belong to this certificate. Download both files from the same certificate.
- Browser says "not secure" with a staging certificate — staging certificates are for testing and are never trusted. Generate a production certificate.
- Port 443 times out — open it in your firewall, e.g.
sudo ufw allow 443/tcp, and in your cloud provider's security group.
Renewing
Let's Encrypt certificates last 90 days. Generate a new certificate before the expiry date shown on your
dashboard, replace the two files, and run sudo systemctl reload nginx.
Need a certificate?
Generate a free Let's Encrypt SSL certificate in your browser — no Certbot required.
Get Your Free SSL Certificate