Skip to main content
Deployment

SSL/TLS Configuration Best Practices

Configure TLS protocol versions, cipher suites, security headers, and HSTS for HTTPS services.

Installing a certificate is only one part of securing HTTPS. Protocol versions, cipher suites, and security headers also need appropriate configuration. This guide explains the main settings to review.

1. TLS Protocol Versions​

1. Protocol Selection​

Recommended baseline:

  • TLS 1.2: Broad compatibility when configured with secure cipher suites
  • TLS 1.3: Improved handshake performance and a streamlined security design

Disable legacy versions:

  • SSL 2.0 and SSL 3.0 have serious known weaknesses.
  • TLS 1.0 and TLS 1.1 are deprecated and disabled by modern browsers.

2. NGINX configuration​

# Allow only TLS 1.2 and TLS 1.3
ssl_protocols TLSv1.2 TLSv1.3;

3. Apache configuration​

# Allow only TLS 1.2 and TLS 1.3
SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1

2. Cipher Suite Configuration​

1. Cipher Suite Selection​

TLS 1.3:

  • TLS 1.3 negotiates a mutually supported cipher suite.
  • Secure library defaults are often suitable; review them for your environment.

TLS 1.2 cipher suites:

  • Prefer ECDHE key exchange for forward secrecy.
  • Use AES-GCM or ChaCha20-Poly1305.
  • Disable weak algorithms such as RC4, DES, and 3DES.

2. NGINX configuration​

# This directive primarily configures TLS 1.2 cipher suites
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; # Allow client cipher preference

3. Apache configuration​

SSLCipherSuite 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
SSLHonorCipherOrder on

3. Perfect Forward Secrecy​

1. Definition​

Forward secrecy protects previously recorded sessions if the server's long-term private key is later compromised. Ephemeral key exchange derives separate session secrets rather than relying solely on that long-term key.

2. Enable Forward Secrecy​

Use ECDHE key exchange:

  • ECDHE, or Elliptic Curve Diffie-Hellman Ephemeral, provides forward secrecy.
  • Enable suitable ECDHE cipher suites for TLS 1.2.

Example configuration:

# Prefer ECDHE cipher suites
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:...';

4. HTTP Strict Transport Security (HSTS)​

1. What Is HSTS?​

HSTS tells browsers to use HTTPS for a host after learning its policy, helping prevent downgrade attacks. Preloading can extend this protection to the first connection.

2. HSTS configuration​

NGINX configuration:

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

Apache configuration:

Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"

Parameters:

  • max-age=31536000: retain the policy for one year, expressed in seconds
  • includeSubDomains: apply the policy to all subdomains
  • preload: signal consent to inclusion in the HSTS preload list

3. HSTS preloading​

Submit to the preload list:

  1. Visit https://hstspreload.org/
  2. Enter your domain
  3. Check that it meets the requirements
  4. Submit the request

5. OCSP Stapling​

1. What Is OCSP Stapling?​

Where supported by the issuing CA, OCSP stapling lets the server include a signed certificate status response in the TLS handshake, reducing separate client OCSP requests and their privacy impact.

2. Configuration​

NGINX configuration:

ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/nginx/ssl/chain.crt;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;

Apache configuration:

SSLUseStapling on
SSLStaplingCache "shmcb:logs/ssl_stapling(32768)"

6. Security Response Headers​

1. Headers to Review​

X-Frame-Options:

  • Helps prevent clickjacking.
  • Values: SAMEORIGIN or DENY

X-Content-Type-Options:

  • Prevents MIME type sniffing.
  • Value: nosniff

X-XSS-Protection:

  • A legacy browser XSS filter header; prefer Content Security Policy for modern applications.
  • Historical value: 1; mode=block; this is not a modern XSS defense.

Content-Security-Policy:

  • Defines a Content Security Policy.
  • Helps mitigate cross-site scripting when configured appropriately.

2. NGINX configuration​

add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Content-Security-Policy "default-src 'self'" always;

3. Apache configuration​

Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
Header always set X-XSS-Protection "1; mode=block"
Header always set Content-Security-Policy "default-src 'self'"

7. TLS Session Settings​

1. Session Caching​

NGINX configuration:

