- 技術 💻
nginx location書き方|優先順位とtry_filesをcurlで検証
nginx の location とは、リクエストされた URI(パス)ごとに処理を振り分けるための設定ブロックです。 location 修飾子 パターン { ... } の形で書き、どの location が選ばれるかは「完全一致 = → 最長の前方一致 → 正規表現を上から順に」という決まった順番で判定されます。書いた順番がそのまま優先されるわけではないため、思った location に当たらないときは、この判定順を知ると原因がすぐにわかります。
この記事では、nginx 1.24.0 を実際に起動し、20個の URI を curl で投げて「どの location に当たったか」を表にしました。 あわせて、try_files を使った SPA・PHP・名前付き location(@fallback)の書き方、root と alias の違い、rewrite と return の使い分け、nginx -t で出るエラー文と直し方まで、実行結果つきでまとめています。
nginx locationの早見表
修飾子は6種類です。 この表と次のフローチャートで、優先順位の判断はほぼ足ります。
| 書き方 | 種類 | マッチ方法 | 大文字小文字 | 判定の順番 | 例 |
|---|---|---|---|---|---|
location = /login |
完全一致 | URI 全体が一致 | 区別する | 最優先。一致したら即決定 | /login のみ(/login/ は対象外) |
location ^~ /static/ |
前方一致(正規表現を止める) | 先頭が一致 | 区別する | 最長の前方一致がこれなら即決定 | /static/a.png |
location ~ \.(png|jpg)$ |
正規表現 | 正規表現 | 区別する | 前方一致の後、設定ファイルの上から順、最初の一致で決定 | /images/a.png |
location ~* \.(css|js)$ |
正規表現 | 正規表現 | 区別しない | ~ と同じ(上から順) |
/app.js、/APP.JS |
location /images/ |
前方一致(修飾子なし) | 先頭が一致 | 区別する | 最長のものを覚えておき、正規表現が外れたら採用 | /images/a.gif |
location @fallback |
名前付き | URI ではマッチしない | ― | try_files や error_page から内部的に呼ばれるだけ |
try_files $uri @fallback; |
| よくあるやりたいこと | 書き方 |
|---|---|
| トップページだけ特別扱い | location = / { ... } |
| 静的ファイル置き場を正規表現より優先 | location ^~ /static/ { ... } |
| 拡張子で振り分け | location ~* \.(css|js|png|jpg)$ { ... } |
| それ以外すべて | location / { ... } |
| ファイルが無ければ index.html(SPA) | try_files $uri $uri/ /index.html; |
| ファイルが無ければ PHP(WordPress 型) | try_files $uri $uri/ /index.php?$args; |
| ファイルが無ければ別サーバーへ | try_files $uri @backend; + location @backend { proxy_pass ...; } |
| URL を別の場所に向ける | alias /path/;(location 部分を置き換え) |
| リダイレクト | return 301 /new; |
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「nginx location書き方|優先順位とtry_filesをcurlで検証」
検証環境とバージョン
この記事の実行結果は nginx 1.24.0(Ubuntu パッケージ)で取得しました。 2026年10月1日時点の公式ダウンロードページでは、mainline が 1.31.6、stable が 1.30.5 です。location の判定順や try_files・alias の基本動作は、1.24 から最新版まで同じ仕様として公式ドキュメント(ngx_http_core_module)に記載されています。
| 項目 | 内容 |
|---|---|
| nginx | 1.24.0(nginx -v → nginx version: nginx/1.24.0 (Ubuntu)) |
| 確認方法 | 各 location で return 200 "ラベル" を返し、curl で当たった location を確認 |
| 使ったポート | 7793(優先順位)、7794(バックエンド役)、7795(try_files 等)、7796(proxy_pass) |
| 起動方法 | nginx -p 作業フォルダ -c 作業フォルダ/nginx.conf(システムの設定とは別に起動) |
「どの location に当たったか」は、各 location に return 200 "名前"; を書いて curl するのが一番確実です。 本番の設定を調べるときも、検証用に add_header X-Loc "名前" always; を仮に入れると、curl -I で見分けられます。
locationの優先順位とフローチャート
nginx は次の順番で location を選びます。 公式ドキュメントの説明を図にしました。
flowchart TD
S[リクエストURI(正規化済み・クエリ文字列なし)] --> E{= の完全一致がある?}
E -- はい --> E1[その location で決定]
E -- いいえ --> P[前方一致(修飾子なし・^~)の中で一番長く一致するものを探して覚える]
P --> C{覚えたものが ^~ ?}
C -- はい --> C1[その location で決定(正規表現は見ない)]
C -- いいえ --> R{正規表現 ~ / ~* を設定ファイルの上から順に試す}
R -- 最初に一致 --> R1[その正規表現 location で決定]
R -- どれも不一致 --> R2[覚えておいた最長の前方一致で決定]
ポイントは3つです。
| ポイント | 内容 |
|---|---|
| 前方一致は「書いた順」ではなく「長さ」 | /images/ と /images/icons/ なら、長い方が選ばれる |
| 正規表現は「書いた順」 | 一致する正規表現が複数あれば、上に書いたものが勝つ |
| 正規表現は前方一致より強い | 前方一致で見つかっても、正規表現が一致すればそちらが選ばれる(^~ と = を除く) |
また、判定に使う URI はクエリ文字列(? 以降)を含まず、%XX のデコードや .. の解決などで正規化された後のものです。
20個のURIでどのlocationに当たるか検証
次の設定を起動して、URI ごとの結果を curl で確かめました。 return 200 で、当たった location の番号を返すだけの設定です。
# 優先順位テスト用(nginx 1.24.0)
server {
listen 127.0.0.1:7793;
location = /login { return 200 "L1 = /login\n"; }
location ^~ /static/ { return 200 "L2 ^~ /static/\n"; }
location ~ \.(png|jpg)$ { return 200 "L3 ~ \\.(png|jpg)\n"; }
location ~* \.(css|js)$ { return 200 "L4 ~* \\.(css|js)\n"; }
location /images/ { return 200 "L5 /images/\n"; }
location /images/icons/ { return 200 "L6 /images/icons/\n"; }
location /api { return 200 "L7 /api\n"; }
location ~ ^/docs/ { return 200 "L8 ~ ^/docs/\n"; }
location ~ \.html$ { return 200 "L9 ~ \\.html\n"; }
location / { return 200 "L10 /\n"; }
}
for u in / /login /login/ /loginx /static/a.png /images/a.png /images/a.gif \
/images/icons/a.gif /images/icons/a.png /app.js /APP.JS /app.PNG \
/api /api/users /apiv2 /docs/a.html /blog/a.html /docs/a.css; do
printf "%-22s " "$u"; curl -s "http://127.0.0.1:7793$u"
done
printf "%-22s " "/static/../login"; curl -s --path-as-is "http://127.0.0.1:7793/static/../login"
printf "%-22s " "/LOGIN"; curl -s "http://127.0.0.1:7793/LOGIN"
printf "%-22s " "/login?x=1"; curl -s "http://127.0.0.1:7793/login?x=1"
実行結果:
/ L10 /
/login L1 = /login
/login/ L10 /
/loginx L10 /
/static/a.png L2 ^~ /static/
/images/a.png L3 ~ \.(png|jpg)
/images/a.gif L5 /images/
/images/icons/a.gif L6 /images/icons/
/images/icons/a.png L3 ~ \.(png|jpg)
/app.js L4 ~* \.(css|js)
/APP.JS L4 ~* \.(css|js)
/app.PNG L10 /
/api L7 /api
/api/users L7 /api
/apiv2 L7 /api
/docs/a.html L8 ~ ^/docs/
/blog/a.html L9 ~ \.html
/docs/a.css L4 ~* \.(css|js)
/static/../login L1 = /login
/LOGIN L10 /
/login?x=1 L1 = /login
結果を「なぜそうなったか」で整理すると次のとおりです。
| URI | 当たった location | 理由 |
|---|---|---|
/login |
L1 = /login |
完全一致が最優先 |
/login/ |
L10 / |
末尾の / があると完全一致にならない |
/loginx |
L10 / |
完全一致は前方一致として扱われない |
/login?x=1 |
L1 | クエリ文字列は判定に使われない |
/LOGIN |
L10 | = は大文字小文字を区別する |
/static/a.png |
L2 ^~ /static/ |
^~ が最長前方一致なので、.png の正規表現を見ずに決定 |
/images/a.png |
L3 正規表現 | 前方一致 /images/ より正規表現が優先 |
/images/a.gif |
L5 /images/ |
正規表現に一致しないので、覚えておいた前方一致 |
/images/icons/a.gif |
L6 /images/icons/ |
前方一致は最長が選ばれる(書いた順ではない) |
/images/icons/a.png |
L3 正規表現 | 最長前方一致があっても、正規表現が勝つ |
/app.js と /APP.JS |
L4 ~* |
~* は大文字小文字を区別しない |
/app.PNG |
L10 | ~ は区別するので .PNG は L3 に一致しない |
/api、/api/users、/apiv2 |
L7 /api |
/api は文字列の前方一致なので /apiv2 にも当たる |
/docs/a.html |
L8 ~ ^/docs/ |
正規表現は上から順。L8 が L9 より上にある |
/docs/a.css |
L4 ~* |
L4 が L8 より上にあるため、/docs/ より拡張子の正規表現が先に一致 |
/static/../login |
L1 | URI が /login に正規化されてから判定される |
特に気をつけたいのは /apiv2 と /docs/a.css の2つです。 /api のように末尾スラッシュなしで書くと、/api で始まるすべてのパスに当たります。/api/ 配下だけにしたいなら location /api/ と書き、/api 単体は location = /api { return 301 /api/; } などで扱うと意図どおりになります。また、正規表現同士は書いた順で決まるため、具体的な正規表現(パスで絞るもの)を上に、汎用的な正規表現(拡張子だけのもの)を下に置くと読みやすくなります。
try_filesの書き方
try_files は「左から順にファイルやディレクトリがあるか確かめ、最初に見つかったものを返し、どれも無ければ最後の引数に進む」ディレクティブです。 最後の引数だけは特別で、URI(内部リダイレクト)、=404 のようなステータスコード、@名前 の名前付き location のいずれかを書きます。
| 引数の例 | 意味 |
|---|---|
$uri |
root + URI のファイルがあれば返す |
$uri/ |
ディレクトリがあれば、index で指定したファイルを返す |
$uri.html |
拡張子なし URL で .html を探す |
=404 |
(最後に置く)404 を返す |
/index.html |
(最後に置く)/index.html へ内部リダイレクトし、location を選び直す |
/index.php?$args |
(最後に置く)クエリ文字列を付けて PHP 側の location へ |
@backend |
(最後に置く)名前付き location @backend へ |
検証用の設定は次のとおりです。ファイル構成も載せます。
ngx/
├── html/index.html … <h1>top</h1>
├── html/about.html … <h1>about</h1>
├── html/assets/app.js
├── spa/index.html … <h1>SPA shell</h1>
├── files/report.txt … report body
├── files/docs/guide.txt … docs page
└── secret/key.txt … do-not-show
server {
listen 127.0.0.1:7795;
root /path/to/ngx/html;
index index.html;
location / { try_files $uri $uri/ =404; } # 静的サイト
location /spa/ { root /path/to/ngx; try_files $uri $uri/ /spa/index.html; } # SPA
location /blog/ { try_files $uri $uri/ /index.php?$args; } # WordPress 型
location ~ \.php$ { return 200 "php handler: uri=$uri args=$args\n"; } # PHP の代わり
location /download/ { alias /path/to/ngx/files/; }
location /dl { alias /path/to/ngx/files/; } # 末尾スラッシュ不一致の例
location /docs/ { root /path/to/ngx/files; }
location /legacy/ { try_files $uri @backend; }
location @backend { proxy_pass http://127.0.0.1:7794; }
location = /old-page { return 301 /about.html; }
location /news/ { rewrite ^/news/(\d+)$ /about.html?id=$1 last; return 404; }
}
# バックエンド役(受け取った URI を返すだけ)
server {
listen 127.0.0.1:7794;
location / { return 200 "backend: request_uri=$request_uri\n"; }
}
この環境には PHP-FPM が入っていないため、PHP の location は return で「どの URI とクエリで届いたか」を表示する形にしています。 実際には fastcgi_pass を書く場所です。
静的サイト(=404)
for u in / /about.html /assets/app.js /nothing; do
echo "== $u"; curl -s -i "http://127.0.0.1:7795$u" | head -1; curl -s "http://127.0.0.1:7795$u" | head -1
done
== /
HTTP/1.1 200 OK
<h1>top</h1>
== /about.html
HTTP/1.1 200 OK
<h1>about</h1>
== /assets/app.js
HTTP/1.1 200 OK
console.log(1)
== /nothing
HTTP/1.1 404 Not Found
<html>
/ は $uri/ に一致し、index index.html; で index.html が返りました。存在しない /nothing は最後の =404 で 404 になります。
SPAのフォールバック(/index.html)
React や Vue などの SPA は、どの URL でも同じ HTML を返し、画面の切り替えはブラウザ側で行います。 そのため「ファイルが無ければ index.html」という書き方をします。
== /spa/
HTTP/1.1 200 OK
<h1>SPA shell</h1>
== /spa/users/42
HTTP/1.1 200 OK
<h1>SPA shell</h1>
== /spa/index.html
HTTP/1.1 200 OK
<h1>SPA shell</h1>
/spa/users/42 というファイルは存在しませんが、最後の /spa/index.html に内部リダイレクトされて SPA の HTML が返りました。 存在しない API パスまで HTML で返したくない場合は、location /api/ { ... } を別に用意して SPA の location に入らないようにします。
PHP(WordPress型)のフォールバック
== /blog/hello
HTTP/1.1 200 OK
php handler: uri=/index.php args=
== /blog/hello?p=2
HTTP/1.1 200 OK
php handler: uri=/index.php args=p=2
/index.php?$args に内部リダイレクトされ、location の選び直しで ~ \.php$ に入りました。 $args を付けておくと、元のクエリ文字列 p=2 が引き継がれます。WordPress の公式な nginx 設定例でも同じ形(try_files $uri $uri/ /index.php?$args;)が使われています。
名前付きlocation(@fallback)へ渡す
名前付き location は URI では選ばれず、try_files などから呼ばれたときだけ使われます。 URI を書き換えずにそのまま渡せるのが特徴です。
== /legacy/x
HTTP/1.1 200 OK
backend: request_uri=/legacy/x
== /legacy/y?a=1
HTTP/1.1 200 OK
backend: request_uri=/legacy/y?a=1
ファイルが無いので @backend に渡り、元の URI とクエリ文字列のままバックエンドに届きました。 「静的ファイルがあれば nginx が返し、無ければアプリに任せる」構成でよく使います。
rootとaliasの違い
root は「root のパス + URI 全体」、alias は「location に一致した部分を alias のパスに置き換え」でファイルを探します。
| 設定 | リクエスト | 探すファイル |
|---|---|---|
location /docs/ { root /srv/files; } |
/docs/guide.txt |
/srv/files/docs/guide.txt |
location /download/ { alias /srv/files/; } |
/download/report.txt |
/srv/files/report.txt |
location /download/ { root /srv/files/; } |
/download/report.txt |
/srv/files/download/report.txt(download フォルダが必要) |
検証結果は次のとおりです。
== /download/report.txt (alias)
HTTP/1.1 200 OK
report body
== /docs/guide.txt (root)
HTTP/1.1 200 OK
docs page
alias を使うべき場面を root で書くと 404 になります。 別ポート(7797)に location /download/ { root .../files/; } を書いて確かめたところ、error.log に探したパスがそのまま出ました。
/download/report.txt 404
[error] ... open() ".../ngx/files/download/report.txt" failed (2: No such file or directory), client: 127.0.0.1, server: , request: "GET /download/report.txt HTTP/1.1", host: "127.0.0.1:7797"
404 のときは error.log の open() "..." を見れば、nginx が実際に探したパスがわかります。 このパスを見て root と alias のどちらが合っているか判断すると早く解決します。
aliasとlocationの末尾スラッシュはそろえる
alias は location の文字列部分をそのまま置き換えるため、末尾スラッシュがそろっていないと意図しないパスが組み立てられます。 location /dl { alias .../files/; } のように、location 側だけスラッシュがない設定で確かめました。
curl -s --path-as-is http://127.0.0.1:7795/dl/report.txt
curl -s --path-as-is http://127.0.0.1:7795/dl../secret/key.txt
report body
do-not-show
/dl../secret/key.txt の /dl が .../files/ に置き換わり、.../files/../secret/key.txt、つまり files フォルダの外のファイルが返りました。 location と alias の両方に末尾スラッシュを付けた設定(location /dl/ { alias .../files/; }、ポート 7797)では、同じリクエストが 404 になりました。
/dl/report.txt 200
/dl../secret/key.txt 404
| 書き方 | /dl/report.txt |
/dl../secret/key.txt |
|---|---|---|
location /dl { alias .../files/; } |
200 | 200(files の外が見える) |
location /dl/ { alias .../files/; } |
200 | 404 |
alias を使うときは「location も alias も末尾スラッシュあり」にそろえると覚えておくと安心です。正規表現の location で alias を使う場合は、公式ドキュメントのとおりキャプチャ($1)でパスを組み立てる必要があります(例: location ~ ^/users/(.+\.(?:gif|jpe?g|png))$ { alias /data/w3/images/$1; }。この形は今回未実行です)。
SPAでrootを重ねて書いたとき
location /spa/ の中で root .../spa; と書くと、URI の /spa/ がさらに足されて .../spa/spa/ を探します。 7797 で試すと、フォールバック先の /index.html が server 全体の index(トップページ)になり、SPA ではない HTML が返りました。
$ curl -s http://127.0.0.1:7797/spa/users/42
<h1>top</h1>
| 書き方 | 結果 |
|---|---|
location /spa/ { root /x/spa; try_files $uri $uri/ /index.html; } |
/x/spa/spa/... を探し、トップの index.html が返る |
location /spa/ { root /x; try_files $uri $uri/ /spa/index.html; } |
/x/spa/index.html が返る(意図どおり) |
location /spa/ { alias /x/spa/; try_files $uri $uri/ /spa/index.html; } |
動くが、alias と try_files の組み合わせは挙動が読みにくいので root で書ける場合は root がおすすめ |
rewriteとreturnの使い分け
URL を変えるだけなら return、正規表現で URI を組み立て直すなら rewrite を使います。 return はその場で応答を返すのでシンプルです。
== /old-page
HTTP/1.1 301 Moved Permanently
Location: http://127.0.0.1:7795/about.html
== /news/15
HTTP/1.1 200 OK
<h1>about</h1>
== /news/abc
HTTP/1.1 404 Not Found
/news/15 は rewrite ... last; で /about.html?id=15 に書き換わり、location を選び直して about.html が返りました。正規表現に一致しない /news/abc は rewrite を通り抜け、次の行の return 404 が実行されています。
| 書き方 | 動き | 向いている場面 |
|---|---|---|
return 301 /new; |
恒久リダイレクト | ページ移転、http→https |
return 302 /tmp; |
一時リダイレクト | メンテナンス時の案内 |
return 200 "text"; |
その場で本文を返す | ヘルスチェック、動作確認 |
rewrite 正規表現 置換 last; |
書き換えて location を選び直す | 内部的に別の処理へ渡す |
rewrite 正規表現 置換 break; |
書き換えて、今の location で処理を続ける | 同じ location 内でパスだけ変える |
rewrite 正規表現 置換 permanent; |
301 リダイレクト | 正規表現でまとめて移転 |
rewrite 正規表現 置換 redirect; |
302 リダイレクト | 一時的なまとめ移転 |
try_files ... /index.php?$args; |
ファイルが無いときだけ内部リダイレクト | SPA、PHP |
proxy_passの末尾スラッシュ(location側との関係)
proxy_pass に URI 部分(/ 以降)を書くと、location に一致した部分がその URI に置き換わります。 詳しくは「Nginxリバースプロキシ設定」の記事で扱っているので、ここでは location との関係だけ表にします。
| location | proxy_pass | /p1/users などへのリクエスト |
バックエンドに届いた URI |
|---|---|---|---|
/p1/ |
http://127.0.0.1:7794 |
/p1/users |
/p1/users(そのまま) |
/p2/ |
http://127.0.0.1:7794/ |
/p2/users |
/users |
/p3/ |
http://127.0.0.1:7794/v1/ |
/p3/users |
/v1/users |
/p4 |
http://127.0.0.1:7794/ |
/p4/users |
//users |
/p4 |
http://127.0.0.1:7794/ |
/p4users |
/users |
上の「届いた URI」は、バックエンド役が $request_uri を返した実際の値です。location と proxy_pass の末尾スラッシュをそろえると、//users のような二重スラッシュを避けられます。また、正規表現の location や名前付き location の中では proxy_pass に URI 部分を書けません(後述の nginx -t エラー参照)。
よくあるハマりと直し方
| 症状 | 原因 | 直し方 |
|---|---|---|
/apiv2 が /api の設定で処理される |
修飾子なしは文字列の前方一致 | location /api/ にする。/api 単体は = /api で扱う |
| 拡張子の正規表現に静的フォルダが吸われる | 正規表現は前方一致より優先 | 静的フォルダを ^~ にする |
| 正規表現の順番で結果が変わる | 正規表現は上から順に最初の一致 | 具体的なパターンを上、汎用的なパターンを下に |
/login/ が = /login に当たらない |
= は完全一致 |
必要なら = /login/ を別に書くか、return 301 で正規化 |
.PNG が ~ \.png$ に当たらない |
~ は大文字小文字を区別 |
~* を使う |
| alias で 404、または想定外のファイルが返る | location と alias の末尾スラッシュ不一致、root と alias の取り違え | 両方に末尾スラッシュ、error.log の open() パスを確認 |
| SPA でトップページの HTML が返る | location 内の root に URI が重ねて足される | root は親フォルダを指定し、フォールバックを /spa/index.html に |
| PHP でクエリ文字列が消える | /index.php だけで $args を付けていない |
/index.php?$args にする |
{3} を含む正規表現でエラー |
{ がブロックの開始と解釈される |
正規表現をダブルクォートで囲む |
| return の文字列でエラー | $ の後ろが変数名として読まれる |
文字列内の $ を避ける、または変数を使う形に |
nginx -tのエラー文と直し方
設定を変えたら nginx -t で文法チェックしてから reload します。 location まわりで出るエラーを、わざと間違えた設定で出しました(パスは /etc/nginx に置き換えて表示しています)。
sudo nginx -t && sudo systemctl reload nginx
| エラー文(nginx 1.24.0 の実際の出力) | 原因 | 直し方 |
|---|---|---|
duplicate location "/" in /etc/nginx/bad/dup.conf:8 |
同じ server に同じ location が2つ | 片方を消すか、include 先の重複を探す |
"proxy_pass" cannot have URI part in location given by regular expression, or inside named location, or inside "if" statement, or inside "limit_except" block |
正規表現 location の proxy_pass に /v1/ などの URI |
proxy_pass は http://host までにし、パスは rewrite で調整 |
unexpected "}" in ...:7 |
直前の行のセミコロン忘れ | 行末に ; を付ける |
unexpected end of file, expecting "}" |
閉じかっこ } の不足 |
ブロックの対応を確認 |
invalid number of arguments in "try_files" directive |
try_files の引数が1つだけ | 最後に =404 などのフォールバックを足す |
unknown directive "locaton" |
ディレクティブ名の打ち間違い | スペルを直す |
unknown directive "3}$" |
正規表現の {3} をクォートしていない |
location ~ "^/item/\d{3}$" とダブルクォートで囲む |
named location "@x" can be on the server level only |
名前付き location を入れ子にした | server 直下に書く |
the "alias" directive cannot be used inside the named location |
名前付き location に alias | root を使う、または通常の location に移す |
location "/a/b" cannot be inside the exact location "/a" |
= の中に location を入れ子 |
入れ子をやめて並べる |
location "/b/" is outside location "/a/" |
入れ子の location が親のパスで始まっていない | 子を /a/b/ のように親のパスから書く |
pcre2_compile() failed: missing closing parenthesis in "^/(api" |
正規表現のかっこ不足 | 正規表現を直す |
invalid variable name |
return の文字列などに $ の後ろが不正な文字 |
$ を含めない、変数名を正しく書く |
エラー文の最後の「ファイル名:行番号」がそのまま修正箇所です。 include を多用している場合も、どのファイルの何行目かが表示されます。
設定を書くときのチェックリスト
| チェック | 確認方法 |
|---|---|
| 前方一致は「最長」、正規表現は「上から順」と意識したか | 本記事の早見表とフローチャート |
静的ファイル置き場に ^~ が必要か考えたか |
拡張子の正規表現がある場合は特に |
/api と /api/ のどちらにするか決めたか |
/apiv2 などで curl |
| try_files の最後の引数(=404 / URI / @名前)を決めたか | 存在しないパスで curl |
| alias と location の末尾スラッシュをそろえたか | /xx../ 形式のパスで 404 になるか |
nginx -t が通ったか |
nginx -t |
| 想定 URI ごとに当たる location を確かめたか | 仮の add_header X-Loc と curl -I |
よくある質問
Q. location の優先順位は、設定ファイルに書いた順番ですか?
A. 前方一致は書いた順番ではなく「一番長く一致したもの」、正規表現は「書いた順番で最初に一致したもの」です。 さらに、完全一致 = が最優先で、正規表現は前方一致より優先されます(^~ の前方一致を除く)。
Q. ^~ はどんなときに使いますか?
A. 「このパス配下は正規表現の location に渡したくない」ときに使います。 例えば /static/ 配下の画像を、拡張子用の正規表現 location(キャッシュ設定など)ではなく専用の設定で処理したい場合です。今回の検証でも /static/a.png は ~ \.(png|jpg)$ ではなく ^~ /static/ に当たりました。
Q. try_files の $uri/ は何のために書くのですか?
A. ディレクトリへのアクセス(/ や /docs/ など)で index ファイルを返すためです。 $uri/ に一致すると index ディレクティブのファイル(例: index.html)が探されます。ディレクトリで index を返す必要がなければ省略できます。
Q. root と alias はどちらを使えばよいですか? A. URL のパスとフォルダ構成が同じなら root、違うなら alias です。 root で書ける場面では root を使うと、try_files との組み合わせも素直に動きます。alias を使う場合は location と alias の末尾スラッシュをそろえてください。
まとめ
- location の判定は「= の完全一致 → 最長の前方一致 → ^~ なら決定 → 正規表現を上から順 → 無ければ最長の前方一致」
- 前方一致は長さ、正規表現は書いた順で選ばれる。
/apiは/apiv2にも当たる - try_files は左から順に探し、最後の引数(=404・URI・@名前)がフォールバック。SPA は
/index.html、PHP は/index.php?$args - root はパス+URI全体、alias は一致部分を置き換え。alias は location と末尾スラッシュをそろえる
- URL を変えるだけなら return、正規表現で組み立てるなら rewrite
- nginx -t のエラー文の末尾に「ファイル:行番号」が出るので、そこから直す
- 当たる location は
return 200やadd_headerと curl で確かめるのが確実
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「nginx location書き方|優先順位とtry_filesをcurlで検証」
株式会社RJCでは、nginx の設定の読み解き方を仲間と学び合っています。こうした知識を共有しながら、日々技術を磨いています。
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。