Nginx - root versus alias, for serving single files?
Solution 1:
Well, these two directives are slightly functional different because you do not use exact match in the latter case. So, /robots.txt1111
will match your second location too.
location =/robots.txt { root /home/www/static/; }
is an exact functional equivalent of your first directive.
Solution 2:
Yes, there is a difference: With "alias" you can .. well alias to another file name, like
location /robots.txt { alias /home/www/static/any-filename.txt; }
whereas
location /robots.txt { root /home/www/static/; }
forces you to name your file on the server also robots.txt. I use the first option since I like to name my robots files on my server as tld.domain.subdomain-robots.txt; e.g
location /robots.txt { alias /home/www/static/ch.notex.static-robots.txt; }
Solution 3:
I think it's worth explicitly laying out that nginx is operating on prefixes and not files per se. In the first case,
location /robots.txt { alias /home/www/static/robots.txt; }
nginx replaces the string prefix /robots.txt
in the URL path with /home/www/static/robots.txt
and then uses the result as a filesystem path. Represented as pseudocode, this would be something like:
if urlPath.startsWith("/robots.txt") {
fsPath := "/home/www/static/robots.txt" + urlPath.stripPrefix("/robots.txt")
serveFile(fsPath)
}
So /robots.txt
is served from /home/www/static/robots.txt
because /robots.txt
stripped of the /robots.txt
prefix is the empty string, and appending the empty string to /home/www/static/robots.txt
leaves it unchanged. But, /robots.txt1
would be served from /home/www/static/robots.txt1
and /robots.txt/foobar
would be served from /home/www/static/robots.txt/foobar
. Those files may not exist, causing nginx to send a 404 response, and it's likely that robots.txt
is not a directory anyway, but nginx doesn't know that in advance, and this is all based on string prefixes and not what appears to be a file or directory by the absence or presence of a trailing slash.
Whereas, in the second case,
location /robots.txt { root /home/www/static/; }
nginx inserts the string /home/www/static/
at the beginning of the URL path and then uses the result as a file system path. In pseudocode, this would be something like:
if urlPath.startsWith("/robots.txt") {
fsPath := "/home/www/static/" + urlPath
serveFile(fsPath)
}
This has the exact same result as the first case, but for a different reason. There's no prefix stripping, but since every URI path has to contain the prefix /robots.txt
, then the file system paths will always start with /home/www/static//robots.txt
which is equivalent to /home/www/static/robots.txt
.
Of course, the pseudocode doesn't quite tell the whole story, as e.g. nginx won't blindly use raw URL paths like /../../../etc/passwd
, the try_files
directive changes the behavior of root
/alias
, and there are constraints on where alias
can be used.