The Qualys SSL Labs Server Test is the industry-standard benchmark for TLS configuration. An A+ grade signals to auditors, customers, and security teams that your server follows best practices. This guide walks you through every requirement, from protocol selection to HSTS preloading, with exact Nginx and Apache configuration lines.
This article is part of the SSL/TLS Configuration Guide. Use the GF.dev TLS Scanner for quick checks between each step and the Secure Headers Test to verify your HSTS deployment.
SSL Labs evaluates four categories, each scored 0-100:
The four category scores are combined into a letter grade. To reach A, all categories must score well and no critical issues can be present. To reach A+, you must also have HSTS with a max-age of at least six months (15768000 seconds).
TLS 1.0 and 1.1 are deprecated (RFC 8996, 2021). Any server that still enables them will be capped at a B grade on SSL Labs.
# Nginx
ssl_protocols TLSv1.2 TLSv1.3;# Apache
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1This removes SSLv3, TLS 1.0, and TLS 1.1, leaving only TLS 1.2 and TLS 1.3.
Remove all cipher suites that lack forward secrecy or use weak algorithms. See TLS Cipher Suites Ranked for the full reasoning. Here is the recommended list:
# Nginx
ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers on;# Apache
SSLCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256
SSLHonorCipherOrder onSSL Labs requires a minimum 2048-bit RSA key. Certificates with 1024-bit keys will fail entirely. For best results, use a 4096-bit RSA key or an ECDSA P-256/P-384 key. ECDSA keys are smaller and faster to verify while providing equivalent or greater security.
When generating a certificate with Let's Encrypt, you can request ECDSA:
sudo certbot certonly --nginx -d example.com --key-type ecdsa --elliptic-curve secp384r1A common mistake is serving only the leaf certificate without the intermediate CA certificates. Browsers may be able to fill in the gap from their cache, but SSL Labs will flag it, and some clients (especially mobile) will fail to connect.
Ensure your ssl_certificate file contains the full chain: leaf certificate first, then intermediates, but not the root CA (which the client already has in its trust store).
# Verify your chain
openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -text | grep -A1 'Issuer'With Let's Encrypt and Certbot, use the fullchain.pem file (not cert.pem):
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;OCSP stapling improves both performance and privacy by having your server fetch and cache the OCSP response, then include it in the TLS handshake. Without stapling, the client must contact the CA's OCSP responder separately, adding latency and leaking which sites the user visits.
# Nginx
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
resolver 1.1.1.1 8.8.8.8 valid=300s;
resolver_timeout 5s;# Apache
SSLUseStapling on
SSLStaplingResponderTimeout 5
SSLStaplingReturnResponderErrors off
SSLStaplingCache shmcb:/var/run/ocsp(128000)Verify stapling is working:
openssl s_client -connect example.com:443 -status 2>/dev/null | grep -A3 'OCSP Response'This is the step that moves you from A to A+. Add the Strict-Transport-Security header with a max-age of at least 15768000 seconds (six months). For full protection, include includeSubDomains and preload:
# Nginx
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;# Apache
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"The preload directive makes your domain eligible for the HSTS Preload List, which is hardcoded into browsers. Read What is HSTS and How Does It Protect Your Site? for important caveats before submitting to the preload list. Verify your header with the GF.dev HSTS Test.
While not directly scored by SSL Labs, a CAA record prevents unauthorized certificate issuance and is a best practice:
example.com. IN CAA 0 issue "letsencrypt.org"
example.com. IN CAA 0 issuewild "letsencrypt.org"If your cipher suite list includes DHE (non-elliptic Diffie-Hellman) suites, generate custom DH parameters of at least 2048 bits:
openssl dhparam -out /etc/nginx/dhparam.pem 4096# Nginx
ssl_dhparam /etc/nginx/dhparam.pem;If you only use ECDHE suites (which is what we recommend), you do not need DH parameters.
TLS session tickets can leak session keys if the ticket encryption key is compromised. For maximum security, disable them:
# Nginx
ssl_session_tickets off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;This forces the use of server-side session caching, which is more secure but uses slightly more server memory.
After making all changes, reload your server and run through these checks:
nginx -t or apachectl configtestfullchain.pem, not cert.pem.With all nine steps complete, your server will score A+ on SSL Labs. For the full context, return to the SSL/TLS Configuration Guide.