← Back to all cheatsheets
DevOps
Nginx DevOps Cheat Sheet
Essential Commands
Service Management
# Start/Stop/Restart
systemctl start nginx
systemctl stop nginx
systemctl restart nginx
systemctl reload nginx # Graceful reload without dropping connections
# Status & Enable
systemctl status nginx
systemctl enable nginx # Enable on boot
systemctl disable nginx
# Alternative commands (older systems)
service nginx start/stop/restart/reload
/etc/init.d/nginx start/stop/restart/reload
Configuration Testing & Reload
nginx -t # Test configuration syntax
nginx -T # Test and dump full configuration
nginx -s reload # Reload configuration
nginx -s quit # Graceful shutdown
nginx -s stop # Fast shutdown
nginx -s reopen # Reopen log files
Process Management
ps aux | grep nginx # View nginx processes
nginx -V # Version and compile options
nginx -v # Version only
lsof -i :80 # Check what's using port 80
netstat -tlpn | grep :80
File Locations
Default Paths
/etc/nginx/ # Main configuration directory
/etc/nginx/nginx.conf # Main configuration file
/etc/nginx/sites-available/ # Available site configurations (Debian/Ubuntu)
/etc/nginx/sites-enabled/ # Enabled site configurations (symlinks)
/etc/nginx/conf.d/ # Additional configuration files (RHEL/CentOS)
/var/log/nginx/ # Log files
/var/www/html/ # Default web root
/usr/share/nginx/html/ # Alternative default web root
Core Configuration Directives
Main Context (nginx.conf)
user www-data; # Worker process user
worker_processes auto; # Number of worker processes
worker_connections 1024; # Max connections per worker
pid /var/run/nginx.pid;
events {
worker_connections 1024;
use epoll; # Connection processing method
multi_accept on;
}
http {
# Basic Settings
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
server_tokens off; # Hide nginx version
# Buffer Settings
client_body_buffer_size 16K;
client_header_buffer_size 1k;
large_client_header_buffers 4 16k;
client_max_body_size 100M; # Max upload size
# Logging
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log warn;
# Gzip Compression
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml text/javascript
application/json application/javascript application/xml+rss;
}
Server Block Examples
Basic HTTP Server
server {
listen 80;
server_name example.com www.example.com;
root /var/www/example.com;
index index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
}
HTTPS with SSL/TLS
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/ssl/certs/example.com.crt;
ssl_certificate_key /etc/ssl/private/example.com.key;
# Modern SSL configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# Security headers
add_header Strict-Transport-Security "max-age=31536000" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
}
HTTP to HTTPS Redirect
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$server_name$request_uri;
}
Reverse Proxy Configuration
Basic Reverse Proxy
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
}
Load Balancing
upstream backend {
least_conn; # or ip_hash, random, etc.
server backend1.example.com weight=3;
server backend2.example.com;
server backend3.example.com down;
server backend4.example.com backup;
}
server {
location / {
proxy_pass http://backend;
}
}
Location Block Patterns
Priority Order (High to Low)
location = /exact { } # Exact match
location ^~ /prefix { } # Prefix match (stops search)
location ~ /regex[0-9] { } # Case-sensitive regex
location ~* /regex[0-9] { } # Case-insensitive regex
location /prefix { } # Prefix match
location / { } # Default
Common Location Examples
# Static files with caching
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 30d;
add_header Cache-Control "public, immutable";
}
# PHP-FPM
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
# Deny access to hidden files
location ~ /\. {
deny all;
}
# WebSocket support
location /ws/ {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
Rate Limiting & Security
Rate Limiting
http {
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
limit_conn_zone $binary_remote_addr zone=addr:10m;
server {
location /api/ {
limit_req zone=one burst=5 nodelay;
limit_conn addr 10;
}
}
}
Basic Authentication
location /admin {
auth_basic "Admin Area";
auth_basic_user_file /etc/nginx/.htpasswd;
}
IP Whitelisting/Blacklisting
location /admin {
allow 192.168.1.0/24;
allow 10.0.0.0/8;
deny all;
}
Caching
Proxy Cache
http {
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m
max_size=10g inactive=60m use_temp_path=off;
server {
location / {
proxy_cache my_cache;
proxy_cache_valid 200 302 60m;
proxy_cache_valid 404 1m;
proxy_cache_use_stale error timeout invalid_header updating;
add_header X-Cache-Status $upstream_cache_status;
}
}
}
Useful Variables
$host # Host header value
$remote_addr # Client IP address
$request_method # GET, POST, etc.
$request_uri # Full original request URI
$uri # Current URI
$args # Query string
$scheme # http or https
$server_name # Server name
$server_port # Server port
$http_user_agent # User agent string
$http_referer # Referrer
$upstream_addr # Upstream server address
$upstream_response_time # Upstream response time
$request_time # Total request processing time
Logging
Custom Log Format
http {
log_format custom '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'rt=$request_time uct="$upstream_connect_time" '
'uht="$upstream_header_time" urt="$upstream_response_time"';
access_log /var/log/nginx/access.log custom;
}
Conditional Logging
map $request_uri $loggable {
~*\.(jpg|jpeg|png|gif|ico|css|js)$ 0;
default 1;
}
access_log /var/log/nginx/access.log combined if=$loggable;
Performance Tuning
Key Optimizations
# File descriptors
worker_rlimit_nofile 65535;
# Events block
events {
worker_connections 4096;
use epoll;
multi_accept on;
}
http {
# Connection settings
keepalive_timeout 65;
keepalive_requests 100;
# Buffer optimizations
client_body_buffer_size 128k;
large_client_header_buffers 4 16k;
# File cache
open_file_cache max=1000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
# Gzip
gzip on;
gzip_comp_level 5;
gzip_min_length 256;
gzip_proxied any;
gzip_vary on;
}
Troubleshooting Commands
# Check syntax errors
nginx -t
# View error logs
tail -f /var/log/nginx/error.log
# View access logs
tail -f /var/log/nginx/access.log
# Test specific configuration file
nginx -t -c /etc/nginx/nginx.conf
# Check listening ports
ss -tlnp | grep nginx
netstat -tlnp | grep nginx
# Check nginx processes
ps aux | grep nginx
# Test upstream connectivity
curl -I http://backend-server:port
# Check disk space for logs
df -h /var/log
# Rotate logs manually
nginx -s reopen
# Check current connections
ss -ant | grep :80 | wc -l
# Monitor nginx status (requires stub_status module)
curl http://localhost/nginx_status
Docker/Kubernetes Integration
Docker Example
FROM nginx:alpine
COPY nginx.conf /etc/nginx/nginx.conf
COPY site.conf /etc/nginx/conf.d/default.conf
EXPOSE 80 443
Kubernetes ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-config
data:
nginx.conf: |
events { }
http {
server {
listen 80;
location / {
proxy_pass http://backend-service:3000;
}
}
}
Common Issues & Solutions
| Issue | Solution |
|---|---|
| 502 Bad Gateway | Check upstream server status, firewall rules, SELinux |
| 504 Gateway Timeout | Increase proxy_read_timeout, check upstream response time |
| 413 Request Entity Too Large | Increase client_max_body_size |
| Too many open files | Increase worker_rlimit_nofile and system limits |
| Permission denied | Check file ownership, SELinux contexts |
| Address already in use | Check for other processes on port (lsof -i :80) |
Quick Tips
- Always test configuration before reload:
nginx -t - Use
nginx -Tto view the full resolved configuration - Enable gzip compression for text-based content
- Set up proper logging and log rotation
- Use
try_filesdirective instead ofifwhen possible - Implement rate limiting for API endpoints
- Keep Nginx and modules updated
- Monitor access and error logs regularly
- Use configuration management tools for consistency across servers