Nginx SSL and Security Configuration

A production Nginx SSL configuration is more than just pointing Nginx at a certificate file. To achieve an A+ rating on SSL Labs and protect against the full range of TLS attacks, you need to configure the protocol versions, cipher suites, session management, OCSP stapling, and security headers correctly. Getting even one of these wrong can leave your site vulnerable to known attacks or achieve a poor security rating that enterprise clients use for vendor security assessments. This example shows a server block configured for modern TLS security. The ssl_protocols TLSv1.2 TLSv1.3 line restricts connections to these two protocol versions. TLSv1.0 and TLSv1.1 are formally deprecated (RFC 8996) and vulnerable to POODLE, BEAST, and SWEET32 attacks — major browsers have already blocked them. ssl_prefer_server_ciphers on ensures the server chooses the cipher suite from its ordered preference list rather than letting clients negotiate potentially weaker options. SSL session management with ssl_session_cache shared:SSL:10m and ssl_session_timeout 10m allows TLS session resumption, where returning clients can skip the full TLS handshake and resume their previous session. This dramatically reduces handshake overhead for repeat visitors and API clients that make many connections. The shared: cache type allows all Nginx worker processes to share the session cache. HSTS (HTTP Strict Transport Security) with max-age=31536000 tells browsers to always connect to this domain over HTTPS for the next year, even if the user types http://. This prevents SSL stripping attacks where an attacker on a shared network intercepts the initial HTTP request before the HTTPS redirect fires. includeSubDomains extends this protection to all subdomains, preventing an attacker from using an insecure subdomain to attack the main domain. X-Content-Type-Options: nosniff and X-Frame-Options: DENY are security headers that protect against MIME sniffing and clickjacking respectively. While these can also be set in the application, setting them at the Nginx layer ensures they apply to all responses including static files and error pages. The location / block uses proxy_pass to forward requests to an application server on localhost:3000. This is the standard reverse proxy pattern where Nginx handles TLS termination, static file serving, and security headers while the application server handles business logic. Tips: run nginx -t to test configuration syntax before reloading with nginx -s reload. Never edit nginx.conf on a production server without first testing the change. Set up a pre-commit hook or CI check that runs nginx -t on any nginx configuration changes before they reach the server.

Example
server {
    listen 443 ssl http2;
    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;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;

    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header X-Content-Type-Options nosniff;
    add_header X-Frame-Options DENY;

    location / {
        proxy_pass http://127.0.0.1:3000;
    }
}
[ open in Nginx Config Formatter → ]

FAQ

What is HSTS and why should I enable it?
HTTP Strict Transport Security tells browsers to always connect over HTTPS for a set duration (max-age). This prevents protocol downgrade attacks and cookie hijacking even if a user manually types http://
What TLS versions should I support?
Support TLSv1.2 and TLSv1.3 only. TLSv1.0 and TLSv1.1 are deprecated and vulnerable to attacks like POODLE and BEAST. Major browsers block sites using old TLS versions.
What is OCSP stapling?
OCSP stapling lets the server pre-fetch and cache the certificate revocation status from the CA, then include it in the TLS handshake. This speeds up connections and improves privacy over standard OCSP requests.

Related Examples