Quick Navigation
1. Information Disclosure
Prevent attackers from fingerprinting your server.
Hide NGINX version Critical
Prevents attackers from targeting version-specific vulnerabilities.
# In http block
server_tokens off;
Remove Server header entirely Recommended
Requires the headers-more module or NGINX Plus.
# With headers-more-nginx-module
more_clear_headers Server;
Disable autoindex Important
Prevents directory listing that could expose sensitive files.
autoindex off;
2. TLS/SSL Configuration
Modern TLS settings for maximum security.
Use TLS 1.2 and 1.3 only Critical
TLS 1.0 and 1.1 have known vulnerabilities and are deprecated.
ssl_protocols TLSv1.2 TLSv1.3;
Configure modern cipher suites Critical
Use strong ciphers and prefer server's cipher order.
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;
ssl_prefer_server_ciphers off; # Let client choose for TLS 1.3
Enable OCSP stapling Important
Improves TLS handshake performance and privacy.
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /path/to/chain.pem;
resolver 1.1.1.1 8.8.8.8 valid=300s;
resolver_timeout 5s;
Configure session caching Recommended
Improves performance for returning visitors.
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off; # Disable for forward secrecy
3. Security Headers
HTTP headers that protect against common attacks.
Enable HSTS Critical
Forces HTTPS and prevents downgrade attacks.
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
Prevent clickjacking Critical
Blocks your site from being embedded in iframes.
add_header X-Frame-Options "SAMEORIGIN" always;
Prevent MIME sniffing Important
Forces browsers to respect declared content types.
add_header X-Content-Type-Options "nosniff" always;
Configure Content-Security-Policy Important
Controls which resources can be loaded. Start permissive, then tighten.
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self'; frame-ancestors 'self';" always;
Control referrer information Recommended
Limits what referrer info is sent to other sites.
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
Disable dangerous features Recommended
Restricts access to browser features you don't need.
add_header Permissions-Policy "accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=()" always;
4. Access Control
Limit what requests are allowed.
Limit request body size Important
Prevents large uploads that could exhaust resources.
client_max_body_size 10m; # Adjust based on your needs
Restrict HTTP methods Recommended
Only allow methods your application needs.
if ($request_method !~ ^(GET|HEAD|POST)$) {
return 405;
}
Block sensitive files Critical
Prevent access to configuration and hidden files.
# Block hidden files
location ~ /\. {
deny all;
return 404;
}
# Block common sensitive files
location ~* (\.git|\.env|\.htaccess|\.htpasswd|web\.config)$ {
deny all;
return 404;
}
Protect admin areas Important
Restrict access to admin panels by IP or authentication.
location /admin/ {
allow 10.0.0.0/8;
allow 192.168.0.0/16;
deny all;
# Or use basic auth
# auth_basic "Admin Area";
# auth_basic_user_file /etc/nginx/.htpasswd;
}
5. Rate Limiting
Protect against abuse and DDoS.
Configure request rate limiting Important
Limit requests per second from each client.
# In http block
limit_req_zone $binary_remote_addr zone=req_limit:10m rate=10r/s;
# In server/location
limit_req zone=req_limit burst=20 nodelay;
limit_req_status 429;
Limit concurrent connections Recommended
Prevent a single IP from opening too many connections.
# In http block
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
# In server/location
limit_conn conn_limit 20;
limit_conn_status 429;
6. Logging & Monitoring
Visibility into what's happening on your server.
Enable access logging Critical
Log all requests for security analysis.
access_log /var/log/nginx/access.log combined buffer=512k flush=1m;
Enable error logging Critical
Capture errors for debugging and security monitoring.
error_log /var/log/nginx/error.log warn;
Log security-relevant headers Recommended
Include useful info in access logs.
log_format security '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'"$http_x_forwarded_for" $request_time';
access_log /var/log/nginx/security.log security;
7. Miscellaneous
Set proper timeouts Recommended
Prevent slowloris attacks and resource exhaustion.
client_body_timeout 10s;
client_header_timeout 10s;
keepalive_timeout 65s;
send_timeout 10s;
Limit buffer sizes Recommended
Prevent buffer overflow attacks.
client_body_buffer_size 16k;
client_header_buffer_size 1k;
large_client_header_buffers 4 8k;
Run Gixy regularly Critical
Automate security scanning in your CI/CD pipeline.
# Install and run
pip install gixy-ng
gixy /etc/nginx/nginx.conf
Complete Example Configuration
Here's a minimal secure server block incorporating all critical items:
server {
listen 443 ssl http2;
server_name example.com;
# TLS
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
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;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
# Security headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# Hide version
server_tokens off;
# Limits
client_max_body_size 10m;
# Block hidden files
location ~ /\. {
deny all;
return 404;
}
# Your application
location / {
# ...
}
}