CentOSにインストールしたnginxでPHPを動かしてみる。

CentOSにインストールしたnginxでPHPを動かしてみます。PHP本体はすでにインストール済みです。nginxとPHPを連携させるにはphp-fpmというパッケージが必要で、そのインストール作業からです。作業はrootユーザーで行います。

【環境】
・CentOS 7.9
・nginx 1.19.6
・PHP 7.2.17

php-fpmをインストールします。

# yum install php-fpm

ですが、、いきなりエラーとなってしまいました。。

このように言っています。


エラー: パッケージ: php-fpm-5.4.16-48.el7.x86_64 (base)
             要求: php-common(x86-64) = 5.4.16-48.el7
            インストール: php-common-7.2.17-1.el7.remi.x86_64 (@remi-php72)
                php-common(x86-64) = 7.2.17-1.el7.remi
            利用可能: php-common-5.4.16-48.el7.x86_64 (base)
                php-common(x86-64) = 5.4.16-48.el7
 問題を回避するために --skip-broken を用いることができます。
 これらを試行できます: rpm -Va --nofiles --nodigest

意味がわからないのでphp-fpmの情報を確認してみました。

# yum info php-fpm

これを見てなんとなくわかりました。先ほどのエラーは「yum install でphp-fpmは5.4.16がインストールされるが依存関係で必要なphp-commonの5.4.16版がなく、php-commonの7.2.17版ならインストールされている」と言っていたようです。ここでPHP本体をインストールしたときのことを思い出しました。CentOS 7 の標準のリポジトリではPHP7がないのでremiリポジトリを入れていたことを。その時の記事です。

CentOS7.4にPHP7がインストールできないと思ったときの対応

これを読み返し、remiリポジトリを指定してインストールをしました。

# yum install --enablerepo=remi-php72 php-fpm

PHP本体を入れたときと同じやり方ですね。インストールログは省略しますが、これで無事にphp-fpmがインストールできました。なお、php-fpmを入れたらPHP 7.2.17だったのが、PHP 7.2.34になりました。

[広告]

ここからphp-fpmの設定に入ります。修正するファイルは /etc/php-fpm.d/www.conf です( /etc/php-fpm.conf がphp-fpm.d配下のwww.confをincludeしています)。

まず、起動ユーザーを設定します。デフォルトではapacheとなっています。nginxの起動ユーザーとあわせておく必要があります。今回はnginxもphp-fpmもapacheユーザーで動かすことにしますので、このままとします。

補足:
nginxユーザーで起動させたい場合は「apache」を「nginx」に読み替えてください。後述するnginxの起動ユーザーの設定も同様です。

■起動ユーザーの設定
user = apache
group = apache

次に、nginxとの連携方法を設定します。nginxではPHPの処理をphp-fpmに任せるようにするのですが、この連携はプロセス間通信で行います。プロセス間通信にはTCP/IPを使う方法とUnixソケットを使う方法の2つがあります。WEBサーバーの役割をnginx、アプリケーションサーバーの役割をphp-fpmが担う場合(つまりWEBサーバーとアプリケーションサーバーを分離させる場合)は、TCP/IPでプロセス間通信を行います。Unixソケットではリモート間での接続はできません。今回は1台のサーバーにnginxもphp-fpmも入れてしまっているのでUnixソケットを使う方法で連携するようにします。

Unixソケットは /var/run 配下にphp-fpm.sockファイルとして作成するようにします。修正するところはlistenパラメータです。

■プロセス間通信方法
修正前
listen = 127.0.0.1:9000
 ↓
修正後
listen = /var/run/php-fpm.sock

php-fpm.sockファイルの所有者がapacheになるように修正をします。listen.owner、listen.group、listen.modeはコメントアウトされているのでそれを外して直します。

■ソケットファイルの所有者変更
修正前
;listen.owner = nobody
;listen.group = nobody
;listen.mode = 0660
 ↓
修正後
listen.owner = apache
listen.group = apache
listen.mode = 0660

修正したwww.confはこんな感じです。左側の数字は行番号です。

修正が終わったらphp-fpmを起動します。

# systemctl start php-fpm

ソケットファイルが出来ているか確認してみます。

# ls -l /var/run/php-fpm.sock

apacheが所有者としてphp-fpm.sockが出来ています。ちなみにですが、nginxがこのソケットファイルにアクセスできない場合は当然ながらエラーになります。その際はnginxのエラーログに「Permission denied」のエラーが出力されます。

こういうエラーです。


2021/01/23 22:52:28 [crit] 1275#1275: *1 connect() to unix:/var/run/php-fpm.sock failed (13: Permission denied) while connecting to upstream, client: xxx.xxx.xxx.xxx, server: localhost, request: "GET /xxx.php HTTP/1.1", upstream: "fastcgi://unix:/var/run/php-fpm.sock:", host: "xxx.xxx.xxx.xxx"

