273

I'm looking to serve the root url of a subdomain and directory of a subdomain to two different folders on my server. Here is the simple set-up that I have and is not working...

server {

    index index.html index.htm;
    server_name test.example.com;

    location / {
            root /web/test.example.com/www;
    }

    location /static {
            root /web/test.example.com/static;
    }
}

In this example going to test.example.com/ would bring the index file in /web/test.example.com/www

and going to test.example.com/static would bring the index file in /web/test.example.com/static

ian
  • 12,003
  • 9
  • 51
  • 107
simoes
  • 4,897
  • 4
  • 23
  • 28

6 Answers6

310

You need to use the alias directive for location /static:

server {

  index index.html;
  server_name test.example.com;

  root /web/test.example.com/www;

  location /static/ {
    alias /web/test.example.com/static/;
  }

}

The nginx wiki explains the difference between root and alias better than I can:

Note that it may look similar to the root directive at first sight, but the document root doesn't change, just the file system path used for the request. The location part of the request is dropped in the request Nginx issues.

Note that root and alias handle trailing slashes differently.

Mike Bijon
  • 52
  • 1
  • 6
furq
  • 5,648
  • 3
  • 16
  • 21
  • 80
    He doesn't need `alias`. Please, read [the official docs](http://nginx.org/r/alias), not the community wiki filled by users. Quote: *When location matches the last part of the directive's value it is better to use the root directive*. – VBart Jul 20 '12 at 16:20
  • 9
    This worked for me except that it's missing a trailing slash. The alias should read: alias /web/test.example.com/static/; – ajma Feb 27 '14 at 05:29
  • 8
    @VBart the docs do say exactly what you quote them as saying, but they don't justify that instruction at all - it seems like an arbitrary style choice. Do you see any logical reason behind it? – Mark Amery May 14 '15 at 09:21
  • This was working without tailling / in my case. But the best way to do this seems like https://stackoverflow.com/a/30038528/2716796 – kakadais Oct 18 '20 at 02:23
  • Do I need to use "try_files $uri $uri/ =404;" under "alias" line ? – BuffK Feb 03 '21 at 02:02
  • 1
    Just need to remember... as i just found out ... alias = "REPLACE" root = "APPEND" – blissweb Dec 27 '21 at 08:05
  • I would really like to know why the instructions say to use `root` rather than `alias` under those circumstances. It isn't explained, and it doesn't work on my configuration, but `alias` works. – Teekin Jun 20 '22 at 17:48
  • @blissweb could you pleas clarify your comment? Are you pointing out a functional distinction between alias and root? – elysch Nov 24 '22 at 18:07
  • 1
    @elysch yes, if you had /static and root /root/ the path would be /root/static/ if you had /static and an alias /root/ the path would be /root/ only. The initial path would be completely replaced. – blissweb Nov 26 '22 at 01:55
139

The Location directive system is

Like you want to forward all request which start /static and your data present in /var/www/static

So a simple method is separated last folder from full path , that means

Full path : /var/www/static

Last Path : /static and First path : /var/www

location <lastPath> {
    root <FirstPath>;
}

So lets see what you did mistake and what is your solutions

Your Mistake :

location /static {
    root /web/test.example.com/static;
}

Your Solutions :

location /static {
    root /web/test.example.com;
}
Philipp Kyeck
  • 18,402
  • 15
  • 86
  • 123
Kernelv5
  • 1,732
  • 1
  • 10
  • 17
  • 28
    This looks like a rather SEVERE limitation on Freedom To Do What I Want. I want URIs starting with a certain path to be served from a directory that doesn't contain that URI path in its physical file path. With this solution, I am FORCED to put my documents on disk under a path that ends with "/static". I don't like this at all. I want absolute and complete freedom of putting the files wherever I want. – Szczepan Hołyszewski May 05 '19 at 17:27
  • 1
    @SzczepanHołyszewski then use the "alias" directive – ddruganov May 31 '22 at 07:06
60
server {

    index index.html index.htm;
    server_name test.example.com;

    location / {
        root /web/test.example.com/www;
    }

    location /static {
        root /web/test.example.com;
    }
}

https://nginx.org/en/docs/http/ngx_http_core_module.html#root

PJunior
  • 2,649
  • 1
  • 33
  • 29
VBart
  • 14,714
  • 4
  • 45
  • 49
  • 2
    what's the different with asked? – Moon soon Dec 23 '15 at 16:11
  • 7
    @Wooden the difference: `root /web/test.example.com;` instead of `root /web/test.example.com/static;`. nginx maps the path specified by *location* to the diretory tree and since the path and the source directory share the same name, it works with `root`. – rmoestl Apr 20 '16 at 08:35
  • 3
    This format is discouraged. Better to have a parent `root` under `server`. See [Nginx config pitfalls](https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/?highlight=alias#root-inside-location-block). – Kamafeather Oct 06 '21 at 17:33
13

A little more elaborate example.

Setup: You have a website at example.com and you have a web app at example.com/webapp

...
server {
  listen 443 ssl;
  server_name example.com;

  root   /usr/share/nginx/html/website_dir;
  index  index.html index.htm;
  try_files $uri $uri/ /index.html;

  location /webapp/ {
    alias  /usr/share/nginx/html/webapp_dir/;
    index  index.html index.htm;
    try_files $uri $uri/ /webapp/index.html;
  }
}
...

I've named webapp_dir and website_dir on purpose. If you have matching names and folders you can use the root directive.

This setup works and is tested with Docker.

NB!!! Be careful with the slashes. Put them exactly as in the example.

viktor_vangel
  • 894
  • 9
  • 16
1

If you use this, I will suggest you set up this command too.

location /static/ {
    proxy_set_header Host $host/static; // if you change the directory and the browser can't find your path
    alias /web/test.example.com/static/;
}
1

If you want to check two different directories for the same URI use this config:

server {
...
    root /var/www/my-site/public/;
...
    index index.php index.html index.htm;
...
    location / {
        root /var/www/old-site/dist/;
        try_files $uri $uri/ /index.php$is_args$args;
    }
...
}

If Nginx couldn't find file in /var/www/old-site/dist/ directory, then it will try file in /var/www/my-site/public/ directory, but as we said to Nginx to try files with $uri $uri/ /index.php$is_args$args patterns, so Nginx will try /index.php$is_args$args in /var/www/my-site/public/ directory. not $uri

If you want to complete your fallthrough, then replace /index.php$is_args$args with /fallthrough$uri and then add the location /fallthrough { ... } with the alias key to your target directory.

https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/#root-inside-location-block

Mahdi Aslami Khavari
  • 1,755
  • 15
  • 23