Nginx -- static file serving confusion with root & alias
NginxNginx Problem Overview
I need to serve my app through my app server at 8080
, and my static files from a directory without touching the app server. The nginx config I have is something like this...
# app server on port 8080
# nginx listens on port 8123
server {
listen 8123;
access_log off;
location /static/ {
# root /var/www/app/static/;
alias /var/www/app/static/;
autoindex off;
}
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
Now, with this config, everything is working fine. Note that the root
directive is commented out.
If I activate root
and deactivate the alias
-- it stops working. However, when I remove the trailing /static/
from the root
it starts working again.
Can someone explain what's going on. Also please explain clearly and verbosely what are the differences between root
and alias
, and their purposes.
Nginx Solutions
Solution 1 - Nginx
There is a very important difference between the root
and the alias
directives. This difference exists in the way the path specified in the root
or the alias
is processed.
root
- the
location
part is appended toroot
part - final path =
root
+location
alias
- the
location
part is replaced by thealias
part - final path =
alias
To illustrate:
Let's say we have the config
location /static/ {
root /var/www/app/static/;
autoindex off;
}
In this case the final path that Nginx will derive will be
/var/www/app/static/static
This is going to return 404
since there is no static/
within static/
This is because the location part is appended to the path specified in the root
. Hence, with root
, the correct way is
location /static/ {
root /var/www/app/;
autoindex off;
}
On the other hand, with alias
, the location part gets dropped. So for the config
location /static/ {
alias /var/www/app/static/;
autoindex off; ↑
} |
pay attention to this trailing slash
the final path will correctly be formed as
/var/www/app/static
In a way this makes sense. The alias
just let's you define a new path to represent an existing "real" path. The location part is that new path, and so it gets replaced with the real path. Think of it as a symlink.
Root, on the other hand is not a new path, it contains some information that has to be collated with some other info to make the final path. And so, the location part is used, not dropped.
alias
The case for trailing slash in There is no definitive guideline about whether a trailing slash is mandatory per Nginx documentation, but a common observation by people here and elsewhere seems to indicate that it is.
A few more places have discussed this, not conclusively though.
https://serverfault.com/questions/375602/why-is-my-nginx-alias-not-working
Solution 2 - Nginx
as say as @treecoder
>In case of the root
directive, full path is appended to the root including the location part, whereas in case of the alias
directive, only the portion of the path NOT including the location part is appended to the alias.
A picture is worth a thousand words
for root
:
for alias
:
Solution 3 - Nginx
In your case, you can use root
directive, because $uri
part of the location
directive is the same with last root
directive part.
> Nginx documentation advices it as well:
When location matches the last part of the directive’s value:
> location /images/ { > alias /data/w3/images/; > } > > it is better to use the root directive instead: > > location /images/ { > root /data/w3; > }
and root
directive will append $uri
to the path.
Solution 4 - Nginx
Just a quick addendum to @good_computer's very helpful answer, I wanted to replace to root of the URL with a folder, but only if it matched a subfolder containing static files (which I wanted to retain as part of the path).
For example if file requested is in /app/js
or /app/css
, look in /app/location/public/[that folder]
.
I got this to work using a regex.
location ~ ^/app/((images/|stylesheets/|javascripts/).*)$ {
alias /home/user/sites/app/public/$1;
access_log off;
expires max;
}
Solution 5 - Nginx
alias
is used to replace the location part path (LPP) in the request path, while the root
is used to be prepended to the request path.
They are two ways to map the request path to the final file path.
alias
could only be used in location block, and it will override the outside root
.
alias
and root
cannot be used in location block together.
Solution 6 - Nginx
server {
server_name xyz.com;
root /home/ubuntu/project_folder/;
client_max_body_size 10M;
access_log /var/log/nginx/project.access.log;
error_log /var/log/nginx/project.error.log;
location /static {
index index.html;
}
location /media {
alias /home/ubuntu/project/media/;
}
}
Server block to live the static page on nginx.
Solution 7 - Nginx
In other words on keeping this brief: in case of root
, location argument specified is part of filesystem's path and URI . On the other hand — for alias
directive argument of location statement is part of URI only
So, alias
is a different name that maps certain URI to certain path in the filesystem, whereas root
appends location argument to the root path given as argument to root
directive.
Solution 8 - Nginx
Though my answer is not needed, But I think It is necessary to add this, root
and alias
works differently when is come to regex.
location ~ /static/my.png$ {
alias /var/www/static/;
access_log off;
expires max;
}
In this case the regex match is not going to add with alias, nginx will search only /var/www/static/
not /var/www/static/my.png
. You have to use regex capture.
location ~ /static/my.png$ {
root /var/www;
access_log off;
expires max;
}
In this case the matched url going to add with root, nginx will search /var/www/static/my.png
.