NGINX SSL/TLS Best Practices

Configure modern, secure HTTPS with TLS 1.3, strong cipher suites, and proper certificate handling in NGINX.

Updated: January 2025 * 12 min read

Why TLS Configuration Matters

A weak TLS configuration can expose your users to serious attacks even when using HTTPS. Outdated protocols and cipher suites allow:

  • BEAST, POODLE, CRIME - Attacks on TLS 1.0 and older protocols
  • DROWN - Attack exploiting SSLv2 support
  • Logjam - Weak Diffie-Hellman parameters
  • Sweet32 - Birthday attacks on 64-bit block ciphers
  • Man-in-the-Middle - Decryption of traffic using weak ciphers

Protocol Version Guide

Protocol Status Recommendation
SSLv2 Broken Never enable - DROWN attack
SSLv3 Broken Never enable - POODLE attack
TLS 1.0 Deprecated Disable - BEAST, multiple vulnerabilities
TLS 1.1 Deprecated Disable - No longer considered secure
TLS 1.2 Secure Enable with strong ciphers only
TLS 1.3 Recommended Enable - Fastest and most secure

Modern Secure Configuration

Here's a production-ready TLS configuration for 2025:

# Modern TLS configuration (2025)
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:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;

# Session handling
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 8.8.8.8 valid=300s;
resolver_timeout 5s;

TLS 1.3 Only (Maximum Security)

If you can drop TLS 1.2 support (most modern clients support 1.3):

# TLS 1.3 only - maximum security
ssl_protocols TLSv1.3;
ssl_prefer_server_ciphers off;

# TLS 1.3 has built-in secure ciphers
# No need to specify ssl_ciphers
TLS 1.3 Benefits: Faster handshakes (1-RTT, 0-RTT resumption), forward secrecy by default, no legacy cipher support, and simpler configuration.

Insecure Patterns to Avoid

Outdated Protocols

# NEVER use these protocols
ssl_protocols SSLv2 SSLv3 TLSv1 TLSv1.1;

# These are vulnerable to POODLE, BEAST, and other attacks

Weak Cipher Suites

# NEVER use these ciphers
ssl_ciphers RC4:DES:3DES:MD5:EXPORT:NULL:ADH;

# RC4 - Broken stream cipher
# DES/3DES - Weak block ciphers (Sweet32)
# MD5 - Broken hash function
# EXPORT - Intentionally weak ciphers
# NULL - No encryption!
# ADH - No authentication

Certificate Configuration

server {
    listen 443 ssl http2;
    server_name example.com;

    # Certificate and private key
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    # Trusted CA certificates for OCSP stapling
    ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;

    # Diffie-Hellman parameters (for TLS 1.2)
    ssl_dhparam /etc/nginx/dhparam.pem;

    # ... rest of configuration
}

Generate Strong DH Parameters

# Generate 4096-bit DH parameters (recommended)
openssl dhparam -out /etc/nginx/dhparam.pem 4096

# This takes several minutes but only needs to be done once

DH Parameter Warning

Weak or default DH parameters make your server vulnerable to the Logjam attack. Always generate your own 2048-bit or larger parameters.

OCSP Stapling

OCSP Stapling improves performance and privacy by having your server fetch certificate revocation status instead of the client.

# Enable OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;

# Trusted CA for OCSP verification
ssl_trusted_certificate /path/to/chain.pem;

# DNS resolver for OCSP responder
resolver 1.1.1.1 8.8.8.8 valid=300s;
resolver_timeout 5s;

HTTP/2 and HTTP/3

# Enable HTTP/2
listen 443 ssl http2;

# Enable HTTP/3 (QUIC) - NGINX 1.25+
listen 443 quic reuseport;
listen 443 ssl;

# Advertise HTTP/3 support
add_header Alt-Svc 'h3=":443"; ma=86400';

Complete Server Block Example

server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://example.com$request_uri;
}

server {
    listen 443 ssl http2;
    server_name example.com;

    # Certificates
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/example.com/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:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;

    # DH parameters
    ssl_dhparam /etc/nginx/dhparam.pem;

    # Session handling
    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 8.8.8.8 valid=300s;

    # Security headers
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

    root /var/www/example.com;
    index index.html;
}

Detecting Issues with Gixy

Gixy automatically detects weak SSL/TLS configurations:

$ gixy /etc/nginx/nginx.conf

==================== Results ====================

[weak_ssl_tls] Weak SSL/TLS configuration detected.
  Severity: HIGH
  Description: Outdated TLS protocols (TLSv1.0, TLSv1.1) or weak
               cipher suites expose your server to attacks.
  Reason: Protocol TLSv1 is deprecated and vulnerable.
  File: /etc/nginx/conf.d/ssl.conf
  Line: 5

==================== Summary ====================
Total issues: 1 (High: 1)

Testing Your Configuration

# Test with OpenSSL
openssl s_client -connect example.com:443 -tls1_3

# Check supported protocols
nmap --script ssl-enum-ciphers -p 443 example.com

# Online testing tools:
# - ssllabs.com/ssltest/
# - testssl.sh

SSL/TLS Checklist

  • Disable SSLv2, SSLv3, TLS 1.0, and TLS 1.1
  • Enable TLS 1.2 and TLS 1.3
  • Use only AEAD cipher suites (GCM, ChaCha20-Poly1305)
  • Generate 4096-bit DH parameters
  • Enable OCSP Stapling
  • Configure HSTS header
  • Set up automatic certificate renewal
  • Test with SSL Labs (aim for A+ grade)

Further Reading