Improving your web security and performance starts with a solid foundation. I regularly use external online generators and verification tools to ensure my NGINX configuration meets the highest standards. This guide details my steps to achieve an A+ security rating and optimal performance settings.
1. Preparation and Configuration Structure
Before making any changes, it’s vital to check your core software versions:
root@web:~# dpkg -l | grep nginx-core
ii nginx-core 1.18.0-6.1 amd64 nginx web/proxy server (standard version)
root@web:~# dpkg -l | grep openssl
ii openssl 1.1.1k-1 amd64 Secure Sockets Layer toolkit - cryptographic utilityMy NGINX setup follows the standard Debian structure, utilizing sites-enabled for live configurations and a conf.d directory to store global, reusable configuration snippets. This modularity is a core principle of good configuration management.
2. SSL/TLS Hardening via External Standards
The first step in establishing a robust TLS configuration is to consult the moz://a SSL Configuration Generator. By inputting my NGINX (1.18.0) and OpenSSL (1.1.1k) versions and selecting the Intermediate profile, I get a rock-solid, standards-compliant foundation.
I implement these core settings in the file /etc/nginx/conf.d/ssl.conf.
#
# default ssl configuration. Used the mozilla ssl configurator as template
# See: https://ssl-config.mozilla.org/#server=nginx&version=1.18.0&config=intermediate&openssl=1.1.1k&guideline=5.6
#
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
ssl_session_tickets off;
# intermediate configuration
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;
# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;Forward Secrecy, Cipher Preference, and CAA
To ensure Forward Secrecy and optimal key exchange, I generate a strong 4096-bit Diffie Hellman parameter file and explicitly define the ECDH curve order.
cd /etc/nginx
openssl dhparam -out dhparam.pem 4096
chmod 0600 dhparam.pemI add these parameters to ssl.conf, along with setting server cipher preference.
ssl_dhparam /etc/nginx/dhparam.pem;
ssl_ecdh_curve X25519:secp521r1:secp384r1:prime256v1;
ssl_prefer_server_ciphers on;
# replace with the IP address of your resolver
resolver 127.0.0.1;For an additional layer of security required for the SSL Labs test, I explicitly define which Certificate Authorities (CAs) are allowed to issue certificates for my domains using a CAA (Certification Authority Authorization) DNS record.
root@ns3:~# nsupdate -l
> zone jeanbruenn.info
> update add blog.jeanbruenn.info. 3600 IN CAA 0 issue "letsencrypt.org"
> update add blog.jeanbruenn.info. 3600 IN CAA 0 iodef "mailto:himself@jeanbruenn.info"
> sendHSTS Implementation and HTTP Redirect
To enforce HTTPS consistently and minimize the risk of protocol downgrade attacks, HTTP Strict Transport Security (HSTS) is mandatory. I use NGINX’s map directive to ensure the header is only sent over HTTPS.
# HSTS (ngx_http_headers_module is required) (63072000 seconds)
map $scheme $hsts_header {
https max-age=63072000;
}
add_header Strict-Transport-Security $hsts_header always;Note on includeSubdomains and preload: Adding these arguments requires careful consideration, especially if you have multiple subdomains or domains. I recommend only adding them selectively to the parent domain, as advised by the RFC6797.
To ensure all traffic is automatically encrypted, I globally redirect HTTP (Port 80) to HTTPS (Port 443).
server {
listen 80 default_server;
listen [::]:80 default_server;
location / {
return 301 https://$host$request_uri;
}
}Certificates (RSA and ECDSA)
I have converted my old RSA certificates to modern ECDSA ones using Certbot, which is now the recommended standard for enhanced security and performance.
certbot renew --key-type ecdsa --elliptic-curve secp384r1 --cert-name jeanbruenn.info --force-renewal

