58

After many hours getting nginx to serve single files such as robots.txt (hint: clear your browser cache each time), I wound up with two different ways, one using the alias directive, and one using the root directive, like so:

location /robots.txt { alias /home/www/static/robots.txt; }
location /robots.txt { root /home/www/static/;  }

Is there any functional difference between the two? Or security issues? Any conflicts with other directives? (Both seemed fine with another /static location). Or any reason to pick one over the other?

Note - I didn't use both at the same time :) Rather I tried each, one at a time, and both worked. I'm not asking how they both interact together in the same file, but which one would be better to use.

64

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.

  • Good point, thanks. But you can use an = in both cases, correct? Or does it only apply to root? Also, see my edit - I didn't mean to use both at once. :) – Cyclops Jun 8 '11 at 17:20
  • @Cyclops yes, you may use = in both cases. – Alexander Azarov Jun 9 '11 at 7:52
  • So they would be the same - is there any reason to pick one directive over the other? Is my main question. – Cyclops Jun 9 '11 at 13:36
  • @Cyclops Basically, there is no such reason. – Alex Jun 9 '11 at 14:05
36

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; }
1

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.

0

There is a difference, when the alias is for a whole directory.

    location ^~ /data/ { alias /home/www/static/data/; }

will work, while

    location ^~ /data/ { root /home/www/static/data/; }

won't do. This would have to be

    location ^~ /data/ { root /home/www/static/; }

(Easy to confuse)

Your Answer

By clicking "Post Your Answer", you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.