エラーの構造
Webアプリケーションにアクセスすると、冷ややかな「404 Not Found」ページが表示されます。ファイルはディスク上に存在するのに、Nginxがそれを提供してくれません。/var/log/nginx/error.logにあるエラーログを素早く確認すると、次のようなイライラさせるメッセージが表示されています。
FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream
エラーの背景
このエラーは、NginxとPHP-FPMの間の通信障害を示しています。Nginxはゲートキーパーとして動作し、リクエストを受け取ってPHPプロセッサに渡します。しかし、PHP-FPMはNginxから提供されたファイルパスを見つけることができないため、「not found(見つかりません)」と応答します。多くの場合、これは3つの設定の不備のいずれかに集約されます。
- PHP-FPMに渡される
SCRIPT_FILENAME変数が存在しないパスを指している。 rootディレクティブが誤った設定ブロック内に閉じ込められている。- PHP-FPMプロセスにディレクトリを読み取るために必要な権限がない。
ステップバイステップの解決策
1. SCRIPT_FILENAMEパラメータの監査
最も頻繁な原因は、fastcgi_param SCRIPT_FILENAME の設定ミスです。通常 /etc/nginx/sites-available/example.com にあるサイト設定ファイルを開きます。
PHPの location ブロックを探します。以下のようになっているはずです。
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
修正方法: SCRIPT_FILENAME が $document_root$fastcgi_script_name を使用していることを確認してください。もし /var/www/html$fastcgi_script_name のようにパスをハードコードしている場合は、すべての文字を検証してください。フォルダ名のタイポ(打ち間違い)が1つあるだけで、404がトリガーされます。
2. rootディレクティブの罠を回避する
root ディレクティブの配置ミスは、よくある落とし穴です。location / ブロック内に root を定義すると、PHPブロックはそれを継承しません。その結果、NginxがPHP-FPMにリクエストを渡す際、$document_root 変数が空になってしまいます。
避けるべき間違い:
server {
listen 80;
server_name example.com;
location / {
root /var/www/my-app/public; # 誤り:スコープが限定されている
index index.php;
}
location ~ \.php$ {
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
...
}
}
正しい方法: root ディレクティブを server レベルに移動します。これにより、ファイル内のすべての location ブロックに適用されるようになります。
server {
listen 80;
server_name example.com;
root /var/www/my-app/public; # 正解:グローバルスコープ
location / {
index index.php;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
}
}
3. 権限のボトルネックを解消する
PHP-FPMは権限に対して非常に厳格です。通常、ファイルをアップロードしたユーザーではなく、www-data や php-fpm として実行されます。PHPワーカーがディレクトリツリーを「辿る」ことができない場合、スクリプトを unknown として報告します。
以下のコマンドでPHPユーザーを特定します:
ps aux | grep php-fpm
このユーザーがPHPファイルへの読み取り権限と、すべての親ディレクトリへの実行権限を持っていることを確認してください。標準的なUbuntuのセットアップでは、以下のコマンドで所有権と権限を素早くリセットできます:
sudo chown -R www-data:www-data /var/www/my-app
sudo find /var/www/my-app -type d -exec chmod 755 {} \;
sudo find /var/www/my-app -type f -exec chmod 644 {} \;
4. RHEL/CentOSでSELinuxを制御する
Red Hat系のシステムでは、SELinuxが「静かな殺し屋」になることがよくあります。Linuxの権限が完璧な 777 であっても、Nginxをブロックすることがあります。一時的に permissive モードに切り替えて、これをテストします:
sudo setenforce 0
もしサイトが突然動作するようになったら、SELinuxが障壁となっていました。強制モード(enforcement)に戻し、Webフォルダに正しいセキュリティコンテキストを適用します:
sudo setenforce 1
sudo chcon -Rt httpd_sys_content_t /var/www/my-app
変更の適用
構文をテストせずにNginxを再起動しないでください。セミコロンが1つ欠けているだけで、サーバー全体がオフラインになる可能性があります。
sudo nginx -t
テストに合格したら、サービスをリロードして修正を適用します:
sudo systemctl reload nginx
sudo systemctl restart php8.2-fpm
ブラウザを更新してください。これでPHPアプリケーションが正しく読み込まれるはずです。
トラブルシューティングのプロのヒント
- シンボリックリンクに注意: Capistranoのようなデプロイツールを使用している場合は、Nginxがシンボリックリンクを辿れるように設定されているか確認してください。必要に応じて、設定に
disable_symlinks off;を記述します。 - ソケットパスを確認:
fastcgi_passが/etc/php/8.2/fpm/pool.d/www.confにある実際のソケットファイルと一致しているか確認してください。バージョンの不一致(例:設定では 8.1 だが 8.2 がインストールされている)は、よくある悩みの種です。 - ドキュメントルートの正確性:
fastcgi_paramにおいて、rootディレクティブにすでにスラッシュが含まれている場合は、末尾のスラッシュを避けてください。二重のスラッシュ(例:/var/www//index.php)は、特定のPHP-FPMバージョンを混乱させることがあります。

