2026年6月19日

2026年6月19日

NginxでWordPressを動かす最適設定(server blockの全体像と各設定の理由)

Nginx で WordPress を動かすときの要点は、パーマリンクを try_files で index.php に渡すこと、PHP-FPM には存在する PHP ファイルだけを渡すこと、アップロードディレクトリなどで PHP を実行させないことの3つです。この記事では、そのまま土台に使える server ブロックの全体像を示したうえで、各設定がなぜ必要か、どこでつまずきやすいか、反映後に何を確認すればよいかを説明します。Nginx のインストールや PHP-FPM の導入は済んでいる前提です。

Apache との違いを先に押さえる

Apache で動いていた WordPress を移す場合、いちばん大きな違いは .htaccess が使えないことです。Nginx はディレクトリごとの設定ファイルを読まないため、パーマリンクの書き換えや、プラグインが .htaccess に書き込むアクセス制限・キャッシュ設定は効きません。必要なものは Nginx の設定ファイルに書き直す必要があります。

また、Nginx 自身は PHP を実行できません。PHP の処理は PHP-FPM に任せ、Nginx は静的ファイルの配信と、PHP へのリクエストの受け渡しを担当します。

server ブロックの全体像

以下は HTTPS 化済みの単一サイトを想定した例です。ドメイン、パス、PHP-FPM のソケットは環境に合わせて変えてください。

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;
    server_name example.com;

    root /var/www/example.com;
    index index.php;

    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    client_max_body_size 64m;

    # パーマリンク
    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    # アップロード領域などでの PHP 実行を禁止
    location ~* ^/wp-content/uploads/.*\.php$ {
        deny all;
    }

    # 隠しファイル(.git や .htaccess など)を拒否。証明書の確認用は除外
    location ~ /\.(?!well-known/) {
        deny all;
    }

    location = /wp-config.php {
        deny all;
    }

    # PHP を PHP-FPM に渡す
    location ~ \.php$ {
        try_files $uri =404;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
        fastcgi_read_timeout 60s;
    }

    # 静的ファイル
    location ~* \.(?:css|js|jpe?g|png|gif|webp|avif|svg|ico|woff2?)$ {
        expires 30d;
        access_log off;
        try_files $uri =404;
    }
}

http2 on; は比較的新しい書き方で、古いバージョンでは listen 443 ssl http2; と書きます。nginx -v でバージョンを確認し、合わない書き方なら nginx -t で警告やエラーが出るので、それに従って直してください。HTTP から HTTPS へのリダイレクトは、80 番ポート用の別の server ブロックで行います。

各設定の理由とつまずきやすい点

パーマリンク:try_files

try_files $uri $uri/ /index.php?$args; は「その URL のファイルがあれば返す、ディレクトリがあればそれを使う、どちらもなければ index.php にクエリ文字列ごと渡す」という意味です。WordPress の投稿 URL は実在するファイルではないため、最後の index.php に渡る部分がパーマリンクを成立させています。これがないと、トップページは表示されるのに個別記事がすべて 404 になる、という典型的な症状になります。

?$args を書き忘れると、検索(?s=)やプレビューなどクエリ文字列を使う機能が動かなくなります。

PHP の受け渡し:try_files $uri =404

PHP の location に入れた try_files $uri =404; は、実在しない PHP ファイルへのリクエストを PHP-FPM に渡さずに 404 で返すためのものです。PHP の設定によっては、画像ファイル名の後ろに /x.php を付けたようなリクエストで、意図しないファイルが PHP として解釈される問題が知られており、その対策になります。

fastcgi_pass のソケットのパスは、ディストリビューションと PHP のバージョンによって異なります。ls /run/php/ などで実際のファイル名を確認してください。ここが違うと 502 Bad Gateway になります。

アップロード領域での PHP 実行禁止

