NGINX: Complete Guide
A comprehensive guide to NGINX as a web server, reverse proxy, and load balancer.
What is NGINX?
NGINX is a high-performance HTTP server and reverse proxy, as well as an IMAP/POP3 proxy server.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β NGINX Capabilities β
ββββββββββββββββ¬βββββββββββββββ¬βββββββββββββββ¬ββββββββββββββββ€
β Web Server βReverse Proxy βLoad Balancer β API Gateway β
ββββββββββββββββΌβββββββββββββββΌβββββββββββββββΌββββββββββββββββ€
βStatic files βHide backends βRound Robin βRate limiting β
βDynamic proxy βSSL terminationβLeast Conn βAuth header β
βCompression βCaching βIP Hash βRequest routingβ
ββββββββββββββββ΄βββββββββββββββ΄βββββββββββββββ΄ββββββββββββββββ
Core Architecture
Event-Driven Model
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β NGINX Architecture β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β βββββββββββββββββββ β
β β Master Process β Configuration, Workers management β
β ββββββββββ¬βββββββββ β
β β β
β ββββββββββΌβββββββββ¬βββββββββββββ¬βββββββββββββ β
β βΌ βΌ βΌ βΌ βΌ β
β Worker Worker Worker Worker Worker β
β Process Process Process Process Process β
β β
β Each worker handles thousands of connections β
β (event-driven, non-blocking I/O) β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Why Event-Driven?
| Model | Apache (Thread-based) | NGINX (Event-based) |
|---|---|---|
| Memory | ~2MB per connection | ~256 bytes per connection |
| Connections | Thousands | Millions |
| CPU Usage | High context switching | Low, efficient |
| Concurrency | Limited by threads | Limited by open files |
Basic Configuration
Structure
# Main context
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
events {
worker_connections 1024;
use epoll; # Linux
}
http {
include /etc/nginx/mime.types;
server {
listen 80;
server_name example.com;
location / {
root /var/www/html;
index index.html;
}
}
}
Server Block (Virtual Host)
server {
listen 80;
listen [::]:80;
server_name api.example.com;
# Redirect HTTP to HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name api.example.com;
ssl_certificate /etc/ssl/certs/example.crt;
ssl_certificate_key /etc/ssl/private/example.key;
location / {
proxy_pass http://backend;
}
}
Reverse Proxy Configuration
Basic Reverse Proxy
server {
listen 80;
server_name app.example.com;
location / {
proxy_pass http://localhost:5000;
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;
}
}
ASP.NET Core Configuration
upstream dotnet_backend {
server localhost:5000;
server localhost:5001;
keepalive 32;
}
server {
listen 443 ssl http2;
server_name api.example.com;
ssl_certificate /etc/ssl/certs/api.crt;
ssl_certificate_key /etc/ssl/private/api.key;
location / {
proxy_pass http://dotnet_backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
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;
# Timeouts
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
location /health {
proxy_pass http://dotnet_backend/health;
access_log off;
}
}
Load Balancing
Algorithms
# 1. Round Robin (default)
upstream backend {
server backend1.example.com;
server backend2.example.com;
server backend3.example.com;
}
# 2. Least Connections
upstream backend {
least_conn;
server backend1.example.com;
server backend2.example.com;
server backend3.example.com;
}
# 3. IP Hash (Session Persistence)
upstream backend {
ip_hash;
server backend1.example.com;
server backend2.example.com;
server backend3.example.com;
}
# 4. Weighted
upstream backend {
server backend1.example.com weight=5;
server backend2.example.com weight=3;
server backend3.example.com weight=2;
}
# 5. Health Checks (NGINX Plus)
upstream backend {
zone backend 64k;
server backend1.example.com;
server backend2.example.com;
health_check interval=5s fails=3 passes=2;
}
Load Balancing Visualization
βββββββββββββββββββ
β Client β
ββββββββββ¬βββββββββ
β
ββββββββββΌβββββββββ
β NGINX β
β Load Balancer β
ββββββββββ¬βββββββββ
β
ββββββββββββββββββββββΌβββββββββββββββββββββ
β β β
ββββββΌβββββ ββββββΌβββββ ββββββΌβββββ
βServer 1 β βServer 2 β βServer 3 β
β(weight=5)β β(weight=3)β β(weight=2)β
βββββββββββ βββββββββββ βββββββββββ
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 /api/ {
proxy_cache my_cache;
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504;
proxy_cache_lock on;
add_header X-Cache-Status $upstream_cache_status;
proxy_pass http://backend;
}
}
}
Cache Status Headers
MISS - Response from backend, not cached
HIT - Response from cache
EXPIRED - Cache expired, fetched from backend
STALE - Stale cache served (backend error)
BYPASS - Cache bypassed per configuration
Security Configuration
SSL/TLS Best Practices
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
# HSTS
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
Rate Limiting
http {
# Define rate limit zones
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=login_limit:10m rate=1r/s;
server {
location /api/ {
limit_req zone=api_limit burst=20 nodelay;
proxy_pass http://backend;
}
location /login {
limit_req zone=login_limit burst=5;
proxy_pass http://backend;
}
}
}
Security Headers
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Content-Security-Policy "default-src 'self';" always;
Performance Optimization
Gzip Compression
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml application/json application/javascript
application/xml application/xml+rss text/javascript application/x-javascript;
gzip_min_length 256;
Static File Optimization
location ~* \.(jpg|jpeg|png|gif|ico|css|js|pdf|woff2?)$ {
expires 30d;
add_header Cache-Control "public, immutable";
access_log off;
}
# Serve pre-compressed files
gzip_static on;
Connection Optimization
# Keep-alive connections
keepalive_timeout 65;
keepalive_requests 100;
# Buffer sizes
client_body_buffer_size 128k;
client_max_body_size 10m;
proxy_buffers 16 16k;
proxy_buffer_size 16k;
Common Configurations
SPA (Single Page Application)
server {
listen 80;
server_name app.example.com;
root /var/www/app;
location / {
try_files $uri $uri/ /index.html;
}
location /api/ {
proxy_pass http://backend:5000;
}
}
WebSocket Support
location /ws/ {
proxy_pass http://websocket_backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400;
}
Microservices Routing
server {
listen 443 ssl http2;
server_name api.example.com;
location /users/ {
proxy_pass http://user-service:5000/;
}
location /orders/ {
proxy_pass http://order-service:5001/;
}
location /products/ {
proxy_pass http://product-service:5002/;
}
}
Docker Configuration
Dockerfile
FROM nginx:alpine
COPY nginx.conf /etc/nginx/nginx.conf
COPY default.conf /etc/nginx/conf.d/default.conf
EXPOSE 80 443
CMD ["nginx", "-g", "daemon off;"]
Docker Compose
version: '3.8'
services:
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./certs:/etc/ssl/certs:ro
depends_on:
- api
networks:
- app-network
Sources
Arhitectura/nginx.gif