php-fpmの修正は以上です。

[広告]

続いてnginxの設定をします。nginxの起動ユーザーをapacheに修正します。修正するファイルは /etc/nginx/nginx.conf です。

■起動ユーザーの設定
修正前
user nginx;
 ↓
修正後
user apache;

nginxからphp-fpmに処理を引き渡す設定をdefault.confのserverディレクティブに記載します。default.confは /etc/nginx/conf.d 配下にあります。以下の記載をそのまま貼り付けてください。locationディレクティブに「〜.php」ファイルへのアクセスがあったときの処理を記載しています。太字部分がphp-fpmとのプロセス間通信の設定になります。


location ~* \.php$ {
    try_files $uri =404;
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    include fastcgi_params;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_intercept_errors on;
    fastcgi_pass unix:/var/run/php-fpm.sock;
}

default.confはこんな感じです。

修正が出来たらnginxのコンフィグテストを行います。

# nginx -t

nginx.conf syntax is ok、nginx.conf test is successful、と表示されれば大丈夫です。

nginxも起動します。

# systemctl start nginx

nginxのドキュメントルートにinfo.phpを作成して配置します。ドキュメントルートはdefault.confのrootディレクティブで指定しています。info.phpは3行だけ記載します。

<?php
  phpinfo()
?>

ブラウザから http://nginxのIPアドレス/info.php でアクセスして、このような画面が表示されれば成功です。

nginxのエラーページの設定方法

デフォルトのnginxの設定のままだとエラーページにnginxのバージョンが表示されてしまいます。

セキュリティを考えると良くないので表示されないようにします。設定は簡単で、nginx.confに「server_tokens off;」と記載するだけです。nginx.confは /etc/nginx 配下にあります。


user  nginx;
worker_processes  1;
 :
 :
http {
 :
  server_tokens off;
 :
}

nginxを再起動して同じエラーページを表示してみると、バージョンが表示されなくなります。

とは言ってもWEBサーバーにnginxを使っていることはバレてしまいます。ユーザーがサイト内の存在しないURLにアクセスすることでサーバーからのエラー情報を取得しようとする場合に備え、専用のエラーページを表示させるようにしておこうと思います。

初期設定のnginxではdefault.confの「error_page 404 /404.html;」の記載がコメントアウトされていますので、このコメントアウトを外して専用のエラーページ(40x.html)表示に変えます。default.confは /etc/nginx/conf.d 配下にあります。


server {
 :
  error_page  400 403 404  /40x.html;
  location = /40x.html {
      root   /usr/share/nginx/html;
  }
 :
 :
}

初期設定だとHTTPのステータスコード404しか記載がありませんので400と403も独自に追加しました。意味は以下です。

400(Bad Request)・・不正なリクエスト
403(Forbidden)・・禁止されているリクエスト
404(Not Found)・・リソースが見つからない

default.confへの記載が終わったら40x.htmlを新規作成して配置します。40x.htmlには以下を記載します。


<!DOCTYPE HTML>
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL was not found on this server.</p>
</body></html>

HTTPステータス400、403も404エラーとして表示させています。この辺は好みによってエラー文言を変えてください。この40x.htmlを /usr/share/nginx/html 配下に配置します。このディレクトリはroot権限がないと書き込みできないです。

nginxを再起動して(存在しないhtmlファイルを指定するなどして)エラーページを表示してみます。

という画面が表示されるかと思いましたが、

となりました。実はコレ、、Apacheのエラー画面のHTMLソースをコピってきたもので、キャッシュが残っていたのかフォントがApacheのままになってしまいました。Apacheで動いているように見せかけて、実はnginxで動いているという・・これはこれでそのままとします。

ちなみに /usr/share/nginx/html 配下には50x.htmlというのが格納されています。これはHTTPステータスが500、502、503、504のときに表示されるものです(default.confに記載されています)。50x.htmlにはnginxの記載がありますのでnginxという文言を隠すのであれば50x.htmlも書き換えたほうが良いでしょう。

少し別の話題になりますが、nginxではエラーページ表示の代わりにレスポンスを返さない、という設定ができます。HTTP標準にはないnginx独自のステータスコード444を指定することで、レスポンスヘッダを返さずに接続を強制的に終了するようです。


server {
    listen       80;
    server_name  dummy;
    root         /var/www/html/dummy;

    location / {
        return 444;
    }
  :
  :
}

この設定をしたnginxにアクセスすると、ブラウザではこのように表示されます。FireFoxの例です。

エラーページとステータスコード444をうまく使い分けると良さそうです。