Nginx Cheatsheet

Location Blocks

Use this Nginx reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.

Syntax

location [modifier] uri { ... }

Modifier Reference

ModifierTypeBehaviour
(none)PrefixMatches if URI starts with the string
=ExactMatches only if URI is exactly equal
^~Priority prefixBest prefix match; skips regex if matched
~Regex (case-sensitive)PCRE regex
~*Regex (case-insensitive)PCRE regex, ignores case
@NamedInternal redirect target only (no client requests)

Matching Priority Order

  1. = exact match (stops immediately)
  2. ^~ longest prefix match (stops — no regex checked)
  3. Regex matches in config file order (first match wins)
  4. Longest prefix match (no modifier)
location = /favicon.ico { ... }          # 1 — exact, checked first
location ^~ /static/ { ... }            # 2 — prefix, skips regex
location ~* \.(jpg|png|gif)$ { ... }    # 3 — regex
location / { ... }                      # 4catch-all prefix

Common Patterns

# Exact match — fast for high-traffic single URIs
location = /health {
    default_type text/plain;   # add_header cannot set Content-Type on return bodies
    return 200 "ok";
}

# Prefix — all URIs under /api/
location /api/ {
    proxy_pass http://backend;
}

# Priority prefix — skip regex for static assets
location ^~ /assets/ {
    root /var/www;
    expires 1y;
}

# Case-insensitive regex — image files anywhere
location ~* \.(png|jpg|jpeg|gif|webp|svg)$ {
    root /var/www;
    expires 30d;
}

# Named location — used with error_page or try_files
location @fallback {
    proxy_pass http://backend;
}

try_files Patterns

# Static site: file → directory index → 404
try_files $uri $uri/ =404;

# SPA: fall through to index.html
try_files $uri $uri/ /index.html;

# Proxy fallback: serve file if it exists, else pass to backend
try_files $uri @backend;

location @backend {
    proxy_pass http://app_server;
}

Nested Locations

location /app/ {
    root /var/www;

    location ~* \.php$ {          # Nested: only runs for .php under /app/
        fastcgi_pass unix:/run/php/php8.2-fpm.sock;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}

Avoid deep nesting — it's hard to reason about priority.

Internal Locations

# Only reachable via internal redirects (error_page, try_files, X-Accel-Redirect)
location /private/ {
    internal;
    root /data/protected;
}

# Use with X-Accel-Redirect from an upstream app
# App returns: X-Accel-Redirect: /private/file.pdf

Basic Auth

# Create the password file (htpasswd ships in apache2-utils / httpd-tools)
sudo htpasswd -c /etc/nginx/.htpasswd admin      # -c only the first time
location /admin/ {
    auth_basic           "Restricted";
    auth_basic_user_file /etc/nginx/.htpasswd;
}

# Combine with an IP allowlist — satisfy any = pass EITHER check
location /internal/ {
    satisfy any;
    allow 10.0.0.0/8;
    deny  all;
    auth_basic           "Restricted";
    auth_basic_user_file /etc/nginx/.htpasswd;
}

Restricting Methods

location /api/ {
    limit_except GET POST {
        deny all;
    }
}

Per-location Logging Control

location /health {
    access_log off;   # Suppress health-check noise
    return 200;
}

location ~* \.(css|js|png)$ {
    access_log /var/log/nginx/static.log;   # Separate log for assets
}

Returning Responses Directly

location = /robots.txt  { return 200 "User-agent: *\nDisallow: /admin/\n"; }
location = /ping        { return 200 "pong"; }
location /old-path/     { return 301 /new-path/; }
location /gone/         { return 410; }