Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

Linux & Mac & Bash Command Dictionary

  1. Home
  2. Linux & Mac & Bash Command Dictionary
  3. Nginx SSL/TLS Configuration

Nginx SSL/TLS Configuration

SSL configuration in Nginx combines multiple directives: specifying the certificate, selecting TLS protocol versions, choosing cipher suites, and adding the HSTS header. Supporting both TLS 1.2 and TLS 1.3 while disabling the older TLS 1.0 and 1.1 is the current security best practice. To achieve an A+ rating on SSL Labs (ssllabs.com/ssltest/), you need to configure HSTS, OCSP stapling, and cipher suites that support Forward Secrecy.

Syntax

# -----------------------------------------------
#  Certificate and private key
# -----------------------------------------------

# ssl_certificate {path to certificate file}
#   → Specifies the path to the server certificate (PEM format)
#   → Use a full-chain certificate that includes intermediate certificates
#   Example: ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;

# ssl_certificate_key {path to private key file}
#   → Specifies the path to the private key (PEM format) corresponding to the certificate
#   Example: ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

# -----------------------------------------------
#  TLS protocol versions
# -----------------------------------------------

# ssl_protocols {protocol name ...}
#   → Specifies the TLS protocol versions to allow
#   → Disable TLSv1.0 and TLSv1.1 due to known vulnerabilities
#   → Supporting both TLSv1.2 and TLSv1.3 is the current best practice
#   Example: ssl_protocols TLSv1.2 TLSv1.3;

# -----------------------------------------------
#  Cipher suites
# -----------------------------------------------

# ssl_ciphers {colon-separated list of cipher suites}
#   → Specifies the cipher suites to allow, separated by colons
#   → Prioritize ECDHE / DHE cipher suites that support Forward Secrecy
#   → Exclude weak ciphers such as RC4, 3DES, NULL, and EXPORT
#   Example: ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;

# ssl_prefer_server_ciphers {on|off}
#   → When set to on, the server's cipher preference takes priority over the client's
#   → This setting is ignored for TLSv1.3
#   Example: ssl_prefer_server_ciphers on;

# -----------------------------------------------
#  HSTS header
# -----------------------------------------------

# add_header Strict-Transport-Security {value} always;
#   → Adds a response header that enforces HTTPS connections
#   → max-age: number of seconds the browser remembers to use HTTPS (31536000 = 1 year)
#   → includeSubDomains: also applies to subdomains
#   → preload: required for registration in the HSTS preload list (Chrome, etc.)
#   Example: add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

# -----------------------------------------------
#  SSL session cache and timeout
# -----------------------------------------------

# ssl_session_cache {type:size}
#   → Specifies the SSL session cache type and size
#   → shared:SSL:10m creates a 10 MB cache shared across all worker processes
#   → Stores approximately 4,000 sessions per MB
#   Example: ssl_session_cache shared:SSL:10m;

# ssl_session_timeout {duration}
#   → Specifies the expiration time for cached SSL sessions
#   → Default is 5 minutes. A value of 10m (10 minutes) is common
#   Example: ssl_session_timeout 10m;

# -----------------------------------------------
#  OCSP stapling
# -----------------------------------------------

# ssl_stapling {on|off}
#   → Enables OCSP stapling
#   → The server pre-fetches certificate revocation information (OCSP response)
#     and delivers it to the client during the TLS handshake
#   → Eliminates the need for the client to query the CA directly, speeding up the connection
#   Example: ssl_stapling on;

# ssl_stapling_verify {on|off}
#   → Enables signature verification of the OCSP response fetched by the server
#   → Use together with ssl_stapling on
#   Example: ssl_stapling_verify on;

# resolver {DNS server IP} valid={cache seconds}
#   → Specifies the DNS server used to resolve the CA's OCSP server for OCSP stapling
#   Example: resolver 8.8.8.8 8.8.4.4 valid=300s;

# -----------------------------------------------
#  DH parameter file (for TLSv1.2)
# -----------------------------------------------

