The Nginx location directive chooses configuration based on the request URI.
You can use it to serve files, proxy requests, or return redirects.
A basic redirect
For a small example of using a location block to serve files as plain text, see the NGINX text response guide.
This server redirects one exact path:
server {
listen 80;
server_name staging.example.com;
root /var/www/staging.example.com/public_html;
location = /old-page {
return 308 https://www.example.com/new-page;
}
}308 is a permanent redirect that preserves the request method and body. Use
302 or 307 while testing if you do not want clients to cache the redirect.
Location modifiers
The syntax is:
location [ = | ~ | ~* | ^~ ] uri { ... }| Modifier | Match |
|---|---|
| No modifier | URI prefix |
= | Exact URI |
~ | Case-sensitive regular expression |
~* | Case-insensitive regular expression |
^~ | URI prefix; skip regular expressions if this one wins |
Nginx matches against the normalized URI path, without the query string.
How Nginx picks a location
For non-nested locations, the search is:
- An exact
=match wins immediately. - Nginx remembers the longest matching prefix.
- If that prefix uses
^~, it wins immediately. - Otherwise, Nginx checks regular expressions in file order. The first match wins.
- If no regular expression matches, the remembered prefix wins.
Prefix order does not matter. Regular expression order does.
Prefix matches
A location without a modifier matches from the start of the URI:
location / {
# Matches every URI
}
location /foo {
# Matches /foo, /foo/bar, and /foobar
# Does not match /bar/foo
}Use a trailing slash when you mean a path segment:
location /foo/ {
# Matches /foo/bar, but not /foobar
}Prefix matching is case-sensitive on Linux, so /foo does not match /FOO.
Nginx ignores ASCII case for prefix locations on macOS and Cygwin.
Exact matches
Use = when only one URI should match:
location = / {
# Matches only /
}
location = /foo {
# Matches only /foo
}Regular expression matches
Nginx uses PCRE-compatible regular expressions. ~ is case-sensitive; ~* is
case-insensitive.
This redirects an old tag URL and keeps its query string:
location ~ ^/tag/(?<slug>[^/]+)$ {
return 308 /tags/$slug$is_args$args;
}For /tag/nginx?source=old:
^anchors the match to the start of the URI(?<slug>[^/]+)captures one path segment as$slug$anchors the match to the end$is_argsbecomes?when arguments exist, or an empty string otherwise$argscontains the query string
The result is /tags/nginx?source=old without needing an if block. See the
complete list of Nginx variables.
More regular expression examples
Cache versioned static files
Long cache lifetimes work best for files with content hashes in their names:
location ~* \.(?:avif|css|gif|ico|jpe?g|js|mjs|otf|png|svg|ttf|webp|woff2?)$ {
add_header Cache-Control "public, max-age=31536000, immutable";
access_log off;
}The escaped \. matches a literal dot. The ~* makes file extensions
case-insensitive.
Keep favicon requests out of the logs
Put this before a broader regular expression location, because the first matching regular expression wins:
location ~* ^/(?:favicon[^/]*\.(?:ico|png|svg)|apple-touch-icon[^/]*\.png)$ {
log_not_found off;
access_log off;
}Test redirects with curl
Browsers cache permanent redirects aggressively. Test with curl while tuning
the configuration:
$ curl --silent --show-error --head \
'http://staging.example.com/tag/nginx?source=old'
HTTP/1.1 308 Permanent Redirect
Server: nginx
Location: http://staging.example.com/tags/nginx?source=old--head (-I) sends a HEAD request, so the server returns headers without a
response body. It is fast and usually enough for testing Nginx redirects.
Some applications reject HEAD or handle it differently from GET. To test a
normal GET, print its headers and discard its body:
curl --silent --show-error --dump-header - --output /dev/null \
'http://staging.example.com/tag/nginx?source=old'This still downloads the response body. It simply does not save or print it.
To print only the destination:
$ curl --silent --show-error --head \
'http://staging.example.com/tag/nginx?source=old' \
| grep -i '^location:'
Location: http://staging.example.com/tags/nginx?source=oldAdd --location to follow the full redirect chain.
For more complex URI changes, see Nginx's
rewrite directive.