94

I'm having trouble understanding nested locations in nginx. I have two locations with some configuration directives in common, so rather than repeat the directives, I'd prefer to repeat the URI using a regular-expression:

location ~ /a|/b {
        location /a {
        }
        location /b {
        }
}

However, this gives the error

nginx: [emerg] location "/a" is outside location "/a|/b" in /etc/nginx/nginx.conf:36

Without the or | it seems okay, though.

location ~ /a {
        location /a {
        }
}

What am I doing wrong? Is there a better way to do this without repeating anything? Can I group locations in another way?

Jesse Nickles
  • 250
  • 1
  • 12
Jayen
  • 1,827
  • 3
  • 16
  • 27
  • 1
    http://forum.nginx.org/read.php?2,174517,174534#msg-174534 – pkhamre Apr 05 '13 at 07:15
  • 9
    because logically they are grouped – Jayen Apr 06 '13 at 09:26
  • 1
    This took me a long time to understand but in the end I was able to create a simple(ish) [priority list of how locations are chosen](https://artfulrobot.uk/blog/untangling-nginx-location-block-matching-algorithm). – artfulrobot May 22 '18 at 10:16
  • There is a ticket for improving location docs: https://trac.nginx.org/nginx/ticket/1467 – cweiske Jan 05 '22 at 12:24

1 Answers1

152

Old question, but the issue is because the parent location is a regex location while the nested locations are prefix locations.

When a parent location is defined by a regex, any nested locations must also be defined by regexes:

location ~ ^/(a|b) {
        location ~ ^/a {
        ...
        }
        location ~ ^/b {
        ...
        }
}

You may only define nested prefix locations when the parent location is also a prefix location:

location /a {
        location /a {
               # You can also skip this location and just write
               # your code directly under the parent location
        }
        location /a/b {
        ...
        }
}

However, you may define nested regex locations when the parent location is a prefix location:

location /a/b {
        location ~ /a {
        ...
        }
        location ~ /b {
        ...
        }
}
Dayo
  • 1,766
  • 1
  • 14
  • 12
  • I got confused by your first sentence, but your examples make sense. I assume in the last example, the prefix location `/b` will throw an error? – Jayen Sep 10 '14 at 01:33
  • 17
    That first sentence should be in the [documentation](http://nginx.org/en/docs/http/ngx_http_core_module.html#location). – AndreKR Apr 15 '15 at 07:13
  • 2
    In the first example, if you leave out the `location /a { }` boilerplate -- does the order matter? – Meekohi May 15 '17 at 20:46
  • 5
    Ah nevermind I misunderstood. The nested locations don't inherit anything from their parent locations. – Meekohi May 15 '17 at 20:52
  • The parent location can be a non regex location but any multiple nested locations within the parent have to all be either regex / non regex. – MitchellK Jun 26 '18 at 07:45
  • the comment in the 1st example almost answers my question. If I put directives in the top location block are they inherited by all nested location blocks, or do the nested blocks need to repeat or override those directives? – Mike Lippert Aug 07 '18 at 00:03
  • This does not explain why the asker's second example would work. – purefanatic May 20 '20 at 15:54
  • @purefanatic. It doesn't explain this because the second example will not work. A Prefix Location Block will fail when nested in a Regex Location Block as shown. – Dayo Jun 06 '20 at 17:11
  • @Dayo But you are wrong: The asker's second example works just fine while you claim it shouldn't. It's exactly that: a prefix location block nested in a regex location block, yet it still works. And I don't know why it works, neither does the asker and your answer does not explain it. – purefanatic Jun 06 '20 at 18:12
  • And even if the second example of the asker *didn't* work I feel like an answer should point that out because the whole question presupposes that it *does* work. – purefanatic Jun 06 '20 at 18:14
  • @purefanatic. It could be that it does work now but pretty certain that would not have worked when the answer was written. As for your feeling about what should have been pointed out, feel free to add an answer of your own on this. – Dayo Jun 09 '20 at 18:54
  • @purefanatic, @Dayo: The second example is regex location nested in regex location. `location ~ ^/a` defines regex, `location /a` is prefix, although both match same urls. – Honza Aug 13 '21 at 16:48