2026年6月30日

2026年6月30日

Nginxのtry_filesの使い方をWordPressの設定例で解説

Nginx の try_files は、並べたファイルやディレクトリを左から順に探し、最初に見つかったものを返し、どれも無ければ最後に書いた URI へ内部転送するか、指定したステータスコードを返すディレクティブです。WordPress では try_files $uri $uri/ /index.php?$args; の1行で、実在する画像や CSS はそのまま配信し、それ以外の投稿ページなどを index.php に渡す、パーマリンクの仕組みを実現しています。この記事では、書式と評価の順番、WordPress での定番の書き方とその意味、PHP の location に try_files $uri =404; を入れる理由、よくある失敗とエラーログの読み方を説明します。

書式と評価の順番

try_files ファイル1 ファイル2 ... 最後の引数;

server か location の中に書きます。Nginx は root(または alias)で指定したディレクトリを基準に、引数を左から順に確かめます。

  • $uri のような引数は「そのパスのファイルがあるか」を確かめる
  • 末尾が / の引数($uri/)は「そのパスのディレクトリがあるか」を確かめる。見つかると index ディレクティブに従って index.php や index.html が探される
  • 最後の引数だけは特別で、「探す対象」ではなく「どれも見つからなかったときの行き先」になる。URI を書けばその URI へ内部転送し、=404 のように書けばそのステータスコードを返す

ここで言う内部転送は、ブラウザに見える URL は変えずに、Nginx の中で別の URI として処理し直すことです。リダイレクト(301 や 302)とは違い、訪問者のアドレスバーは元の URL のままです。転送された URI は改めて location の照合からやり直されるため、/index.php に転送されたリクエストは、PHP 用の location ~ \.php$ で処理されます。

WordPress での定番の書き方

server {
    listen 443 ssl;
    server_name example.com;
    root /var/www/example.com;
    index index.php index.html;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.php$ {
        try_files $uri =404;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass unix:/run/php/php-fpm.sock;   # 実際のソケット名に合わせる
    }
}

location / の1行は、次の順に処理されます。

  1. /wp-content/uploads/2026/10/photo.jpg のように実在するファイルなら、そのまま静的ファイルとして返す
  2. /wp-admin/ のように実在するディレクトリなら、その中の index.php を探す
  3. /sample-page/ のように実在しないパスなら、/index.php?$args へ内部転送し、WordPress がパーマリンクを解釈してページを組み立てる

$args はクエリ文字列(? 以降)です。これを付けないと、検索の ?s=キーワード やプレビューの ?preview=true などが WordPress に届きません。/index.php$is_args$args と書く例もあり、こちらはクエリが無いときに ? を付けない書き方です。どちらでも WordPress は動きます。

Apache の .htaccess で WordPress が書き込む RewriteCond %{REQUEST_FILENAME} !-f などの記述は、Nginx ではこの try_files が受け持ちます。Nginx は .htaccess を読まないため、管理画面でパーマリンク設定を保存しても、Nginx 側にこの行が無ければ投稿ページは 404 のままです。

PHP の location に try_files $uri =404 を入れる理由

PHP 用の location にある try_files $uri =404; は、「実在しない PHP ファイルへのリクエストを PHP-FPM に渡さない」ための行です。PHP の設定によっては、/wp-content/uploads/image.jpg/x.php のような存在しないパスを渡されたとき、パスをさかのぼって image.jpg を PHP として実行しようとすることがあります。アップロードされた画像に悪意のあるコードが仕込まれていると、それが実行されるおそれがあります。

try_files $uri =404; があれば、x.php というファイルが実在しない時点で 404 を返すため、この経路を塞げます。あわせて、アップロード用のディレクトリでは PHP を実行させない設定も入れておくと、より安全です。

location ~* ^/wp-content/uploads/.*\.php$ {
    deny all;
}

正規表現の location は設定ファイルに書いた順に照合されるため、この location は PHP 用の location ~ \.php$ より前に書きます。

サブディレクトリに WordPress を置く場合

https://example.com/blog/ のように WordPress を /blog に置く場合は、location と転送先の両方を合わせます。

