Nginx

High-performance, lightweight web server and reverse proxy server. High concurrent connection handling with event-driven architecture. Specialized in static content delivery.

Web ServerReverse ProxyLoad BalancerHigh PerformanceHTTP Server

Application Server

Nginx

Overview

Nginx is a high-performance web server, reverse proxy, load balancer, API Gateway, and content cache designed for maximum performance and stability. Originally created by Igor Sysoev to solve the C10K problem (handling 10,000 concurrent connections), Nginx has become one of the most popular web servers globally, powering millions of websites and applications. Built with an event-driven, asynchronous architecture, Nginx excels at serving static content, handling high concurrency, and efficiently proxying requests to backend services. Its lightweight footprint, combined with exceptional performance characteristics, makes it an ideal choice for modern web infrastructures, from simple websites to complex microservices architectures.

Details

Nginx 2025 edition continues to dominate the web server landscape with its proven architecture and continuous evolution to meet modern web demands. At its core, Nginx operates using a master-worker process model where a master process manages multiple worker processes that handle actual request processing. This architecture, combined with its event-driven I/O model, enables Nginx to handle thousands of concurrent connections with minimal memory footprint. The server supports HTTP/1.1, HTTP/2, and HTTP/3 protocols, along with WebSocket connections and gRPC proxying. Nginx's modular design allows for extensive customization through both static and dynamic modules, while its configuration system provides fine-grained control over every aspect of request processing. Whether serving static files, load balancing between backend servers, or acting as an API gateway, Nginx delivers consistent high performance across diverse use cases.

Key Features

  • High Concurrency: Event-driven architecture handling thousands of simultaneous connections efficiently
  • Multi-Protocol Support: HTTP/1.1, HTTP/2, HTTP/3, WebSocket, gRPC, and FastCGI protocols
  • Load Balancing: Advanced load balancing with multiple algorithms and health checking
  • Reverse Proxy: Comprehensive proxying capabilities with SSL termination and caching
  • Static File Serving: Optimized static content delivery with compression and caching
  • Modular Architecture: Extensible through static and dynamic modules for custom functionality

Advantages and Disadvantages

Advantages

  • Exceptional performance and low resource consumption with event-driven, non-blocking I/O architecture
  • Versatile functionality serving as web server, reverse proxy, load balancer, and API gateway in one solution
  • High concurrency handling thousands of connections with minimal memory footprint
  • Battle-tested stability and reliability proven in production environments worldwide
  • Extensive configuration flexibility with powerful directive-based configuration system
  • Strong ecosystem support with comprehensive documentation and large community
  • Excellent caching capabilities improving application performance and reducing backend load

Disadvantages

  • Configuration complexity can be challenging for beginners with steep learning curve
  • Limited dynamic content processing requiring integration with application servers like PHP-FPM
  • Windows support is experimental and not recommended for production environments
  • Reloading configuration requires careful planning in high-traffic scenarios
  • Advanced features may require commercial Nginx Plus version
  • Module system requires compilation for static modules, limiting runtime flexibility
  • Memory usage can grow with complex configurations and many concurrent connections

Reference Links

Configuration Examples

Basic Web Server Configuration

# /etc/nginx/nginx.conf - Basic web server setup
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;

events {
    worker_connections 1024;
    use epoll;
    multi_accept on;
}

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    # Logging configuration
    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';
    access_log /var/log/nginx/access.log main;

    # Basic performance settings
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;

    # Basic server block
    server {
        listen 80;
        listen [::]:80;
        server_name example.com www.example.com;
        root /var/www/html;
        index index.html index.htm index.nginx-debian.html;

        location / {
            try_files $uri $uri/ =404;
        }

        # Static assets caching
        location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg)$ {
            expires 1y;
            add_header Cache-Control "public, immutable";
        }

        # 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;

        # Error pages
        error_page 404 /404.html;
        error_page 500 502 503 504 /50x.html;
        
        location = /50x.html {
            root /var/www/html;
        }
    }

    # Include additional configuration files
    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

SSL/HTTPS Configuration