# Configure in the http block to apply to all server blocks
ssl_session_cache shared:SSL:50m;
ssl_session_timeout 1d;
ssl_session_tickets off; # Disable session tickets; assess the resumption tradeoff

Apache configuration:

SSLSessionCache "shmcb:logs/ssl_session_cache(512000)"
SSLSessionCacheTimeout 300

2. Session Timeout​

  • Choose a suitable session lifetime.
  • Balance security and performance.
  • Example range: 1–24 hours, depending on service requirements.

Certificate configuration​

1. Complete Certificate Chains​

Serve the full chain:

  • Use a full-chain file containing intermediate CA certificates
  • Configure the server to send the intermediate chain
  • Check chain completeness regularly

2. Certificate Key Size​

Key size considerations:

  • RSA: At least 2048 bits; larger keys increase computational cost.
  • ECDSA: Common choices include P-256 and P-384, subject to compatibility requirements.

3. Certificate renewal​

  • Renew certificates regularly
  • Use an automatic renewal tool.
  • Monitor expiration dates

9. Complete Configuration Examples​

1. Nginx Configuration​

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

# TLS certificate
ssl_certificate /etc/nginx/ssl/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/privkey.pem;
ssl_trusted_certificate /etc/nginx/ssl/chain.crt;

# TLS protocols
ssl_protocols TLSv1.2 TLSv1.3;

# TLS cipher suites
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;

# TLS sessions
ssl_session_cache shared:SSL:50m;
ssl_session_timeout 1d;
ssl_session_tickets off;

# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;

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

# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;

# Add the remaining site configuration here.
}

2. Apache Configuration​

<VirtualHost *:443>
ServerName example.com
ServerAlias www.example.com

# TLS configuration
SSLEngine on
SSLCertificateFile /etc/apache2/ssl/cert.pem
SSLCertificateKeyFile /etc/apache2/ssl/private.key
SSLCertificateChainFile /etc/apache2/ssl/chain.crt

# TLS protocols
SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1

# TLS cipher suites
SSLCipherSuite 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
SSLHonorCipherOrder on

# OCSP Stapling
SSLUseStapling on
SSLStaplingCache "shmcb:logs/ssl_stapling(32768)"

# HSTS
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"

# Security headers
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
Header always set X-XSS-Protection "1; mode=block"

# Add the remaining site configuration here.
</VirtualHost>

Security testing​

1. SSL Labs Assessment​

Visit https://www.ssllabs.com/ssltest/ and enter your domain to assess the deployed TLS configuration. Review the findings rather than relying on the grade alone.

2. Security Header Checks​

Use an online tool to inspect security response headers:

  • SecurityHeaders.com
  • Mozilla Observatory

3. Regular Reviews​

  • Test the TLS configuration regularly.
  • Review security advisories and software updates.
  • Update the configuration when required.

11. Best Practices Checklist​

1. Protocols and Cryptography​

  • ✅ Use TLS 1.2 or later
  • ✅ Disable insecure protocols and cipher suites
  • ✅ Enable forward secrecy.
  • ✅ Use strong cryptographic algorithms.

2. Security Features​

  • ✅ Enable HSTS
  • ✅ Enable OCSP stapling when supported by the certificate's CA
  • ✅ Configure security response headers
  • ✅ Serve the complete intermediate certificate chain.

3. Performance optimization​

  • ✅ Configure TLS session caching
  • ✅ Enable HTTP/2 where appropriate.
  • ✅ Review cipher suite selection.
  • ✅ Use OCSP stapling where supported to reduce latency

4. Monitoring and Maintenance​

  • ✅ Test the TLS configuration regularly.
  • ✅ Monitor certificate expiration
  • ✅ Review security advisories.
  • ✅ Keep the configuration up to date.

Conclusion​

A secure HTTPS deployment combines suitable TLS versions and cipher suites with correctly configured certificates, response headers, and HSTS. Review these settings as your application and client requirements change.

Key points:

  • ✅ Use TLS 1.2 or later
  • ✅ Enable forward secrecy.
  • ✅ Configure HSTS appropriately.
  • ✅ Enable OCSP stapling when supported by the certificate's CA
  • ✅ Configure security response headers
  • ✅ Test and update regularly.

Security configuration requires ongoing maintenance. CertOne provides certificate management and automatic renewal to support that work.