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 — but not for Let's Encrypt Important
Stapling improves TLS handshake performance and privacy, but only when the certificate actually carries an OCSP URL. Let's Encrypt shut its OCSP responders down on 2025-08-06, so for a certbot certificate these directives are dead config — leave them out. Where stapling still applies, use a local resolver: an external one is a DNS-poisoning risk that Gixy rates HIGH. See the SSL/TLS guide.
# Commercial CA that still runs an OCSP responder
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/ssl/certs/example.com.chain.pem;
resolver 127.0.0.1 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
# RPM alternative with ReDoctor-backed deep analysis
sudo dnf install https://extras.getpagespeed.com/release-latest.rpm
sudo dnf install gixy-deep
gixy --deep /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 / {
# ...
}
}