Operations 12 min read

Nginx Config Deep Dive: Reverse Proxy, Location Matching & Root vs Alias Explained

This tutorial breaks down Nginx configuration hierarchy, location matching priority, root vs alias path mapping differences, reverse proxy essentials including proxy_pass trailing slash behavior, required headers, timeout settings, and SSE streaming configuration with practical examples and common pitfalls.

Code Farmer Manor Chronicle
Code Farmer Manor Chronicle
Code Farmer Manor Chronicle
Nginx Config Deep Dive: Reverse Proxy, Location Matching & Root vs Alias Explained

Nginx Configuration Hierarchy

Nginx configuration is structured in layers, from broad to specific: global → events → http → server . Outer layers are inherited by inner layers.

1. Global Block

user www-data;
worker_processes auto;

user : Runs worker processes as low-privilege user www-data. Never use root — if Nginx is compromised, the attacker won't gain full server control.

worker_processes : Number of worker processes. Set to auto to match CPU cores. A common mistake is setting it very high (thousands), which only wastes memory without improving performance.

2. Events Block

events {
    worker_connections 1024;
}
worker_connections

is the maximum simultaneous connections per worker process. Rule of thumb : max concurrent connections ≈ worker_processes × worker_connections. Default 1024 suffices for small sites; increase for high concurrency.

3. HTTP Block

The http {} block contains all site configurations. Key include directives: include mime.types: Loads MIME type mapping so browsers handle files correctly (e.g., .html → text/html). Do not remove. include conf.d/*.conf: Loads all .conf files from conf.d/. include sites-enabled/*: Loads enabled site configurations.

This modular approach keeps the main config clean and isolates site-specific settings.

conf.d vs sites-enabled: Division of Labor

Core difference is enable/disable workflow :

conf.d/*.conf : Place config directly in .conf files. Best for simple scenarios, single server blocks. Disable a site by deleting or commenting out the file — destructive.

sites-available + sites-enabled : Configs in available, symlinks in enabled. Best for many sites, need flexible enable/disable. Disable by removing the symlink; config remains in sites-available/ for easy rollback.

Recommendation : Use sites-available/sites-enabled for project sites (manageable, reversible); use conf.d/ for small tools or temporary configs. Don't mix both for the same site.

Location Matching & Root vs Alias (Critical)

Location matching priority (high to low):

server {
    location = /demo {}      # 1. Exact match, only /demo
    location ^~ /img/ {}     # 2. Prefix match, stops regex search
    location ~ \.png$ {}    # 3. Regex match (~* case-insensitive)
    location / {}            # 4. Generic prefix, fallback
}
= /demo

(exact): Matches only /demo. ^~ /img/ (prefix, stop): Matches all paths starting with /img/, skips regex after match. ~ \.png$ (regex): Matches by file extension; ~* ignores case. / (generic prefix): Catch-all for any path.

Mnemonic : Exact (=) > Prefix with ^~ > Regex (~) > Generic prefix /

Root vs Alias: Path Resolution

Both map requests to local files, but concatenation logic differs:

# root: full URL path appended to root directory
location /images/ {
    root /var/www/myweb;   # /images/logo.png
}                          # → /var/www/myweb/images/logo.png

# alias: replaces matched URL segment with alias path
location /images/ {
    alias /var/www/pics/;  # /images/logo.png
}                          # → /var/www/pics/logo.png

Mnemonic : root = "append entire URL to root"; alias = "replace matched URL segment with given directory".

Concatenation : root appends full URL path after root; alias replaces matched location segment with alias directory.

Trailing slash : root usually omitted; alias critical — missing slash causes 404.

Use case : root for most cases (site root directory); alias for directory mapping, static assets.

Classic pitfall : Using root when you only want to map a prefix. Example: file at /var/www/myweb/logo.png, config location /static/ { root /var/www/myweb; } → Nginx looks for /var/www/myweb/static/logo.png (404).

Reverse Proxy Configuration & Pitfalls

Reverse proxy forwards requests to backend app servers; clients only talk to Nginx.

1. Basic Reverse Proxy

server {
    listen 80;
    server_name example.com;

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

Three proxy_set_header lines are mandatory : Host $host: Backend uses it to identify the virtual host; missing may cause 403. X-Real-IP / X-Forwarded-For: Backend logs see real client IP; without them, all requests appear as 127.0.0.1.

If backend logs or does IP-based logic, none of these three can be omitted .

2. proxy_pass Trailing Slash — Critical Difference

A single slash changes path translation entirely:

# Style A: no trailing slash → full URL passed unchanged
location /api/ {
    proxy_pass http://127.0.0.1:8080;
}
# /api/login → backend receives /api/login (path unchanged)

# Style B: trailing slash → matched segment replaced by /
location /api/ {
    proxy_pass http://127.0.0.1:8080/;
}
# /api/login → backend receives /login (/api/ stripped)

Mnemonic : No trailing slash = path passed through; trailing slash = matched segment replaced by slash.

Choose based on backend routing: if backend routes include /api prefix, use Style A; if backend routes are root-relative (no /api), use Style B. Wrong choice = 404.

3. Proxy Timeouts & Buffering

Prevent 504 errors when backend is slow:

proxy_connect_timeout 30s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
proxy_buffering on;

4. SSE / Streaming Endpoints — Must Disable Buffering

Default proxy buffering breaks Server-Sent Events (SSE) — client receives a large chunk instead of incremental stream. Disable buffering:

location /stream/ {
    proxy_pass http://127.0.0.1:8000;
    proxy_buffering off;
    add_header X-Accel-Buffering no;
}

After any config change, always run nginx -t && systemctl reload nginx.

HTTPS Setup (Recommended)

Easiest path: use Certbot to obtain and configure Let's Encrypt certificates automatically:

sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d example.com

Certbot handles certificate download, Nginx configuration, and automatic renewal — no manual ssl block needed.

Summary

Config has hierarchy : global user / worker_processes → events → http → server; outer layers inherited by inner.

Separate site configs : conf.d/ for simplicity, sites-available/enabled for reversible management.

Root vs alias : root appends full path; alias replaces matched segment — source of 90% of 404s.

Reverse proxy essentials : three proxy_set_header lines required; proxy_pass trailing slash determines path rewrite; streaming needs proxy_buffering off.

Always run nginx -t before reload.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

operationsconfigurationNginxreverse proxyweb-servercertbotlocation-matchingroot-alias
Code Farmer Manor Chronicle
Written by

Code Farmer Manor Chronicle

A heart like drifting clouds, ever at ease; a mind like flowing water, free to roam.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.