3. Advanced Security Headers
Beyond TLS, configuring HTTP security headers is the next layer of defense against web attacks. I consolidate these headers into /etc/nginx/conf.d/headers.conf.
/etc/nginx/conf.d/headers.conf (security headers)
#
# securityheaders
#
# see: https://scotthelme.co.uk/hardening-your-http-response-headers/#x-frame-options
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
# https://infosec.mozilla.org/guidelines/web_security#x-frame-options
add_header X-Frame-Options "SAMEORIGIN" always;
# see: https://scotthelme.co.uk/hardening-your-http-response-headers/#x-content-type-options
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options
add_header X-Content-Type-Options "nosniff" always;
# see: https://scotthelme.co.uk/a-new-security-header-referrer-policy/
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy
add_header Referrer-Policy "no-referrer" always;
# see: https://scotthelme.co.uk/goodbye-feature-policy-and-hello-permissions-policy/
# https://github.com/w3c/webappsec-permissions-policy/blob/main/permissions-policy-explainer.md
# https://github.com/w3c/webappsec-permissions-policy/blob/main/features.md
add_header Permissions-Policy "camera=(), microphone=()" always;
# see: https://scotthelme.co.uk/a-new-security-header-feature-policy/
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Feature-Policy
# For compatibility reasons, including Feature-Policy (the former header for
# Permission-Policy, as well.
add_header Feature-Policy "microphone 'none'" always;
/etc/nginx/conf.d/headers.conf (mozilla observatory)
#
# mozilla observatory
#
# A setting of 0 disables this, and currently the observatory will reduce
# your points if you disable it. However, read the github issue - you want
# it disabled.
# see: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection
# https://github.com/mozilla/http-observatory/issues/432
add_header X-XSS-Protection 0 always;
# see: https://scotthelme.co.uk/content-security-policy-an-introduction/
# https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
# https://developers.google.com/web/fundamentals/security/csp
# you REALLY want to check what this is doing BEFORE using it. 2nd link.
# add_header Content-Security-Policy "frame-ancestors 'none'" always;
4. Performance Tuning
While security is paramount, performance is critical for user experience. I use tools like Google PageSpeed Insights to identify bottlenecks. My initial check flagged the lack of text compression.
I resolved this by adding /etc/nginx/conf.d/compression.conf:
gzip on;
gzip_proxied any;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
gzip_min_length 1400;
gzip_comp_level 3;Tip: A gzip_min_length of 1400 bytes avoids wasting resources on files that benefit little from compression.

Verification and Results
Continuous verification is a key principle in devops. I use external tools as my observability mechanism to validate the configuration changes.
| Tool | Focus | Ranking (My Configuration) |
| Qualys SSL Labs | SSL/TLS Configuration and Vulnerabilities | A+ |
| CryptCheck | Cipher Strength and Key Exchange | A+ |
| securityheaders.com | HTTP Security Headers | A+ |
| Mozilla Observatory | Overall Web Security Score | B+ |
Note: I’d especially recommend the links to Scott Helme’s page—in my opinion, Scott did an excellent job explaining the rationale behind these headers. I also checked Webbkoll—a page I stumbled upon—which, besides complaining about the missing CSP, also displays useful GDPR/DSGVO information. This tool confirmed that disabling X-XSS-Protection (setting it to 0) is the correct secure practice today, even if older checkers complain.
See Also
- Webbkoll. Web Security and Privacy Checker.
https://webbkoll.dataskydd.net/ - Mozilla. SSL Configuration Generator (v5.6).
https://ssl-config.mozilla.org/ - RFC 6797. HTTP Strict Transport Security (HSTS).
https://www.rfc-editor.org/rfc/rfc6797 - Scott Helme. Security Header Deep Dive.
https://scotthelme.co.uk/hardening-your-http-response-headers/ - Qualys SSL Labs. SSL Server Test.
https://www.ssllabs.com/ssltest/ - CryptCheck. TLS Configuration Checker.
https://cryptcheck.fr/ - securityheaders.com Security Headers Checker.
https://securityheaders.com/ - Google. PageSpeed Insights.
https://developers.google.com/speed/pagespeed/insights/