93

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.

0

4 Answers 4

94

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.

4
  • 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, 2011 at 17:20
  • @Cyclops yes, you may use = in both cases. Jun 9, 2011 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, 2011 at 13:36
  • @Cyclops Basically, there is no such reason.
    – Alex
    Jun 9, 2011 at 14:05
64

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

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.

1

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)

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .