簡単そうに見えたのだが思い通りにいかない.
優先順位というか, 処理順序というか. ここらの話.
location = / {
# matches the query / only.
[ configuration A ]
}
location / {
# matches any query, since all queries begin with /, but regular
# expressions and any longer conventional blocks will be
# matched first.
[ configuration B ]
}
location /documents/ {
# matches any query beginning with /documents/ and continues searching,
# so regular expressions will be checked. This will be matched only if
# regular expressions don't find a match.
[ configuration C ]
}
location ^~ /images/ {
# matches any query beginning with /images/ and halts searching,
# so regular expressions will not be checked.
[ configuration D ]
}
location ~* \.(gif|jpg|jpeg)$ {
# matches any request ending in gif, jpg, or jpeg. However, all
# requests to the /images/ directory will be handled by
# Configuration D.
[ configuration E ]
}
Nginx location priority - Stack Overflow
なので公式 wiki/recipe を見ながら少し整理.
PHP FastCGI Example | NGINX
Codeigniter | NGINX
Drupal | NGINX
osCommerce | NGINX
WordPress | NGINX
公式にて書式はこう.
Syntax: location [ = | ~ | ~* | ^~ ] uri { ... }
Module ngx_http_core_module
複数のlocationブロックがある場合, リクエストのURL内該当文字列に対して優先順位の順番にマッチを確認していき, 最初にマッチしたロケーション設定(処理)ひとつが反映される.
1.「=」完全一致
2.「^~」前方検索 (マッチ文字列の長い順)
3.「~」正規表現 (記述順)
4.「~*」正規表現 (記述順・大小文字を考慮しない)
5.「(なし)」前方検索 (マッチ文字列の長い順)
これに加えて, それぞれの設定(処理)自体の優先順位を考慮しておかないと, 「アクセス拒否したつもりが丸出し」や「PHPスクリプトのダウンロード公開」などとなってしまう.
1. 特殊ファイルのログ制御
2. ディレクトリ単位のアクセス拒否
3. ファイル単位のアクセス拒否
4. PHPファイルの実行 (PHP-FPM)
5. 静的ファイルのキャッシュ期限の設定
6. フロントコントローラへのリクエスト付け替え
これら2つの優先順位を考慮にいれながら書かれている公式wiki/recipeの設定は, ある程度おおまかにパターン化できる.
1.「=」特殊ファイルのログ制御
2. 「^~」ディレクトリ単位のアクセス拒否
3.「~」ファイル単位のアクセス拒否
4.「~」PHPファイルの設定・実行 (PHP-FPM)
5.「~*」静的ファイルのキャッシュ期限の設定
6.「なし」フロントコントローラへのリクエスト付け替え
頻出しそうなのを順序を守って箇条書きに.
# 1. specific files
location = /favicon.ico {
log_not_found off;
access_log off;
}
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
# 2. deny directories
location ^~ /conf/ {
return 403;
}
# 3. deny files
location ~ (^|/)\. {
return 403;
}
location ~ \.(txt|log)$ {
allow 192.168.0.0/16;
deny all;
}
# 4. php scripts
location ~ [^/]\.php(/|$) {
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
if (!-f $document_root$fastcgi_script_name) {
return 404;
}
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
}
# 5. static content files
location ~* \.(?:ico|css|js|gif|jpe?g|png)$ {
expires max;
}
# 6. others(internal rewrite)
location / {
try_files $uri $uri/ index.php;
}
実際はこれらに加えてさらに, 内部/外部での リライト/リダイレクトなどを記述して location 設定を複数またいでいくことになると, 大量に記述された apache mod_rewrite 設定のように直感的に設定できなくなっていくので locationブロックに関してはテンプレ化しておくのがいいように思う.
そもそもは「if」や「locationを使った入れ子」で混乱したので.
nginxのlocation設定について、優先順位の基本と意外な罠
If Is Evil | NGINX
if ($request_uri = /) {
set $test A;
}
if ($host ~* teambox.com) {
set $test "${test}B";
}
if ($http_cookie !~* "auth_token") {
set $test "${test}C";
}
if ($test = ABC) {
proxy_pass http://teambox-cms.heroku.com;
break;
}
nginx hack for multiple conditions
手をつける前に, ある程度の歴史や経緯を分かっておく必要があったかな.
Nginx Configuration Primer
まあいいか.
みんなも reload したらチェックしてみよう.
$ curl -L http://yourhost.com/ -o /dev/null \
-w '%{http_code} %{content_type} %{size_download} %{url_effective}\n' \
-s
200 text/html; charset=UTF-8 1334 http://yourhost.com/