SSL certificates can be valid for at most 199 days. By 15 March 2027 the limit becomes 99 days, for DigiCert certificates from 24 February 2027. Read more →
Nginx / Linux Advanced ~4 min. read

Nginx SSL/TLS Configuration Guide

A comprehensive guide to configuring SSL/TLS certificates in Nginx on Linux, including OCSP stapling, secure cipher suites, and HTTP to HTTPS redirection.

Nginx SSL/TLS Configuration Guide

Overview

Nginx is one of the most popular web servers and reverse proxies in the world. This guide covers the entire SSL/TLS setup process: from generating a CSR with OpenSSL to certificate installation, chain bundling, and hardening your configuration with modern TLS settings, OCSP stapling, and HSTS.

Prerequisites

  • Nginx 1.18+ installed (older versions may not support TLS 1.3)
  • OpenSSL installed on the server
  • Root or sudo access
  • A domain name pointing to the server's IP address
  • An SSL certificate from FairSSL (DV, OV, or EV)

Step 1: Generate a Private Key and CSR with OpenSSL

# Create directory for certificate files
sudo mkdir -p /etc/nginx/ssl/eksempel.dk

# Generate 2048-bit RSA key and CSR
sudo openssl req -new -newkey rsa:2048 -nodes \
  -keyout /etc/nginx/ssl/eksempel.dk/privkey.key \
  -out /etc/nginx/ssl/eksempel.dk/eksempel.csr \
  -subj "/C=DK/ST=Hovedstaden/L=Koebenhavn/O=Eksempel A\/S/CN=www.eksempel.dk"

# Set restrictive permissions on the private key
sudo chmod 600 /etc/nginx/ssl/eksempel.dk/privkey.key
sudo chown root:root /etc/nginx/ssl/eksempel.dk/privkey.key

Submit the contents of the CSR file through your FairSSL.com control panel to order the certificate.

Step 2: Prepare Certificate Files and Chain Bundling

Once FairSSL has issued the certificate, you will typically receive:

  • Domain Certificate: eksempel_dk.crt
  • Intermediate/CA Bundle: ca-bundle.crt

Nginx requires the primary certificate and the intermediate certificate to be combined into a single file (the full chain). The order is critical – your domain certificate first, followed by the intermediate:

# Create fullchain file (certificate + intermediate)
cat eksempel_dk.crt ca-bundle.crt | sudo tee /etc/nginx/ssl/eksempel.dk/fullchain.crt > /dev/null

# Copy the private key (if not already in place)
sudo cp privkey.key /etc/nginx/ssl/eksempel.dk/privkey.key

# Set correct permissions
sudo chmod 644 /etc/nginx/ssl/eksempel.dk/fullchain.crt
sudo chmod 600 /etc/nginx/ssl/eksempel.dk/privkey.key

Important: Do not include the root certificate in the full chain file. Browsers already have root certificates pre-installed in their trust stores.

Step 3: Configure the Nginx Server Block for HTTPS

Create or edit your server block configuration (typically located in /etc/nginx/sites-available/):

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name www.eksempel.dk eksempel.dk;

    # Certificate and key
    ssl_certificate     /etc/nginx/ssl/eksempel.dk/fullchain.crt;
    ssl_certificate_key /etc/nginx/ssl/eksempel.dk/privkey.key;

    # TLS protocols (TLS 1.2 and 1.3 only)
    ssl_protocols TLSv1.2 TLSv1.3;

    # Cipher suites (modern and secure)
    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;
    ssl_prefer_server_ciphers off;

    # SSL session caching
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 1d;
    ssl_session_tickets off;

    # HSTS (HTTP Strict Transport Security)
    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;

    # Document root and other configuration
    root /var/www/eksempel.dk/public;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

Step 4: HTTP to HTTPS Redirection

Add a separate server block to redirect all incoming HTTP traffic to HTTPS:

server {
    listen 80;
    listen [::]:80;
    server_name www.eksempel.dk eksempel.dk;

    # Redirect all traffic to HTTPS
    return 301 https://$host$request_uri;
}

Step 5: Enable OCSP Stapling

OCSP stapling improves the TLS handshake speed by serving the certificate's validity status directly from your server:

# Add inside the server block (within the SSL configuration):
ssl_stapling on;
ssl_stapling_verify on;

# Point to the intermediate certificate for OCSP verification
ssl_trusted_certificate /etc/nginx/ssl/eksempel.dk/fullchain.crt;

# DNS resolver (use your provider or public resolvers)
resolver 1.1.1.1 8.8.8.8 valid=300s;
resolver_timeout 5s;

Step 6: Testing and Restarting

# Test the Nginx configuration for syntax errors
sudo nginx -t

# Reload the configuration (no downtime)
sudo systemctl reload nginx

# Or full restart
sudo systemctl restart nginx

# Verify Nginx is listening on port 443
sudo ss -tlnp | grep 443

Verify the certificate installation:

# Show certificate info and chain
openssl s_client -connect www.eksempel.dk:443 -servername www.eksempel.dk < /dev/null 2>/dev/null | openssl x509 -noout -subject -dates -issuer

# Test OCSP stapling
openssl s_client -connect www.eksempel.dk:443 -servername www.eksempel.dk -status < /dev/null 2>/dev/null | grep -A 5 "OCSP Response"

# Test with curl
curl -vI https://www.eksempel.dk 2>&1 | grep -E "SSL|TLS|subject|issuer"

You should also use the FairSSL.com SSL scanner or Qualys SSL Labs for a comprehensive online evaluation of your TLS configuration.

Troubleshooting

  • "nginx: [emerg] cannot load certificate": The certificate file is empty, corrupted, or in the wrong format. Ensure fullchain.crt contains valid PEM blocks (beginning with -----BEGIN CERTIFICATE-----).
  • "PEM routines:get_name:no start line": The file contains invalid characters or has incorrect encoding. Ensure the file is saved in UTF-8/ASCII without a BOM.
  • Browser shows "Not Secure": The full chain file is missing the intermediate certificate. Recreate the file using cat cert.crt intermediate.crt > fullchain.crt.
  • OCSP stapling isn't working: It can take a few minutes after a restart for Nginx to fetch the OCSP response. Check with openssl s_client -status. Also, ensure your resolver is correctly configured.
  • ERR_SSL_PROTOCOL_ERROR: Ensure port 443 is open in your firewall (sudo ufw allow 443) and that listen 443 ssl is correctly configured in your server block.
  • Certificate expired: Set a reminder or use monitoring. Check the expiry date with openssl x509 -enddate -noout -in /etc/nginx/ssl/eksempel.dk/fullchain.crt.

Strengthen your TLS security

Use the Mozilla SSL Configuration Generator to generate a secure TLS configuration with modern cipher suites and protocol settings.

Mozilla SSL Configuration Generator guide

Certificates on many servers and appliances

A publicly trusted SSL certificate can be valid for at most 199 days now, 99 days by 15 March 2027 and 46 days by 15 March 2029. Each certificate then has to be replaced at least twice a year now and at least eight times a year from 2029, on every server, firewall and load balancer that uses it. sslbrain from FairSSL runs as an appliance in your own network and renews and installs the certificates from one place, including on devices without an agent.

How sslbrain renews and installs certificates on Nginx(opens sslbrain.com in a new tab)

Ready to create a free account?

Create a free account and order your first certificate. A DV certificate is issued in under 2 minutes.