Nginx security cheatsheet.
Standard headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header X-Frame-Options "DENY" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
add_header X-XSS-Protection "0" always; # disable legacy filter
always ensures headers on error responses too.
CSP
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'nonce-$request_id'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self' https://api.example.com; frame-ancestors 'none'" always;
Tighten over time. Start with report-only:
add_header Content-Security-Policy-Report-Only "default-src 'self'; report-uri /csp-report" always;
CORS
location /api/ {
if ($request_method = OPTIONS) {
add_header Access-Control-Allow-Origin "https://app.example.com" always;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE";
add_header Access-Control-Allow-Headers "Content-Type, Authorization";
add_header Access-Control-Max-Age 86400;
return 204;
}
add_header Access-Control-Allow-Origin "https://app.example.com" always;
proxy_pass http://app;
}
Avoid * for credentialed requests.
Hide nginx version
server_tokens off;
Hotlink protection
location ~ \.(jpg|png|gif|webp)$ {
valid_referers none blocked example.com *.example.com;
if ($invalid_referer) {
return 403;
}
}
Deny directories
location ~ /\.(?!well-known) {
deny all;
access_log off;
log_not_found off;
}
Blocks .git, .env, .htaccess etc. Allows .well-known/.
Limit methods
location /api/ {
if ($request_method !~ ^(GET|POST|PUT|DELETE|OPTIONS)$) {
return 405;
}
}
Request size
client_max_body_size 10m;
client_body_buffer_size 16k;
client_header_buffer_size 1k;
large_client_header_buffers 4 8k;
Slowloris protection
client_body_timeout 10s;
client_header_timeout 10s;
keepalive_timeout 65 60;
send_timeout 10s;
IP allowlist / denylist
location /admin/ {
allow 10.0.0.0/8;
allow 192.168.1.100;
deny all;
}
Basic auth
location /admin/ {
auth_basic "Admin";
auth_basic_user_file /etc/nginx/.htpasswd;
}
htpasswd -c /etc/nginx/.htpasswd admin
auth_request
location /private/ {
auth_request /auth;
error_page 401 = @login;
proxy_pass http://app;
}
location = /auth {
internal;
proxy_pass http://auth-service/verify;
proxy_set_header X-Original-URI $request_uri;
}
Delegate auth to a service.
Geo-blocking
geo $bad_country {
default 0;
CN 1;
RU 1;
}
server {
if ($bad_country) { return 403; }
}
Requires GeoIP2 module.
ModSecurity / Coraza WAF
Modules add WAF capability:
load_module modules/ngx_http_modsecurity_module.so;
http {
modsecurity on;
modsecurity_rules_file /etc/nginx/modsec/main.conf;
}
OWASP Core Rule Set.
Bot detection (basic)
map $http_user_agent $is_bot {
default 0;
~*(bot|crawl|spider|wget|curl) 1;
}
# Apply different rate limit
Block known bad UAs
if ($http_user_agent ~* "(zmeu|libwww-perl|nikto)") {
return 444;
}
444: nginx-specific, closes connection without response.
Disable trace methods
if ($request_method ~ "(TRACE|DELETE)") {
return 405;
}
SSL session abuse
ssl_session_tickets off;
Reduces TLS session resumption fingerprinting.
File extension block
location ~ \.(env|git|sql|bak|backup|swp|orig|inc|log)$ {
deny all;
log_not_found off;
}
proxy_buffering on (limits attack)
Default. Buffers full response before forwarding; reduces slowloris.
Robots / spider control
location = /robots.txt {
alias /var/www/robots.txt;
log_not_found off;
access_log off;
}
Common mistakes
add_headerwithoutalways→ missing on error responses.add_headerinifblock — inherits weirdly.- CSP
unsafe-inlineeverywhere — defeats purpose. server_tokenson → version disclosed.- Allowing TRACE / OPTIONS without need.
Read this next
If you want my security headers snippet bundle, it’s at rajpoot.dev .
Building something AI-, backend-, or data-heavy and want a second pair of eyes? I do consulting and freelance work — see my projects and ways to reach me at rajpoot.dev .