Nginx (Engine-X)

The web server that handles your traffic, proxies your apps, and terminates your SSL—all in one config file.

4 min read

What is Nginx?

Nginx (pronounced "engine-x") is a web server that also functions as a reverse proxy, load balancer, and HTTP cache. Created by Igor Sysoev in 2004 to handle the C10K problem (10,000 concurrent connections), it now powers over 30% of the web.

nginx
server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
    }
}

Unlike Apache's process-per-connection model, Nginx uses an event-driven, asynchronous architecture that handles thousands of connections with minimal memory.

Core Concepts

Server Blocks (Virtual Hosts)

Server blocks let you host multiple sites on one machine:

nginx
# Site 1
server {
    listen 80;
    server_name app.example.com;
    root /var/www/app;
}

# Site 2
server {
    listen 80;
    server_name api.example.com;

    location / {
        proxy_pass http://localhost:8080;
    }
}

Location Blocks

Location blocks match URL paths and define how to handle requests:

nginx
server {
    # Exact match
    location = /health {
        return 200 'ok';
    }

    # Prefix match
    location /api/ {
        proxy_pass http://backend;
    }

    # Regex match
    location ~* \.(jpg|png|gif)$ {
        expires 30d;
        add_header Cache-Control "public";
    }

    # Default fallback
    location / {
        try_files $uri $uri/ /index.html;
    }
}
ModifierPriorityBehavior
=1stExact match only
^~2ndPrefix match, stops regex search
~3rdCase-sensitive regex
~*3rdCase-insensitive regex
(none)4thPrefix match

Reverse Proxy

The most common Nginx use case — sitting in front of application servers:

nginx
upstream backend {
    server 127.0.0.1:3000;
    server 127.0.0.1:3001;
    server 127.0.0.1:3002;
}

server {
    listen 80;

    location / {
        proxy_pass http://backend;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
    }
}

SSL/TLS Configuration

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

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    # Modern TLS settings
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers off;
}

# Redirect HTTP to HTTPS
server {
    listen 80;
    server_name example.com;
    return 301 https://$server_name$request_uri;
}

Common Patterns

SPA (Single Page App) Routing

nginx
location / {
    try_files $uri $uri/ /index.html;
}

Gzip Compression

nginx
gzip on;
gzip_types text/plain text/css application/json application/javascript;
gzip_min_length 1000;

Rate Limiting

nginx
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;

location /api/ {
    limit_req zone=api burst=20 nodelay;
    proxy_pass http://backend;
}

Where You'll See This

  • Web hosting — Serving static files and proxying to app servers
  • Load balancing — Distributing traffic across multiple backends
  • SSL termination — Handling HTTPS at the edge
  • CDN/Caching — Caching responses to reduce backend load
  • API gateways — Routing and rate-limiting API traffic
  • Docker/Kubernetes — Ingress controllers and sidecar proxies

Nginx vs Apache

FeatureNginxApache
ArchitectureEvent-drivenProcess/thread per connection
Static filesVery fastFast
Config styleCentralized files.htaccess + centralized
ModulesCompiled inDynamic loading
Best forReverse proxy, high concurrencyShared hosting, .htaccess

Common Gotchas

⚠️Missing Semicolons

Every Nginx directive must end with a semicolon. A missing semicolon gives cryptic errors like "unexpected end of file" that point to the wrong line.

ℹ️Config Testing

Always run nginx -t before reloading. It validates your config without disrupting live traffic. Then nginx -s reload to apply changes gracefully.

  • Location block priority — Regex locations can override longer prefix matches. Use ^~ to prevent this.
  • proxy_pass trailing slashproxy_pass http://backend/ (with slash) strips the matched location prefix. Without slash, it passes the full URI.
  • try_files and proxy_pass — You cannot use both in the same location block. Use a named location instead.
  • Config formatting — Messy configs with inconsistent indentation make it hard to spot nesting errors. Use a formatter to keep things clean.

Try It

Format Nginx Config

"In nginx config, the semicolons are mandatory but the tears are optional."