# ssl_dhparam {path to DH parameter file}
#   → Specifies the Diffie-Hellman parameter file used by DHE cipher suites
#   → 2048 bits or more is recommended
#   → Generate: sudo openssl dhparam -out /etc/nginx/dhparam.pem 2048
#   Example: ssl_dhparam /etc/nginx/dhparam.pem;

Directive reference

DirectiveDescription
ssl_certificateSpecifies the path to the server certificate (PEM format). Use a full-chain certificate that includes intermediate certificates.
ssl_certificate_keySpecifies the path to the private key (PEM format) corresponding to the certificate. Set file permissions to 600.
ssl_protocolsSpecifies the TLS protocol versions to allow. Using TLSv1.2 TLSv1.3 is the current best practice.
ssl_ciphersSpecifies the cipher suites to allow, separated by colons. Prioritize ECDHE / DHE cipher suites that support Forward Secrecy.
ssl_prefer_server_ciphersWhen set to on, the server's cipher preference takes priority over the client's. Ignored for TLSv1.3.
add_header Strict-Transport-SecurityAdds the HSTS header to enforce HTTPS connections. Configure using a combination of max-age, includeSubDomains, and preload.
ssl_session_cacheSpecifies the SSL session cache type and size. shared:SSL:10m creates a 10 MB cache shared across all worker processes.
ssl_session_timeoutSpecifies the expiration time for cached SSL sessions. A value of 10m (10 minutes) is common.
ssl_staplingEnables OCSP stapling. The server pre-fetches certificate revocation information and delivers it to the client, speeding up the TLS handshake.
ssl_stapling_verifyEnables signature verification of the OCSP response fetched by the server. Use together with ssl_stapling on.
resolverSpecifies the IP address of the DNS server used to resolve the CA's OCSP server for OCSP stapling.
ssl_dhparamSpecifies the path to the Diffie-Hellman parameter file used by DHE cipher suites. 2048 bits or more is recommended.

Example

/etc/nginx/sites-available/akane-ssl.conf
# -----------------------------------------------
#  HTTP → HTTPS redirect
# -----------------------------------------------
#  Redirects all HTTP requests to akane.example.com
#  to HTTPS with a 301 permanent redirect
# -----------------------------------------------

server {
    listen 80;
    listen [::]:80;
    server_name akane.example.com;

    # Redirect all HTTP requests to HTTPS permanently
    return 301 https://$host$request_uri;
}

# -----------------------------------------------
#  HTTPS server block (TLS 1.2 / 1.3 support)
# -----------------------------------------------

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;
    server_name akane.example.com;

    # -----------------------------------------------
    #  Document root and index files
    # -----------------------------------------------
    root /var/www/akane.example.com/html;
    index index.php index.html;

    # -----------------------------------------------
    #  Certificate and private key
    #  Uses a full-chain certificate obtained with Let's Encrypt
    # -----------------------------------------------
    ssl_certificate /etc/letsencrypt/live/akane.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/akane.example.com/privkey.pem;

    # -----------------------------------------------
    #  TLS protocol versions
    #  TLSv1.0 and TLSv1.1 are disabled due to known vulnerabilities
    # -----------------------------------------------
    ssl_protocols TLSv1.2 TLSv1.3;

    # -----------------------------------------------
    #  Cipher suites
    #  Prioritizes ECDHE / DHE cipher suites for Forward Secrecy
    #  Weak ciphers such as RC4, 3DES, and EXPORT are excluded
    # -----------------------------------------------
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;

    # Server cipher preference takes priority over the client's (ignored for TLSv1.3)
    ssl_prefer_server_ciphers on;

    # -----------------------------------------------
    #  DH parameter file (for DHE cipher suites in TLSv1.2)
    #  Generate: sudo openssl dhparam -out /etc/nginx/dhparam.pem 2048
    # -----------------------------------------------
    ssl_dhparam /etc/nginx/dhparam.pem;

    # -----------------------------------------------
    #  SSL session cache
    #  Allocates a 10 MB session cache shared across all worker processes
    #  Stores approximately 40,000 sessions
    # -----------------------------------------------
    ssl_session_cache   shared:SSL:10m;
    ssl_session_timeout 10m;

    # -----------------------------------------------
    #  OCSP stapling
    #  The server pre-fetches certificate revocation information
    #  and delivers it to the client during the TLS handshake
    # -----------------------------------------------
    ssl_stapling        on;
    ssl_stapling_verify on;
    resolver            8.8.8.8 8.8.4.4 valid=300s;
    resolver_timeout    5s;

    # -----------------------------------------------
    #  Security headers
    # -----------------------------------------------

    # HSTS: enforces HTTPS for 1 year (31,536,000 seconds)
    # includeSubDomains applies this to subdomains as well
    # preload is required for HSTS preload list registration
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

    # Clickjacking protection
    add_header X-Frame-Options "SAMEORIGIN" always;

    # MIME type sniffing protection
    add_header X-Content-Type-Options "nosniff" always;

    # XSS protection (for modern browsers)
    add_header X-XSS-Protection "1; mode=block" always;

    # -----------------------------------------------
    #  PHP-FPM integration
    # -----------------------------------------------
    location ~ \.php$ {
        include        snippets/fastcgi-php.conf;
        fastcgi_pass   unix:/run/php/php8.3-fpm.sock;
        fastcgi_param  HTTPS on;
    }

    # -----------------------------------------------
    #  Let's Encrypt certificate renewal directory
    # -----------------------------------------------
    location ~ /.well-known/acme-challenge/ {
        allow all;
        root /var/www/html;
    }
}

