Nginx Cheatsheet
Location Blocks
Use this Nginx reference while you build software engineering projects, review code, or refresh the syntax you reach for most.
Syntax
location [modifier] uri { ... }Modifier Reference
| Modifier | Type | Behaviour |
|---|---|---|
| (none) | Prefix | Matches if URI starts with the string |
= | Exact | Matches only if URI is exactly equal |
^~ | Priority prefix | Best prefix match; skips regex if matched |
~ | Regex (case-sensitive) | PCRE regex |
~* | Regex (case-insensitive) | PCRE regex, ignores case |
@ | Named | Internal redirect target only (no client requests) |
Matching Priority Order
=exact match (stops immediately)^~longest prefix match (stops — no regex checked)- Regex matches in config file order (first match wins)
- 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 / { ... } # 4 — catch-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; }