Self-Signed SSL Certificate for Nginx
A practical step-by-step guide. Generates a working HTTPS setup in under five minutes.
Self-signed certificates are perfect for local development, staging servers, internal tools, and learning how TLS works. Browsers will display a warning because the certificate isn't signed by a trusted CA, but the traffic itself is encrypted the same way as with a Let's Encrypt cert.
Step 1: Generate the Certificate
The fastest way is to use cert-depot.com — enter your domain, click generate, and download the ZIP. You'll get two files: certificate.pem and private-key.pem.
If you prefer the command line with OpenSSL:
openssl req -x509 -newkey rsa:2048 -nodes \
-keyout private-key.pem -out certificate.pem \
-days 365 \
-subj "/CN=localhost" \
-addext "subjectAltName=DNS:localhost,DNS:example.local,IP:127.0.0.1"
Important: Always include a Subject Alternative Name (SAN). Modern browsers (Chrome 58+, released 2017) ignore the Common Name field and will reject certificates without a matching SAN, even if the CN is correct.
Step 2: Install the Files
Place the certificate and key somewhere Nginx can read them. A common convention is /etc/nginx/ssl/:
sudo mkdir -p /etc/nginx/ssl
sudo cp certificate.pem /etc/nginx/ssl/
sudo cp private-key.pem /etc/nginx/ssl/
sudo chmod 600 /etc/nginx/ssl/private-key.pem
sudo chown root:root /etc/nginx/ssl/*
The chmod 600 on the private key is critical — it should not be readable by any user other than root.
Step 3: Configure the Server Block
Edit your site configuration (typically /etc/nginx/sites-available/default or a file under /etc/nginx/conf.d/):
server {
listen 443 ssl;
server_name example.local;
ssl_certificate /etc/nginx/ssl/certificate.pem;
ssl_certificate_key /etc/nginx/ssl/private-key.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
root /var/www/html;
index index.html;
}
}
# Optional: redirect HTTP to HTTPS
server {
listen 80;
server_name example.local;
return 301 https://$server_name$request_uri;
}
Step 4: Test and Reload
Always test the configuration before reloading Nginx to avoid downtime:
sudo nginx -t
sudo systemctl reload nginx
If nginx -t reports errors, fix them before reloading. Common issues: typo in file paths, missing file, or wrong file permissions.
Step 5: Verify HTTPS is Working
Use curl to confirm the certificate is being served (the -k flag tells curl to ignore the untrusted-certificate warning):
curl -kvI https://example.local/
You should see the certificate details in the output. To inspect exactly what's being served:
openssl s_client -connect example.local:443 -servername example.local \
</dev/null 2>/dev/null | openssl x509 -text -noout
Or paste the certificate into our PEM decoder to see its details in a friendlier format.
Troubleshooting
Browser shows "Your connection is not private"
This is expected with a self-signed certificate. In Chrome, click "Advanced" and then "Proceed to example.local (unsafe)". To avoid the warning entirely, you need to trust the certificate in your system's certificate store.
Nginx won't start with "cannot load certificate"
Check that the certificate file exists and Nginx can read it. Run sudo ls -la /etc/nginx/ssl/ and verify the paths in your config match exactly.
Certificate errors despite the correct CN
This almost always means your certificate doesn't have a matching Subject Alternative Name. Regenerate it including the hostname as a SAN — see Step 1.