← News
/PLAYBOOK · 2026-07-25

Nginx Security Headers Config: Comprehensive Site Hardening

Nginx HTTP security response headers: CSP, HSTS, X-Frame-Options and 7 core policies. Full config plus online checks. One-stop HTTPS hardening.

Scope

For Nginx web-server admins and security ops. Blog, corporate site, or shop: HTTP security headers (security response headers) cut XSS, clickjacking, MIME sniffing, and MITM. Apply on reverse proxy, load balancer, or standalone Nginx.

Prerequisites

How it works

HTTP security headers are response directives. The browser tightens policy on receipt.

Steps

Step 1: Locate Nginx config

Confirm config paths:

`# Locate the main configuration file
sudo nginx -t 2>&1 | grep "test failed" || sudo nginx -t 2>&1
# Typical paths
ls /etc/nginx/nginx.conf
ls /etc/nginx/conf.d/
ls /etc/nginx/sites-available/`

Step 2: Add security headers in the server block

Edit the site conf (e.g. /etc/nginx/sites-available/site.conf). Inside server, outside location:

`server {
    listen 443 ssl http2;
    server_name helixcyber.ai;

    # ===== HTTP security headers config start =====

    # HSTS: force HTTPS, 1-year max-age, include subdomains
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

    # Forbid embedding in iframe (clickjacking defense)
    add_header X-Frame-Options "SAMEORIGIN" always;

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

    # Enable XSS filter (deprecated in modern browsers; retained for legacy compatibility)
    add_header X-XSS-Protection "1; mode=block" always;

    # Content-Security-Policy: same-origin resources + trusted CDN only
    add_header Content-Security-Policy "
        default-src 'self';
        script-src 'self' 'unsafe-inline' https://www.googletagmanager.com;
        style-src 'self' 'unsafe-inline';
        img-src 'self' data: https:;
        font-src 'self';
        connect-src 'self';
        frame-ancestors 'self';
        form-action 'self';
    " always;

    # Control Referer information
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;

    # Permissions-Policy: disable non-essential APIs
    add_header Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=()" always;

    # ===== Security headers config end =====

    # Existing config continues...
    location / {
        proxy_pass http://127.0.0.1:8080;
        # ...
    }
}`

Step 3: Syntax-check and reload Nginx

`# Check syntax
sudo nginx -t

# Reload if syntax is valid
sudo systemctl reload nginx
# or
sudo nginx -s reload`

Step 4: Verify headers with curl

`# Inspect response headers
curl -sI https://helixcyber.ai | grep -iE "^(strict-transport|content-security|x-frame|x-content|x-xss|referrer|permissions-policy)"

# Expected example:
# strict-transport-security: max-age=31536000; includeSubDomains; preload
# content-security-policy: default-src 'self'; script-src 'self' ...
# x-frame-options: SAMEORIGIN
# x-content-type-options: nosniff
# referrer-policy: strict-origin-when-cross-origin`

Step 5: Online scan

Scan the domain with Mozilla Observatory (https://observatory.mozilla.org/). Score plus remediations. A+ is best.

Verification

After the steps, check:

FAQ

Q1: Styles or JS break after CSP?

Policy too tight. F12 → Console. Read CSP violations. Whitelist the origin on the matching directive. Google Analytics needs script-src 'self' https://www.googletagmanager.com. Use Content-Security-Policy-Report-Only first; enforce after clean.

Q2: HTTP dead after HSTS?

HSTS forces HTTPS. Keep HTTP→HTTPS 301: (1) listen on 80; (2) HTTP server block has return 301 https://$host$request_uri;. Rollback: chrome://net-internals/#hsts — query and delete the domain pin. Drop server HSTS max-age (e.g. 300s) and reload.

Summary

Nginx HTTP security headers are a server-side control plane. Seven headers (HSTS, X-Frame-Options, X-Content-Type-Options, CSP, Referrer-Policy, Permissions-Policy, X-XSS-Protection) cover transport crypto through content isolation. Ship the conf in CI/CD. Rescan with Mozilla Observatory so the baseline does not regress.