wp-content/uploads/ は WordPress が書き込める場所なので、脆弱なプラグインを経由して PHP ファイルを置かれる被害が起きやすいディレクトリです。ここで PHP を実行できなくしておけば、置かれても動かないため被害を抑えられます。なお、正規表現の location は書かれた順に評価されるため、この拒否ルールは PHP を渡す location ~ \.php$ より前に書く必要があります。

隠しファイルと wp-config.php

.git ディレクトリやエディタのバックアップファイルが公開ディレクトリに残っていると、ソースコードや設定が丸ごと取得されることがあります。ドットで始まるパスはまとめて拒否し、Let's Encrypt の所有確認に使う /.well-known/ だけは通すようにしています。

アップロードサイズ

client_max_body_size の既定は 1m なので、そのままでは大きな画像やプラグインの ZIP をアップロードすると 413 エラーになります。Nginx の値だけでなく、PHP の upload_max_filesize と post_max_size もあわせてそろえてください。いずれか小さいほうが上限になります。

静的ファイルのキャッシュ

CSS・JS・画像に有効期限を付けると、再訪問時にブラウザがキャッシュを使うため表示が速くなります。WordPress やテーマはファイルの URL にバージョンのクエリを付けて読み込むことが多いので、更新時の反映はおおむねそれで切り替わります。期限を長くしすぎると、クエリの付かない画像を差し替えたときに古いものが表示され続けることがあるので、運用に合わせて調整してください。

必要に応じて追加する設定

  • xmlrpc.php:使っていなければ location = /xmlrpc.php { deny all; } で閉じると、総当たり攻撃の入り口を減らせます。ただし Jetpack やスマートフォンアプリなど、利用している機能が止まる場合があるので確認してから設定します。
  • gzip 圧縮:gzip on; と gzip_types で、HTML 以外のテキスト系ファイルも圧縮できます。
  • ページキャッシュ:アクセスが多いサイトでは、キャッシュプラグインや Nginx の fastcgi_cache を検討します。fastcgi_cache を使う場合は、ログイン中のユーザーやコメント投稿者の Cookie を持つリクエスト、POST リクエストをキャッシュから外す設定が欠かせません。外し忘れると、管理者向けの画面が他人に表示されるおそれがあります。
  • ロードバランサーや CDN の背後に置く場合:TLS を手前で終端していると、WordPress が HTTPS で接続されていると判定できず、リダイレクトのループが起きることがあります。wp-config.php で X-Forwarded-Proto ヘッダーを見て $_SERVER['HTTPS'] を設定する方法が一般的ですが、信頼できる中継元からのヘッダーに限って採用してください。

反映と確認

設定ファイルを変更する前にバックアップを取り、可能ならステージング環境で試してから本番に反映します。

sudo nginx -t
sudo systemctl reload nginx

curl -I https://example.com/                      # 200 が返るか
curl -I https://example.com/sample-post/          # 個別記事が 404 にならないか
curl -I https://example.com/wp-content/uploads/test.php   # 403 または 404 になるか
curl -I https://example.com/.git/config           # 403 になるか

あわせて、管理画面へのログイン、メディアのアップロード、パーマリンク設定の保存、プレビューの表示を一通り操作して、エラーログ(/var/log/nginx/error.log)に新しいエラーが出ていないか確認してください。

この記事の設定は、Nginx の安定版と、WordPress の公式ドキュメントに掲載されている Nginx の設定例を参考にしています(2026年10月現在)。マルチサイトの場合は書き換えルールが異なります。

まとめ

  • .htaccess は効かないので、パーマリンクやアクセス制限は Nginx の設定に書く
  • パーマリンクは try_files $uri $uri/ /index.php?$args;、PHP には try_files $uri =404; で実在するファイルだけを渡す
  • アップロード領域の PHP 実行、隠しファイル、wp-config.php へのアクセスを拒否する。拒否ルールは PHP の location より前に書く
  • client_max_body_size は PHP のアップロード上限とそろえる
  • 反映前に nginx -t、反映後は curl と管理画面の操作で動作を確認する

お気軽にご相談ください

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