OpenWrt で NGINX と PHP 7(FPM)環境を整える

例えば WordPress をインストールするためには PHP 7 が Web サーバーと連携して使える状態(FastCGI)を整えておく必要がある。この文書では、WordPress のことはとりあえずおいておいて、一般的に OpenWrt に Web サーバーとして NGINX(SSL 版)を利用し、PHP 7 を FPM(FastCGI Process Manager)で連携する方法について記す。

前提状況:USB フラッシュドライブ

WWW 用のデータを置く場所として USB フラッシュの外部ドライブを用意(👉 OpenWrt での USB フラッシュドライブ)し、/mnt/data にマウントしていることを前提としている。

LuCI もろとも Web サーバー(HTTPd)を SSL 対応 NGINX 化する

以前の OpenWrt 18.x とは飛躍的に進歩して、19.07 では SSL 対応版の NGINX が opkg として用意されている(以前は自前で Linux ソースコードからモジュールをビルドする必要があった)のみならず、NGINX 版 LuCI がセットアップされている opkg すら用意されており、OpenWrt コミュニティの旺盛な活動を感じる(👉 LuCI on other web servers > LuCI on nginx)。


opkg update
opkg install luci-ssl-nginx
opkg remove luci

デフォルトでインストールされている LuCI/uHTTPd の方は不要になるのでアンインストールした。

用意した USB の外部領域(/mnt/data)があるので、デフォルトの Web ルート(/www 以下)を /mnt/data/www/default 以下にコピー。