Run the following command:

$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
$ sudo systemctl reload nginx
$ curl -I https://akane.example.com
HTTP/2 200
strict-transport-security: max-age=31536000; includeSubDomains; preload
x-frame-options: SAMEORIGIN
x-content-type-options: nosniff
x-xss-protection: 1; mode=block
Generating the DH parameter file and checking the SSL Labs rating
# -----------------------------------------------
#  Generate the DH parameter file (first time only)
#  Generating 2048 bits may take a few minutes
# -----------------------------------------------

# Generate the parameter file for DHE cipher suites
sudo openssl dhparam -out /etc/nginx/dhparam.pem 2048

# Verify the file was created
ls -lh /etc/nginx/dhparam.pem

# -----------------------------------------------
#  Syntax check and reload
# -----------------------------------------------

# Check the configuration file for syntax errors
sudo nginx -t

# Reload the configuration after a successful syntax check (without dropping connections)
sudo systemctl reload nginx

# -----------------------------------------------
#  Online test with SSL Labs
#  https://www.ssllabs.com/ssltest/analyze.html?d=akane.example.com
#  Visit the URL above to verify an A+ rating
# -----------------------------------------------

# Check TLS connection details using the openssl command
openssl s_client -connect akane.example.com:443 -tls1_2 < /dev/null 2>&1 | grep "Protocol\|Cipher"
openssl s_client -connect akane.example.com:443 -tls1_3 < /dev/null 2>&1 | grep "Protocol\|Cipher"

Run the following command:

$ ls -lh /etc/nginx/dhparam.pem
-rw-r--r-- 1 root root 424 Mar 25 12:00 /etc/nginx/dhparam.pem
$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
$ sudo systemctl reload nginx
$ openssl s_client -connect akane.example.com:443 -tls1_3 < /dev/null 2>&1 | grep "Protocol\|Cipher"
    Protocol : TLSv1.3
    Cipher : TLS_AES_256_GCM_SHA384

Overview

For Nginx SSL configuration, the foundation is to restrict TLS versions with ssl_protocols and allow only secure cipher suites with ssl_ciphers. TLSv1.0 and TLSv1.1 have been deprecated by major browsers since 2018, and the combination of TLSv1.2 TLSv1.3 is now the standard configuration. Adding the HSTS header (Strict-Transport-Security) tells the browser to remember HTTPS for one year, protecting against protocol downgrade attacks. Enabling OCSP stapling removes the need for the client to query the CA directly, which can speed up the TLS handshake and improve privacy. For obtaining certificates, Let's Encrypt / Certbot provides free certificates with automatic renewal. For general Nginx configuration, see Nginx overview. For performance tuning, see Nginx performance settings.

If you find any errors or copyright issues, please .