# /etc/nginx/sites-available/example.com - HTTPS configuration
server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;
    
    # Redirect all HTTP traffic to HTTPS
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name example.com www.example.com;
    root /var/www/html;
    index index.html index.htm;

    # SSL configuration
    ssl_certificate /etc/nginx/ssl/example.com.crt;
    ssl_certificate_key /etc/nginx/ssl/example.com.key;
    ssl_trusted_certificate /etc/nginx/ssl/example.com.chain.crt;

    # SSL optimization
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 24h;
    ssl_session_tickets off;

    # Modern SSL configuration
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE+AESGCM:ECDHE+CHACHA20:DHE+AESGCM:DHE+CHACHA20:!aNULL:!MD5:!DSS;
    ssl_prefer_server_ciphers off;

    # HSTS (HTTP Strict Transport Security)
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

    # OCSP Stapling
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8 8.8.4.4 valid=300s;
    resolver_timeout 5s;

    location / {
        try_files $uri $uri/ =404;
    }

    # Security configuration
    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;
}

Reverse Proxy Configuration

# /etc/nginx/sites-available/app-proxy - Reverse proxy setup
upstream backend_servers {
    server 192.168.1.10:8080 weight=3 max_fails=3 fail_timeout=30s;
    server 192.168.1.11:8080 weight=2 max_fails=3 fail_timeout=30s;
    server 192.168.1.12:8080 weight=1 backup;
    
    # Connection pooling
    keepalive 32;
    keepalive_requests 100;
    keepalive_timeout 60s;
}