mkdir -p /mnt/data/www/default
cp -rp /www/* /mnt/data/www/default

それに連動して /etc/nginx/nginx.conf の設定を変更して、Web ルートが /mnt/data/www/default を指し示すように修正する。ただし、元々の root オプションが http ブロック直下にあったのを、2 番目の ssl 用の server ブロック内に新しい root オプションを挿入している。これにより、マルチドメインを利用する SNI の場合に server 毎に別々の root 指定を切り替えられるように記述したいからである。

/etc/nginx/nginx.conf

http {
    (...)
-   root /www;
    (...)
    server {
    (...)
+       root /mnt/data/www/default;

        location ~* .(jpg|jpeg|png|gif|ico|css|js)$ {
    (...)
    }

    include /etc/nginx/conf.d/*.conf;
}

こうすることで、NGINX 版 LuCI が元通り利用できるのはもちろんのこと、default 以下に test.html や test.php などを置いて NGINX の動作テストすることができるし、/mnt/data/www/scaredeer.com 等を作って nginx.conf を適切に設定すれば SNI 運用することもできる。ともかくデフォルトで表示される LuCI の管理画面を含めて、すべて USB の外部領域 /mnt/data/www 以下にまとめて配置する形にできるわけである。

PHP 7(php7-fpm)のインストール・セットアップ


opkg install php7-fpm

php7 は依存関係から必然的にインストールされる。一方、OpenWrt 公式ガイドは FPM ではなく通常の FastCGI の場合の解説なので、php7-cgi や php7-fastcgi 等のインストールまでは不要。CGI の一種ではあるが、モジュールとして動かす FastCGI/FPM は通常の CGI とは異なるため、FastCGI/FPM でセットアップする場合に CGI(php7-cgi)用のパッケージまでも並行してインストールするのは容量の無駄食いになるだけである。また、通常の FastCGI よりも FPM の方がさらに効率的な実装なので、FPM をインストールした場合は通常の FastCGI はやはり不要である。他に、php7-cli も、PHP をコマンドで動かさないのであれば何の必要もない。また公式ガイドにあるような、php.ini の cgi.force_redirect = 1 や cgi.redirect_status_env = "yes"; の設定も不要で、doc_root のみ、実情に合わせて記述すれば十分だった。

/etc/php.ini

- doc_root = "/www"
+ doc_root = "/mnt/data/www/default"

以上で php7-fpm のインストール・セットアップ自体は終わる。具体的には /var/run/php7-fpm.sock という形の Web ソケットが得られる。

NGINX の php7-fpm との連携

php7-fpm のインストール自体は上で終わりだが、今度は NGINX 側で http から .php にアクセスがあった時に、Web ソケットを通じて入出力を受け渡しするように設定をする必要がある。つまり、改めて nginx 側の設定に話が戻る。

基本的には NGINX の .conf ファイルをどう記述するかということで、NGINX 公式に基本的な説明がある(/var/run/php-fpm.sock は /var/run/php7-fpm.sock に直して読む必要がある)。

それを基にした OpenWrt の公式解説が上掲の PHP with FastCGI だが、この解説は OpenWrt でのデフォルト設定の文脈の中でのものなので、該当セクションだけを切り取るとわかり辛く誤解が生じやすい。大元の /etc/nginx/nginx.conf の http ブロック中で /etc/nginx/conf.d/*.conf を include し、さらに include された一つの /etc/nginx/conf.d/*.conf の server ブロック中で /etc/nginx/conf.d/*.locations を include するという、3 段構成で設定ファイルを記述している。その 3 段目の .locations に記述された location ブロックが、/etc/nginx/conf.d/php.locations として例示されているものなので、いきなりこの設定ファイルを真似て設置しても、ちゃんと動かないのには注意が必要である。適切に 1 段目の nginx.conf と 2 段目 の conf.d/*.conf を記述・設置した上で、conf.d/php.locations を置くこと。

ここまでの作業では、/etc/nginx/nginx.conf は luci-ssl-nginx のインストール後に root 設定を /mnt/data/www に変更しただけで、以下のような状態だが:


user  root;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile on;
    keepalive_timeout 0;

    client_body_buffer_size 10K;
    client_header_buffer_size 1k;
    client_max_body_size 1G;
    large_client_header_buffers 2 1k;

    gzip on;
    gzip_http_version 1.1;
    gzip_vary on;
    gzip_comp_level 1;
    gzip_proxied any;
    gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript image/svg+xml;

    server {
        listen 80 default_server;
        listen [::]:80 default_server;
        server_name _;
        return 301 https://$host$request_uri;
    }

    server {
        listen 443 ssl default_server;
        listen [::]:443 ssl default_server;
        server_name  localhost;

        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_prefer_server_ciphers on;
        ssl_ciphers "EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:EECDH:DHE+AESGCM:DHE:!RSA!aNULL:!eNULL:!LOW:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!CAMELLIA:!SEED";
        ssl_session_tickets off;

        ssl_certificate /etc/nginx/nginx.cer;
        ssl_certificate_key /etc/nginx/nginx.key;

        root /mnt/data/www/default;

        location ~* .(jpg|jpeg|png|gif|ico|css|js)$ {
            expires 365d;
        }

        include luci_uwsgi.conf;
    }

    include /etc/nginx/conf.d/*.conf;
}

まず、index.php の読み込みを有効にするため(無指定のデフォルトの場合は index.html のみ有効)、ssl 用の server ブロックに index 指定を挿入する:


    server {
    (...)
        root /mnt/data/www/default;
+       index index.php index.html;

        location ~* .(jpg|jpeg|png|gif|ico|css|js)$ {
    (...)
    }

次に、デフォルトの ssl の server ブロック中にカスタムの location ブロックの追加ができるようにするため、include を挿入する:


        location ~* .(jpg|jpeg|png|gif|ico|css|js)$ {                           
            expires 365d;                                                       
        }
+       include /etc/nginx/conf.d/*.locations;

        include luci_uwsgi.conf;
    }

この時点では /etc/nginx/conf.d が存在していなかったので、ディレクトリを作成の上、/etc/nginx/conf.d/php.locations を作成し、その中で .php 用の設定として php7-fpm を使う設定を行えばよい。


mkdir /etc/nginx/conf.d
/etc/nginx/conf.d/php.locations

location ~ [^/]\.php(/|$) {
    fastcgi_split_path_info ^(.+?\.php)(/.*)$;
    if (!-f $document_root$fastcgi_script_name) {
        return 404;
    }

    fastcgi_pass unix:/var/run/php7-fpm.sock;
    fastcgi_index index.php;

    # include the fastcgi_param setting
    include fastcgi_params;

    # Mitigate https://httpoxy.org/ vulnerabilities
    fastcgi_param HTTP_PROXY "";

    # SCRIPT_FILENAME parameter is used for PHP FPM determining
    #  the script name. If it is not set in fastcgi_params file,
    # i.e. /etc/nginx/fastcgi_params or in the parent contexts,
    # please comment off following line:
    fastcgi_param  SCRIPT_FILENAME   $document_root$fastcgi_script_name;
}

そうした上で、以下のような .php のテストページ(https://[IP address]/test.php)を表示テストして初めて、php7-fpm が適切に動作しているかどうかを確かめることができたことになる。

/mnt/data/www/default/test.php

環境変数がずらずらと表示されれば正常である。

コメント

このブログの人気の投稿

OpenWrt での Wi-Fi 設定

シークエンスパパとも 本物の霊能力

シークエンスパパともの先見の明