Last updated: 2026-02-11
Nginx TLS/SSL Configuration Guide
This guide provides recommended TLS/SSL settings for the Nginx web server. These settings are designed to achieve an A+ rating on Qualys SSL Labs while maintaining compatibility with modern clients.
Prerequisites
- Nginx 1.13.0 or later (for TLS 1.3 support)
- OpenSSL 1.1.1 or later
- A valid SSL/TLS certificate from a trusted CA
Protocol Versions
Disable all legacy protocols and allow only TLS 1.2 and TLS 1.3. Older protocols (SSL 2.0, SSL 3.0, TLS 1.0, TLS 1.1) have known vulnerabilities and are deprecated by RFC 8996.
ssl_protocols TLSv1.2 TLSv1.3;
Cipher Suites
Use only AEAD cipher suites with ECDHE key exchange. This ensures forward secrecy and protection against known attacks. All ciphers below use authenticated encryption (GCM or POLY1305), and none rely on CBC mode or static RSA key exchange.
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;
When TLS 1.3 is enabled, set ssl_prefer_server_ciphers to off. TLS 1.3 handles cipher negotiation differently, and all ciphers in the list above are equally strong, so client preference is appropriate:
ssl_prefer_server_ciphers off;
TLS 1.3 cipher suites are configured automatically by OpenSSL and do not need to be specified. If you want to explicitly set them (requires Nginx 1.19.4+):
ssl_conf_command Ciphersuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256;
Note: On RHEL 8 (Nginx 1.14), Debian 11 (Nginx 1.18), and Ubuntu 22.04 (Nginx 1.18), ssl_conf_command is not available. It can safely be omitted since OpenSSL enables all TLS 1.3 ciphers by default.
Certificate Configuration
Point Nginx to your certificate, private key, and the full certificate chain (for OCSP stapling):
ssl_certificate /etc/nginx/ssl/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/privkey.pem;
ssl_trusted_certificate /etc/nginx/ssl/chain.pem;
Session Settings
Configure session caching to improve performance for returning clients, and disable session tickets for forward secrecy:
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
- ssl_session_cache stores TLS session parameters in shared memory, reducing the cost of repeated handshakes.
10mprovides space for roughly 40,000 sessions. - ssl_session_tickets off disables TLS session tickets. Session tickets can undermine forward secrecy because the ticket encryption key is typically static across restarts.
OCSP Stapling
OCSP stapling attaches the certificate's revocation status to the TLS handshake, eliminating the need for clients to contact the CA independently. This improves connection speed and user privacy.
ssl_stapling on;
ssl_stapling_verify on;
resolver 1.1.1.1 1.0.0.1 valid=300s;
resolver_timeout 5s;
HTTP Strict Transport Security (HSTS)
HSTS instructs browsers to only connect over HTTPS for the specified duration. The includeSubDomains flag extends this to all subdomains, and preload allows submission to browser HSTS preload lists.
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
Only enable
includeSubDomainsif all subdomains support HTTPS. Only addpreloadif you intend to submit your domain to the HSTS preload list, as this is difficult to reverse.
HTTPS Redirect
Redirect all HTTP traffic to HTTPS:
server {
listen 80;
server_name example.com;
return 301 https://$host$request_uri;
}
Complete Configuration Example
server {
listen 443 ssl;
server_name example.com;
# Certificates
ssl_certificate /etc/nginx/ssl/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/privkey.pem;
ssl_trusted_certificate /etc/nginx/ssl/chain.pem;
# Protocols and ciphers
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;
ssl_prefer_server_ciphers off;
# Sessions
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 1.1.1.1 1.0.0.1 valid=300s;
resolver_timeout 5s;
# Security headers
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
# ... your site configuration
}
Verification
After applying your configuration, reload Nginx and verify:
nginx -t
systemctl reload nginx
Test your configuration externally using Qualys SSL Labs at https://www.ssllabs.com/ssltest/. The settings above should achieve an A+ rating.
You can also test locally with OpenSSL:
openssl s_client -connect example.com:443 -tls1_2
openssl s_client -connect example.com:443 -tls1_3