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.
Related: How to configure Let's Encrypt SSL in Nginx
Related: How to redirect HTTP to HTTPS in Nginx
Related: How to enable HSTS in Nginx
Related: How to configure TLS ciphers in Nginx
Related: How to enable OCSP stapling in Nginx
Nginx security hardening checklist:
- 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.
- 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.
- 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.
- 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 ##### - 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.
- 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.
Related: How to add custom headers in Nginx
- 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.
Related: How to add custom headers in Nginx
- 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.
- 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.
- 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.
- 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.
- 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.
- 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.
- 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.
Related: How to limit request sizes in Nginx
- 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.
- 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.
Related: How to prevent DoS abuse in Nginx
Related: How to block user agents in Nginx - 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.
- Retain security audit logs without exhausting disk space.
Rotation and retention should be verified before enabling more verbose formats or higher error log levels.
Mohd Shakir Zakaria is a cloud architect with deep roots in software development and open-source advocacy. Certified in AWS, Red Hat, VMware, ITIL, and Linux, he specializes in designing and managing robust cloud and on-premises infrastructures.
Comment anonymously. Login not required.
