The location directive determines which configuration block handles a specific URI inside a server block, described in the article on Nginx virtual hosts. The catch is that a site usually has several location blocks, and Nginx does not check them in file order but follows its own priority algorithm. Not understanding that algorithm is a common reason a rule looks correct on paper but never fires.
What the location directive does
Location matches the request URI against a pattern and, if it matches, applies the nested directives: root, proxy_pass, try_files, headers, and so on. A single server block can contain dozens of locations — for static files, for an API, for an admin panel, for specific file extensions.
The key difficulty is that several locations can match the same URI at once. For example, the request /api/users/5 matches both location /api/ and location ~ \.php$ if .php appears in the path. Nginx must pick exactly one block using strict rules.
Location modifiers: =, ~, ~*, ^~, and no modifier
A modifier before the location pattern changes the comparison type and priority:
- location = /path — exact URI match, the highest priority.
- location ^~ /path — prefix match that stops the search for regular expressions.
- location ~ /path — case-sensitive regular expression match.
- location ~* .php$ — case-insensitive regular expression match.
- location /path — a plain prefix match with no modifier.
The order Nginx checks rules in
Nginx does not check locations top to bottom in the file; it follows an algorithm with a strict priority:
1. Exact match: location = /path
2. Prefix locations; the longest matching prefix is selected among them
3. If the selected prefix carries the ^~ modifier, the search stops here
4. Otherwise Nginx checks regexp locations ~ and ~* in file order
5. If a regexp match is found, it is used
6. If not, the same longest prefix from step 2 is applied
This gives the rule: regexp locations only fire if a longer prefix with ^~ has not blocked them, and the order regexp locations are written in the file matters — Nginx takes the first match from top to bottom.
Modifier priority table
| Modifier | Comparison type | Priority |
|---|---|---|
| = | Exact URI match | 1 — highest |
| ^~ | Prefix, blocks regexp | 2 |
| ~ and ~* | Regular expression | 3, in file order |
| no modifier | Plain prefix | 4 — lowest |
Common mistakes and rule conflicts
A classic mistake is location /images/ with a plain prefix next to location ~* \.(jpg|png)$ for caching images. If jpg files live under /images/, the regular expression wins over the prefix even if location /images/ is written earlier in the file — file order only matters between regexp blocks themselves.
A second common mistake is forgetting ^~ before a static-file location, which lets a request for a static file unexpectedly fall into a regexp block with proxy_pass to PHP-FPM. Forwarding requests to a backend is covered in the article on reverse proxy in Nginx, and the final serving of files is covered in the article on serving static files.
Practical location examples
A typical rule set for a site with static files, an API, and redirects, which also echoes the article on rewrite and return in Nginx:
location = /favicon.ico { access_log off; log_not_found off; }
location ^~ /assets/ { expires 30d; }
location ~* \.(css|js|woff2)$ { expires 7d; }
location /api/ { proxy_pass http://127.0.0.1:3000; }
location / { try_files $uri $uri/ /index.php?$args; }
Here /favicon.ico is handled first by exact match, /assets/ with ^~ is guaranteed not to fall through to regexp blocks, and the remaining regexp and general location are checked in the order from the algorithm above.
How to check which location fired
To confirm a request lands in the right block, add a temporary header add_header X-Location-Debug "block name"; to each disputed location and inspect the response headers with curl -I. After edits, nginx -t and systemctl reload nginx are mandatory.
- List every location in the server block and note its modifier.
- Check whether a regexp block accidentally shadows static files that should have ^~.
- Check the order of regexp locations relative to each other — Nginx takes the first match.
- Run nginx -t before reload on a production server.
Location priority in Nginx is not file order but a strict algorithm: exact match, then a prefix with ^~, then regexp in write order, and only then a plain prefix. Remembering this sequence saves hours of configuration debugging.