📖 Guide
Nginx Cheat Sheet — Complete Configuration Reference
Complete Nginx configuration reference covering server blocks, locations, proxying, SSL, load balancing, and caching.
121 commands across 12 categories
Server BlocksLocationsReverse ProxyLoad BalancingSSL / TLSHeaders & SecurityGzip CompressionLoggingRewrites & RedirectsRate LimitingCachingPerformance Tuning
Server Blocks
| Command | Description |
|---|---|
listen 80; | Listen on port 80 (HTTP) |
listen 443 ssl; | Listen on port 443 (HTTPS) |
listen [::]:80; | Listen on port 80 with IPv6 |
listen 80 default_server; | Set as default server for this port |
server_name example.com; | Match requests for this domain |
server_name example.com www.example.com; | Match multiple domains |
server_name *.example.com; | Match all subdomains (wildcard) |
server_name ~^(?<subdomain>.+)\.example\.com$; | Regex server name with capture |
server_name ""; | Match requests with no Host header |
root /var/www/html; | Set document root for the server |
index index.html index.htm; | Set default index files |
Locations
| Command | Description |
|---|---|
location / { ... } | Match all requests (prefix match) |
location /api { ... } | Match requests starting with /api |
location = /health { ... } | Exact match — only /health, not /health/check |
location ~* \.(jpg|png|gif)$ { ... } | Case-insensitive regex match for image files |
location ~ \.php$ { ... } | Case-sensitive regex match for PHP files |
location ^~ /static/ { ... } | Prefix match — skip regex matching |
try_files $uri $uri/ /index.html; | Try file, then directory, then fallback (SPA) |
try_files $uri $uri/ =404; | Return 404 if file not found |
root /var/www/site; | Set document root for this location |
alias /var/www/files/; | Map location to a different directory path |
autoindex on; | Enable directory listing |
Reverse Proxy
| Command | Description |
|---|---|
proxy_pass http://localhost:3000; | Proxy requests to backend server |
proxy_pass http://backend/; | Proxy to upstream group (load balanced) |
proxy_set_header Host $host; | Forward original Host header to backend |
proxy_set_header X-Real-IP $remote_addr; | Forward client's real IP |
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; | Forward chain of proxy IPs |
proxy_set_header X-Forwarded-Proto $scheme; | Forward protocol (http/https) |
proxy_http_version 1.1; | Use HTTP/1.1 for keepalive connections |
proxy_set_header Upgrade $http_upgrade; | Support WebSocket upgrade |
proxy_set_header Connection "upgrade"; | Support WebSocket connection |
proxy_connect_timeout 60s; | Timeout for establishing connection to backend |
proxy_read_timeout 60s; | Timeout for reading response from backend |
proxy_send_timeout 60s; | Timeout for sending request to backend |
proxy_buffering off; | Disable response buffering (streaming) |
proxy_redirect off; | Don't rewrite Location headers from backend |
Load Balancing
| Command | Description |
|---|---|
upstream backend { server 10.0.0.1:8080; server 10.0.0.2:8080; } | Define upstream group (round-robin by default) |
upstream backend { least_conn; server ...; } | Route to server with fewest active connections |
upstream backend { ip_hash; server ...; } | Sticky sessions by client IP |
upstream backend { hash $request_uri; server ...; } | Hash-based routing by URI |
server 10.0.0.1:8080 weight=3; | Weighted load balancing (3x more traffic) |
server 10.0.0.2:8080 backup; | Backup server — used only when others are down |
server 10.0.0.3:8080 down; | Mark server as permanently offline |
server 10.0.0.1:8080 max_fails=3 fail_timeout=30s; | Health check: mark unhealthy after 3 failures |
keepalive 32; | Keep 32 idle connections to upstream servers |
SSL / TLS
| Command | Description |
|---|---|
ssl_certificate /etc/ssl/cert.pem; | Path to SSL certificate |
ssl_certificate_key /etc/ssl/key.pem; | Path to SSL private key |
ssl_protocols TLSv1.2 TLSv1.3; | Allow only TLS 1.2 and 1.3 |
ssl_ciphers HIGH:!aNULL:!MD5; | Set allowed cipher suites |
ssl_prefer_server_ciphers on; | Prefer server's cipher order |
ssl_session_cache shared:SSL:10m; | Enable SSL session caching (10MB) |
ssl_session_timeout 1d; | SSL session timeout (24 hours) |
ssl_stapling on; | Enable OCSP stapling |
ssl_stapling_verify on; | Verify OCSP stapling responses |
ssl_trusted_certificate /etc/ssl/chain.pem; | CA certificate chain for OCSP |
return 301 https://$host$request_uri;e.g. server { listen 80; return 301 https://$host$request_uri; } | Redirect HTTP to HTTPS |
add_header Strict-Transport-Security "max-age=31536000" always; | Enable HSTS (1 year) |
Headers & Security
| Command | Description |
|---|---|
add_header X-Frame-Options DENY; | Prevent clickjacking (no iframes) |
add_header X-Content-Type-Options nosniff; | Prevent MIME type sniffing |
add_header X-XSS-Protection "1; mode=block"; | Enable XSS filter |
add_header Referrer-Policy strict-origin-when-cross-origin; | Control referrer information |
add_header Content-Security-Policy "default-src 'self'"; | Content Security Policy header |
add_header Permissions-Policy "camera=(), microphone=()"; | Restrict browser features |
proxy_hide_header X-Powered-By; | Remove header from proxied response |
server_tokens off; | Hide Nginx version from error pages and headers |
add_header Access-Control-Allow-Origin *; | Allow CORS from all origins |
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS"; | Specify allowed CORS methods |
Gzip Compression
| Command | Description |
|---|---|
gzip on; | Enable gzip compression |
gzip_vary on; | Add Vary: Accept-Encoding header |
gzip_min_length 1024; | Only compress responses larger than 1KB |
gzip_comp_level 5; | Compression level (1-9, 5 is good balance) |
gzip_types text/plain text/css application/json application/javascript; | MIME types to compress |
gzip_proxied any; | Compress proxied responses too |
gzip_disable "msie6"; | Disable gzip for old IE browsers |
Logging
| Command | Description |
|---|---|
access_log /var/log/nginx/access.log; | Set access log path |
error_log /var/log/nginx/error.log warn; | Set error log path and level |
access_log off; | Disable access logging for this context |
log_format main '$remote_addr - $request'; | Define custom log format |
access_log /var/log/nginx/api.log main; | Use custom format for access log |
error_log /var/log/nginx/error.log debug; | Enable debug-level logging |
log_format json escape=json '{"time":"$time_iso8601"}'; | JSON-formatted log output |
Rewrites & Redirects
| Command | Description |
|---|---|
return 301 https://example.com$request_uri; | Permanent redirect (301) |
return 302 /temporary-page; | Temporary redirect (302) |
return 403; | Return forbidden status |
return 200 'OK'; | Return a plain text response |
rewrite ^/old-page$ /new-page permanent; | Rewrite URL with 301 redirect |
rewrite ^/blog/(.*)$ /articles/$1 last; | Rewrite with regex capture group |
rewrite ^/api/v1/(.*)$ /api/v2/$1 break; | Internal rewrite (don't re-process) |
if ($host = 'www.example.com') { return 301 https://example.com$request_uri; } | Redirect www to non-www |
error_page 404 /404.html; | Custom 404 error page |
error_page 500 502 503 504 /50x.html; | Custom server error page |
Rate Limiting
| Command | Description |
|---|---|
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s; | Define rate limit zone (10 req/sec per IP) |
limit_req zone=api; | Apply rate limit to location |
limit_req zone=api burst=20; | Allow burst of 20 extra requests |
limit_req zone=api burst=20 nodelay; | Burst without delaying requests |
limit_req_status 429; | Return 429 Too Many Requests |
limit_conn_zone $binary_remote_addr zone=addr:10m; | Define connection limit zone |
limit_conn addr 10; | Max 10 concurrent connections per IP |
limit_rate 100k; | Limit response bandwidth to 100KB/s |
Caching
| Command | Description |
|---|---|
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=cache:10m max_size=1g; | Define cache storage (10MB keys, 1GB disk) |
proxy_cache cache; | Enable caching in this location |
proxy_cache_valid 200 1h; | Cache 200 responses for 1 hour |
proxy_cache_valid 404 1m; | Cache 404 responses for 1 minute |
proxy_cache_use_stale error timeout; | Serve stale cache on backend errors |
proxy_cache_bypass $http_cache_control; | Bypass cache when Cache-Control header present |
add_header X-Cache-Status $upstream_cache_status; | Add cache hit/miss header for debugging |
expires 30d; | Set browser cache expiry to 30 days |
expires -1; | Disable browser caching |
add_header Cache-Control "public, no-transform"; | Set Cache-Control header |
Performance Tuning
| Command | Description |
|---|---|
worker_processes auto; | Auto-detect CPU cores for workers |
worker_connections 1024; | Max connections per worker process |
multi_accept on; | Accept multiple connections at once |
use epoll; | Use epoll event model (Linux) |
sendfile on; | Enable efficient file serving |
tcp_nopush on; | Send headers and file in one packet |
tcp_nodelay on; | Disable Nagle's algorithm (low latency) |
keepalive_timeout 65; | Keep connections alive for 65 seconds |
keepalive_requests 100; | Max requests per keepalive connection |
client_max_body_size 10m; | Max upload size (10MB) |
client_body_buffer_size 128k; | Buffer size for request body |
open_file_cache max=1000 inactive=20s; | Cache file metadata for faster serving |
📖 Free, searchable command reference. Bookmark this page for quick access.