Hardening Nginx reduces the chance that default settings leak version details, expose sensitive locations, or allow abusive traffic to overwhelm upstream applications.

Most security controls in Nginx are applied through configuration directives in /etc/nginx, scoped at the http, server, or location level. TLS negotiation, redirects, request filtering, access controls, and response headers can be tightened without changing application code when the reverse-proxy boundary is owned by Nginx.

Apply changes incrementally and keep a rollback path available, because a single syntax error can prevent a clean reload. Commands below assume a Linux host using systemd and the standard /etc/nginx layout, and risky features like HSTS or over-broad CORS should only be enabled after behavior is verified under real traffic patterns.

Nginx security hardening checklist:

  1. Create a rollback archive of /etc/nginx before applying hardening changes.
    $ sudo tar -C /etc -czf nginx-backup-$(date +%F).tgz nginx

    Store the archive somewhere reachable from console access to support quick rollback.

  2. Test the Nginx configuration for syntax errors.
    $ sudo nginx -t
    nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
    nginx: configuration file /etc/nginx/nginx.conf test is successful

    Fix any errors before reloading, because Nginx rejects invalid directives at startup and reload time.

  3. Reload Nginx to apply changes without terminating established connections.
    $ sudo systemctl reload nginx

    On non-systemd systems, sudo nginx -s reload triggers a reload via the master process.

  4. Confirm the Nginx service is active after the reload.
    $ sudo systemctl status nginx
    ● nginx.service - A high performance web server and a reverse proxy server
         Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
         Active: active (running) since Sun 2025-12-14 09:18:12 UTC; 12s ago
    ##### snipped #####
  5. Disable server_tokens to reduce version disclosure.
    # ///etc/nginx/nginx.conf/// (inside the //http// block) or a specific //server// block
    server_tokens off;

    With server_tokens disabled, the Server header typically becomes nginx without a version string.

  6. Verify response headers do not disclose versions or framework details.
    $ curl -sSI https://example.com/ | grep -Ei '^(server|x-powered-by):'
    server: nginx

    Headers like X-Powered-By are often set by upstream runtimes and can be removed in the proxy/FastCGI layer when needed.

  7. Add baseline browser security headers for common responses.
    server {
        add_header X-Content-Type-Options "nosniff" always;
        add_header X-Frame-Options "SAMEORIGIN" always;
        add_header Referrer-Policy "strict-origin-when-cross-origin" always;
        add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
    }

    Introduce Content-Security-Policy cautiously, because strict policies can break application assets and third-party integrations.

  8. Block access to hidden files and backup artifacts.
    location ~ /\.(?!well-known) {
        deny all;
    }
    
    location ~* \.(?:bak|old|orig|swp|tmp)$ {
        deny all;
    }

    A rule that blocks /.well-known/ can break ACME HTTP-01 challenges and other standards-based discovery paths.

  9. Redirect cleartext HTTP traffic to HTTPS.
    $ curl -I http://example.com
    HTTP/1.1 301 Moved Permanently
    Location: https://example.com/
    ##### snipped #####

    Enable HSTS only after HTTPS and redirects are confirmed stable, because preloaded or long-lived HSTS can strand clients on a broken TLS configuration.

  10. Verify legacy TLS protocol handshakes fail.
    $ openssl s_client -connect example.com:443 -tls1
    CONNECTED(00000003)
    ##### snipped #####
    error:0A00042E:SSL routines:ssl3_read_bytes:tlsv1 alert protocol version

    A successful handshake on tls1 indicates legacy protocols are still enabled.

  11. Verify OCSP stapling is presented for public certificates.
    $ openssl s_client -connect example.com:443 -status < /dev/null
    ##### snipped #####
    OCSP Response Status: successful
    ##### snipped #####

    Absence of an OCSP Response Status section usually indicates stapling is not enabled or cannot be validated for the certificate chain.

  12. Protect sensitive locations with IP allowlists or basic authentication.
    location /admin/ {
        allow 203.0.113.0/24;
        deny all;
        auth_basic "Restricted";
        auth_basic_user_file /etc/nginx/.htpasswd;
    }

    Apply controls only where needed to avoid blocking legitimate clients and automated health checks.

  13. Restrict allowed HTTP methods to the application’s needs.
    $ curl -I -X TRACE https://example.com/
    HTTP/2 405
    ##### snipped #####

    Unexpected 2xx responses on unsafe methods indicate the server accepts them.

  14. Limit request body and header sizes to reduce abuse.
    http {
        client_max_body_size 10m;
        client_body_timeout 10s;
        client_header_timeout 10s;
        large_client_header_buffers 4 16k;
    }

    Align limits with expected upload sizes and client behavior to avoid breaking legitimate requests.

  15. Scope CORS headers to required endpoints with explicit allowed origins.
    location /api/ {
        add_header Access-Control-Allow-Origin "https://app.example.com" always;
        add_header Vary "Origin" always;
    }

    Over-broad CORS rules can expose authenticated endpoints to unintended origins.

  16. Rate limit abusive request patterns.
    http {
        limit_req_zone $binary_remote_addr zone=perip:10m rate=10r/s;
    }
    
    server {
        location /login/ {
            limit_req zone=perip burst=20 nodelay;
        }
    }

    Rate limits should be tested under load to avoid blocking legitimate traffic.

  17. Deploy a web application firewall when deeper request inspection is required.

    Prefer detection or logging-first deployment when available to reduce the chance of accidental outages.

  18. Retain security audit logs without exhausting disk space.

    Rotation and retention should be verified before enabling more verbose formats or higher error log levels.

Discuss the article:

Comment anonymously. Login not required.