0

I need to create a virtual sub directory in nginx which will serve files from a different location than the root. This virtual directory also runs PHP, but I've omitted the fastcgi config for brevity.

I have two location blocks, the one for the /virtual directory uses alias, while the location block for / has it's own root directive. This root directive gets inherited by the virtual folder, messing up the paths. Is there any way I can exclude urls in /virtual from inheriting the root directive of the / location block?

Here is an excerpt of my server config:

server {
    root /path/to;

    location ^~ /virtual/ {
        alias /path/to/lions/public;
        try_files $uri $uri/ /lions/public/index.php?$query_string;
    }

    location / {
        root /path/to/tigers/public;
        try_files $uri $uri/ /index.php?$query_string;
    }
}

If I browse to hostname/virtual/whatever, nginx looks for the file at

/path/to/tigers/public/lions/public/whatever

instead of

/path/to/lions/public/whatever

I have tried the following pattern to match all urls at / except for those starting with /virtual, but that didn't match anything.

location ^~ ((?!\/virtual)\/.*)$

I have also tried putting both an alias and a root directive in the location block for /virtual, but nginx wouldn't start.

Is there any other way to have a different root for my alias directory?

  • Try [this approach](https://stackoverflow.com/a/16304073/3832970). Use `location ~ ^/?virtual/.*$ { # empty }` and then use `location / { ... }` – Wiktor Stribiżew May 24 '17 at 17:59

1 Answers1

0

The value of the location and the value of the alias should either both end in / or neither end in / - due to the way nginx does the text substitution when calculating the $request_filename.

All elements in the try_files statement are URIs, so your final element should be /virtual/index.php?$query_string and not /lions/public/index.php?$query_string. The latter would begin a new search, which would be processed by the location / block. Hence the strange file path.

Finally, there is an unpredictability when using alias and try_files together. See this bug report. The same functionality can be achieved using a if block. See this caution on the use of if.

For example:

location ^~ /virtual/ {
    alias /path/to/lions/public/;
    if (!-e $request_filename) { rewrite ^ /virtual/index.php?$query_string; }
}
Richard Smith
  • 45,711
  • 6
  • 82
  • 81