server {
    listen 80;
    server_name api.example.com;
    
    # Client configuration
    client_max_body_size 20M;
    client_body_timeout 60s;
    client_header_timeout 60s;

    location / {
        # Proxy configuration
        proxy_pass http://backend_servers;
        
        # Headers for backend
        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_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Port $server_port;

        # Timeouts
        proxy_connect_timeout 30s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;

        # Buffering
        proxy_buffering on;
        proxy_buffer_size 8k;
        proxy_buffers 16 8k;
        proxy_busy_buffers_size 16k;

        # Error handling
        proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
        proxy_next_upstream_tries 3;
        proxy_next_upstream_timeout 30s;
    }

    # Health check endpoint
    location /health {
        access_log off;
        return 200 "healthy\n";
        add_header Content-Type text/plain;
    }

    # Static files served directly by Nginx
    location /static/ {
        alias /var/www/static/;
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
}

Load Balancing with Health Checks

# /etc/nginx/conf.d/load-balancer.conf - Advanced load balancing
upstream web_backend {
    # Load balancing method
    least_conn;
    
    # Backend servers
    server web1.example.com:80 weight=3 max_fails=2 fail_timeout=30s;
    server web2.example.com:80 weight=3 max_fails=2 fail_timeout=30s;
    server web3.example.com:80 weight=2 max_fails=2 fail_timeout=30s;
    server web4.example.com:80 backup;
    
    # Connection pooling
    keepalive 16;
}

upstream api_backend {
    # IP hash for session persistence
    ip_hash;
    
    server api1.example.com:8080 max_fails=3 fail_timeout=30s;
    server api2.example.com:8080 max_fails=3 fail_timeout=30s;
    server api3.example.com:8080 max_fails=3 fail_timeout=30s;
    
    keepalive 32;
}

# Rate limiting
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=web_limit:10m rate=50r/s;

server {
    listen 80;
    server_name lb.example.com;

    # Web application load balancing
    location / {
        limit_req zone=web_limit burst=20 nodelay;
        
        proxy_pass http://web_backend;
        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;

        # Health check simulation (basic)
        proxy_connect_timeout 5s;
        proxy_send_timeout 10s;
        proxy_read_timeout 10s;
        
        proxy_next_upstream error timeout http_500 http_502 http_503 http_504;
    }

    # API load balancing with session persistence
    location /api/ {
        limit_req zone=api_limit burst=5 nodelay;
        
        proxy_pass http://api_backend;
        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;

        # API-specific configuration
        proxy_buffering off;
        proxy_request_buffering off;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
    }

    # Load balancer status page
    location /nginx_status {
        stub_status on;
        access_log off;
        allow 127.0.0.1;
        allow 192.168.1.0/24;
        deny all;
    }
}

High-Performance Configuration

# /etc/nginx/nginx.conf - High-performance configuration
user nginx;
worker_processes auto;
worker_cpu_affinity auto;
worker_rlimit_nofile 65535;

error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
    worker_connections 8192;
    use epoll;
    multi_accept on;
    accept_mutex off;
}

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    # Logging optimized for performance
    log_format optimized '$remote_addr - $remote_user [$time_local] '
                        '"$request" $status $body_bytes_sent '
                        '"$http_referer" "$http_user_agent" '
                        '$request_time $upstream_response_time';
    
    access_log /var/log/nginx/access.log optimized buffer=32k flush=5s;

    # Performance optimizations
    sendfile on;
    sendfile_max_chunk 1m;
    tcp_nopush on;
    tcp_nodelay on;
    
    # Keep-alive settings
    keepalive_timeout 30s;
    keepalive_requests 1000;

    # Client settings
    client_body_buffer_size 128k;
    client_max_body_size 50m;
    client_header_buffer_size 3m;
    large_client_header_buffers 4 256k;
    client_body_timeout 60s;
    client_header_timeout 60s;
    send_timeout 60s;

    # Gzip compression
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_min_length 1000;
    gzip_types
        text/plain
        text/css
        text/xml
        text/javascript
        application/json
        application/javascript
        application/xml+rss
        application/atom+xml
        image/svg+xml;

    # File caching
    open_file_cache max=10000 inactive=5m;
    open_file_cache_valid 2m;
    open_file_cache_min_uses 1;
    open_file_cache_errors on;

    # Proxy caching
    proxy_cache_path /var/cache/nginx/proxy levels=1:2 keys_zone=proxy_cache:50m 
                     max_size=1g inactive=60m use_temp_path=off;

    # Rate limiting zones
    limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;
    limit_req_zone $binary_remote_addr zone=api:10m rate=100r/s;
    limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;

    # Connection limiting
    limit_conn_zone $binary_remote_addr zone=addr:10m;

    server {
        listen 80 default_server deferred;
        listen [::]:80 default_server;
        server_name _;
        root /var/www/html;
        index index.html;

        # Connection limits
        limit_conn addr 50;
        limit_rate 500k;

        # General rate limiting
        limit_req zone=general burst=50 nodelay;

        location / {
            try_files $uri $uri/ =404;
            
            # Static file caching
            location ~* \.(jpg|jpeg|png|gif|ico|css|js|pdf|doc)$ {
                expires 1y;
                add_header Cache-Control "public, immutable";
                add_header Pragma public;
                access_log off;
            }
        }

        # API endpoints with specific rate limiting
        location /api/ {
            limit_req zone=api burst=200 nodelay;
            
            proxy_pass http://backend_api;
            proxy_cache proxy_cache;
            proxy_cache_valid 200 302 5m;
            proxy_cache_valid 404 1m;
            proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
            
            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;
        }

        # Login endpoint with strict rate limiting
        location /login {
            limit_req zone=login burst=5 nodelay;
            
            proxy_pass http://auth_backend;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }

    include /etc/nginx/conf.d/*.conf;
}

Security Configuration

# /etc/nginx/conf.d/security.conf - Security hardening
# Hide Nginx version
server_tokens off;

# 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 Permissions-Policy "geolocation=(), microphone=(), camera=()" always;

# Rate limiting for security
limit_req_zone $binary_remote_addr zone=brute_force:10m rate=1r/s;

# Block common attack patterns
map $request_uri $block_request {
    default 0;
    "~*\.(php|aspx|jsp)$" 1;
    "~*/wp-admin" 1;
    "~*/phpmyadmin" 1;
    "~*/\.git" 1;
    "~*/\.env" 1;
}

server {
    listen 443 ssl http2;
    server_name secure.example.com;

    # SSL configuration
    ssl_certificate /etc/nginx/ssl/secure.example.com.crt;
    ssl_certificate_key /etc/nginx/ssl/secure.example.com.key;
    
    # Strong SSL configuration
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE+AESGCM:ECDHE+CHACHA20:DHE+AESGCM:DHE+CHACHA20:!aNULL:!MD5:!DSS;
    ssl_prefer_server_ciphers off;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 24h;

    # HSTS
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

    # Block malicious requests
    if ($block_request = 1) {
        return 444;
    }

    # Block suspicious user agents
    if ($http_user_agent ~* (nmap|nikto|wikto|sf|sqlmap|bsqlbf|w3af|acunetix|havij|appscan)) {
        return 444;
    }

    # Rate limiting for authentication endpoints
    location /auth/ {
        limit_req zone=brute_force burst=3 nodelay;
        
        # Additional security headers for auth
        add_header Cache-Control "no-store, no-cache, must-revalidate" always;
        add_header Pragma "no-cache" always;
        
        proxy_pass http://auth_backend;
        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;
    }

    # Deny access to hidden files
    location ~ /\. {
        deny all;
        access_log off;
        log_not_found off;
    }

    # Deny access to backup and config files
    location ~* \.(bak|config|sql|fla|psd|ini|log|sh|inc|swp|dist)$ {
        deny all;
        access_log off;
        log_not_found off;
    }

    location / {
        # Content Security Policy
        add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self'; connect-src 'self'; frame-ancestors 'none';" always;
        
        try_files $uri $uri/ =404;
    }
}

Container and Docker Configuration

# Dockerfile for custom Nginx build
FROM nginx:1.25-alpine

# Install additional modules
RUN apk add --no-cache nginx-mod-http-geoip nginx-mod-http-image-filter

# Copy custom configuration
COPY nginx.conf /etc/nginx/nginx.conf
COPY conf.d/ /etc/nginx/conf.d/
COPY ssl/ /etc/nginx/ssl/

# Copy static content
COPY html/ /var/www/html/

# Set proper permissions
RUN chown -R nginx:nginx /var/www/html && \
    chmod -R 755 /var/www/html

# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
    CMD curl -f http://localhost/health || exit 1

EXPOSE 80 443

CMD ["nginx", "-g", "daemon off;"]
# docker-compose.yml for Nginx deployment
version: '3.8'

services:
  nginx:
    build: .
    container_name: nginx-server
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./conf.d:/etc/nginx/conf.d:ro
      - ./ssl:/etc/nginx/ssl:ro
      - ./logs:/var/log/nginx
      - ./cache:/var/cache/nginx
      - html_data:/var/www/html
    environment:
      - NGINX_ENTRYPOINT_QUIET_LOGS=1
    networks:
      - web_network
    restart: unless-stopped
    depends_on:
      - backend
      
  backend:
    image: node:18-alpine
    container_name: app-backend
    expose:
      - "3000"
    networks:
      - web_network
    environment:
      - NODE_ENV=production
    restart: unless-stopped

volumes:
  html_data:

networks:
  web_network:
    driver: bridge

Monitoring and Logging Configuration

# /etc/nginx/conf.d/monitoring.conf - Monitoring setup
log_format json_combined escape=json
'{'
  '"time_local":"$time_local",'
  '"remote_addr":"$remote_addr",'
  '"remote_user":"$remote_user",'
  '"request":"$request",'
  '"status": "$status",'
  '"body_bytes_sent":"$body_bytes_sent",'
  '"request_time":"$request_time",'
  '"http_referrer":"$http_referer",'
  '"http_user_agent":"$http_user_agent",'
  '"upstream_addr":"$upstream_addr",'
  '"upstream_status":"$upstream_status",'
  '"upstream_response_time":"$upstream_response_time",'
  '"http_x_forwarded_for":"$http_x_forwarded_for"'
'}';

server {
    listen 80;
    server_name monitor.example.com;
    
    access_log /var/log/nginx/access.json json_combined;

    # Metrics endpoint for Prometheus
    location /metrics {
        access_log off;
        stub_status on;
        allow 127.0.0.1;
        allow 192.168.1.0/24;
        deny all;
    }

    # Health check endpoint
    location /health {
        access_log off;
        return 200 "OK";
        add_header Content-Type text/plain;
    }

    # Detailed status information
    location /status {
        access_log off;
        stub_status on;
        allow 127.0.0.1;
        allow 192.168.1.0/24;
        deny all;
    }

    # Real-time log streaming
    location /logs {
        access_log off;
        allow 127.0.0.1;
        allow 192.168.1.0/24;
        deny all;
        
        # Tail logs in real-time
        add_header Content-Type text/plain;
        echo_exec /usr/bin/tail -f /var/log/nginx/access.log;
    }
}