nginxで、locationディレクティブによって、読み込んでくるディレクトリを変更しようとしたところ、詰まりました。
最初は以下のような形で書いていました。
server {
location / {
root /usr/local/www/nginx/;
index index.html;
try_files $uri $uri/ /index.html;
}
location /admin/ {
root /usr/local/www/nginx/admin/;
index index.html;
try_files $uri $uri/ /index.html;
}
}
/~
にアクセスしてきた場合には/usr/local/www/nginx以下のファイルを読み込んできて、
/admin/~
にアクセスしてきた場合には/usr/local/www/nginx/admin以下のファイルを読み込んでくるようにしたかったのです。
しかし、これではうまくいきませんでした。
nginxのrootのパス処理方法
例えば/admin/
にアクセスしたら、/usr/local/www/nginx/admin/index.html
が読み込まれるかと思いきや、そうではありません。この場合はroot+locationのパスにアクセスするので、/usr/local/www/nginx/admin/admin/index.html
を読み込もうとしてしまいます。
しかし、このファイルは存在しないので、try_filesによって再びindex.htmlを読み込もうとしますが、これも/usr/local/www/nginx/admin/admin/index.html
にアクセスするので、無限ループに陥ってしまいます。
その結果、以下のようなエラーが出ます。
rewrite or internal redirection cycle while internally redirecting to "/admin/index.html"
最終的には、location /
で指定しているroot /usr/local/www/nginx/
より、/usr/local/www/nginx/index.html
が読み込まれるようです。
これを解決したい場合には、rootで読み込まれるパスがroot+locationであることから、以下のように修正すると良いでしょう。
server {
location / {
root /usr/local/www/nginx/;
index index.html;
try_files $uri $uri/ /index.html;
}
location /admin/ {
root /usr/local/www/nginx/;
try_files $uri $uri/ /admin/index.html;
}
}
location /admin/
からはindexを外してやりましょう。
indexを残しておくと、/admin/
にアクセスした場合に/usr/local/www/nginx/index.html
が優先して読み込まれてしまいます。これは、あくまでもrootが/usr/local/www/nginx/
であり、/admin/
のindexとして読み込んできているのが/usr/local/www/nginx/index.html
だからです。
なお、indexにindex /admin/index.html;
と指定してやればよさそうですが、indexには相対パスは指定できないそうで、エラーが出てしまいます。
nginx: [warn] only the last index in "index" directive should be absolute in
他にも、エイリアスを使用する書き方もあります。
aliasとは
エイリアスとは、ショートカットリンクのようなイメージです。それ自体が実体ではないものの、別の場所にある実体を参照できるようにしたものです。
エイリアスとは - IT用語辞典 e-Words
nginxの場合どうなるか見ていきましょう。
server {
location / {
root /usr/local/www/nginx/;
index index.html;
try_files $uri $uri/ /index.html;
}
location /admin/ {
alias /usr/local/www/nginx/admin/;
try_files $uri $uri/ /admin/index.html;
}
}
/admin/~
にアクセスした場合、/usr/local/www/nginx/admin/
を読み込んできます。rootがroot+locationを読み込んできたのに対して、こちらはaliasに指定したディレクトリをそのまま読み込んでくるという違いがあります。
つまり、/usr/local/www/nginx/admin/admin/
にはならないということです。
rootとaliasの違い
rootは、読み込んでくるrootディレクトリです。serverもしくはlocationディレクティブ内で使用できます。indexなどにも影響します。仕様として、root+locationを読み込んできます。
一方、aliasはlocationディレクティブのみで使用できます。
直接指定したディレクトリを読み込みにいきます。
rootとalias、どちらを使うべきか
公式ドキュメントで、locationがaliasのパスの最後に一致する場合(今回例で挙げてきたような場合)は、rootを使うのが良いと書かれています。
http://nginx.org/en/docs/http/ngx_http_core_module.html#alias
一方、rootで指定しているディレクトリとは違う場所から読み込んでくる場合には、aliasを使用すると良いそうです。
http://nginx.org/en/docs/http/ngx_http_core_module.html#root
serverディレクティブで基本となるrootを設定しておいて、そのrootディレクトリ内にlocationごとのディレクトリが含まれている場合にはrootを使っていき、その基本となるrootから外れるときだけaliasを使うみたいな形で使い分けると良いのかなと思いました。
ただ、そもそも今回みたいな場合は、大本のディレクトリの中にadminを入れるとしてしまってますが、フロント画面と管理画面は別にしておいたほうが良いと思うので、frontとadminのディレクトリを分けて、それぞれでroot設定するというほうがよさそうですね。