location /blog/ {
    try_files $uri $uri/ /blog/index.php?$args;
}

転送先を /index.php のままにすると、ドキュメントルート直下の別の index.php が呼ばれたり、ファイルが無くてエラーになったりします。

よくある失敗とエラーログの読み方

設定を変える前に /etc/nginx をバックアップし、変更後は sudo nginx -t && sudo systemctl reload nginx で構文を確かめてから反映します。うまく動かないときは、エラーログ(多くの環境で /var/log/nginx/error.log)を見ると原因の見当が付きます。

rewrite or internal redirection cycle と出る

エラーログに rewrite or internal redirection cycle while internally redirecting to "/index.php" と記録され、訪問者には 500 が返る状態です。最後の引数の転送先がさらに同じ try_files に戻り、無限に転送が続いています。よくある原因は次の順です。

  • root のパスが間違っていて、index.php 自体が見つからない
  • PHP 用の location が無い、または正規表現が合っておらず、/index.php が再び location / で処理されている
  • サブディレクトリ設置で、転送先のパスが実際の配置と合っていない

ls -l で root に書いたパスに index.php があるか、Nginx の実行ユーザーに読み取り権限があるかを確認します。

PHP のソースがダウンロードされる

/index.php へ転送された後に処理する PHP 用の location が無いと、Nginx は index.php をただのファイルとして返してしまい、ソースコードがそのまま表示またはダウンロードされます。wp-config.php の中身が見える可能性もあるため、設定変更の直後は curl -I https://example.com/ で Content-Type が text/html になっているかを確認してください。

静的ファイルの location で XML や robots.txt が 404 になる

画像や CSS 用の location ~* \.(css|js|png|jpe?g|gif|webp|svg|xml|txt)$ { try_files $uri =404; } のように、拡張子でまとめて =404 にすると、PHP へ渡らなくなります。WordPress の robots.txt や、SEO プラグインやコアが出力する XML サイトマップは、実在するファイルではなく WordPress が動的に生成しているため、このように書くと 404 になります。静的ファイル用の location に xml や txt を含めないか、最後の引数を /index.php?$args にします。

location ~* \.(css|js|png|jpe?g|gif|webp|svg|woff2?)$ {
    try_files $uri =404;
    expires 30d;
    access_log off;
}

画像を =404 で返すと、存在しない画像へのリクエストで毎回 WordPress が起動するのを防げるため、負荷の軽減にもなります。ただし、画像を動的に生成するプラグインを使っている場合は、その仕組みと合うか確認してください。

alias と組み合わせて意図しないパスになる

location の中で root の代わりに alias を使うと、try_files の扱いが直感と異なる場合があり、Nginx の不具合報告としても知られています。WordPress の設定では alias を使わず、root で書くほうがつまずきにくくなります。

古い if (!-e $request_filename) の設定を引き継いでいる

古い記事では if (!-e $request_filename) { rewrite ^ /index.php last; } のような書き方を見かけます。これは try_files が無かったころの方法で、今は try_files に置き換えるのが一般的です。location の中の if は思わぬ動きをすることがあるため、移行するときに見直す価値があります。

設定の書き方は Nginx の版が変わってもほぼ同じですが、PHP-FPM のソケット名や設定ファイルの場所は OS と PHP の版で異なります(2026年10月現在)。本番に入れる前に、ステージング環境で投稿ページ・固定ページ・検索・管理画面・サイトマップの表示まで確認しておくと安心です。

まとめ

  • try_files は左から順に探し、最後の引数だけが「見つからなかったときの行き先」になる
  • WordPress は try_files $uri $uri/ /index.php?$args; でパーマリンクを実現する。$args を忘れると検索などが動かない
  • PHP 用の location には try_files $uri =404; を入れ、アップロード用ディレクトリでの PHP 実行を禁止する
  • サブディレクトリ設置では location と転送先の両方をそのパスに合わせる
  • internal redirection cycle は root と PHP 用 location の不備を疑う
  • 静的ファイル用の location に xml や txt を含めると、動的なサイトマップや robots.txt が 404 になる

お気軽にご相談ください

お見積りへ お問い合わせへ
▲