最近VPSサービスのリプレースを行いまして、ついでにWebサーバをApacheからnginxに変更したのですが、移行時に気になったところがいくつかあったのでメモっておきます。
移行環境情報
移行前
OS: FreeBSD8.4
Apache2.2+mod_php
移行後
OS: FreeBSD10.1
nginx1.8+php-fpm (php5.6)
nginxはpkgでインストール
php-fpmはportsからインストール
稼働状況
- Wordpress (php,rewrite)
- ownCloud (php,rewrite)
- CakePHPで作成したWebアプリ (php,rewrite)
- VirtualHost3つほど
- HTTPSあり
見事にphpのアプリばかりですね!
.htaccessが使えない
たぶんこれが一番インパクト大きいんじゃないかと。
.htaccessの中身はすべてnginxの設定ファイルに変換して設定する必要があります。
静的ファイルがメインのWebサイトならさほど問題ないでしょうが、WordpressをはじめとしたCMS、CakePHP等のフレームワークでは必ずと言っていいほど使われています。
ほかにもApacheでは.htaccessでサクッとできたディレクトリ毎のBASIC認証もnginxでは設定ファイルに書いてあげないといけなくなります。
mod_rewriteが使えない
mod_rewriteはApache用のモジュールなので当然使えません。
上記に挙げたいくつかのWebアプリは1ファイルで処理するためにmod_rewriteで制御を行っています。
そのため単純にWebサーバをnginxに差し替えただけでは当然動きません。
nginxにもrewrite機能はありますので、mod_rewriteのルールをnginx用に書き換えてあげる必要があります。
公式ドキュメントに書かれているのでそこまで手間にはならなさそうですね。
Wordpress: https://codex.wordpress.org/Nginx
CakePHP: http://book.cakephp.org/3.0/ja/installation.html#nginx
ownCloud: https://doc.owncloud.org/server/8.0/admin_manual/installation/nginx_configuration.html
※実例を出したかったのですが、ウチのサイトはサブディレクトリで運用しているのであまり参考にならなさそうなので省略
mod_phpが使えない
mod_phpはApache用のモジュールなので(以下略
nginxからphpを実行するためにはCGI経由で実行する必要があります。(CGI経由のphp実行自体はApacheでもできますけどネ)
意外と面倒なphpの設定
nginxでphpを使うためにphp-fpmを使用します。
単純にphpを実行するだけならlocationディレクティブにphpをCGIで実行する設定をすればOKです。
http {
...
server {
listen 80 default_server;
server_name example.com;
index index.php index.html;
...
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_script_name;
include fastcgi_params;
}
}
server {
listen 80;
server_name www.example.com;
index index.php index.html;
...
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_script_name;
include fastcgi_params;
}
}
}
問題はこれ、VirtualHost毎に設定をしないといけないのです!
ApacheならLoadModuleを1行書くだけですべてのホストで実行できていたのにこれは面倒くさい…
ちなみにlocationディレクティブはserverディレクティブ配下にしか書けないようです。
http://nginx.org/en/docs/http/ngx_http_core_module.html#location
代替案として
phpのCGI設定だけ別ファイルに切り出しておいてIncludeで管理した方が楽そう。
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_script_name;
include fastcgi_params;
}
http {
...
server {
listen 80 default_server;
server_name example.com;
index index.php index.html;
...
include nginx-php.conf
}
server {
listen 80;
server_name www.example.com;
index index.php index.html;
...
include nginx-php.conf
}
}
スッキリ。
実行ユーザに注意
Apache+mod_phpの場合、phpはApacheのプロセスで動作しているのでphpの実行ユーザ=Apacheの実行ユーザとなっています。
それが、nginx+php-fpmではnginxはnginxの実行ユーザ、php-fpmはphp-fpmの実行ユーザと別々に設定されています。
そのため、Apache+mod_phpで書き出したファイル等をnginx+php-fpmで読み書きしようとするとファイル権限によりエラーとなる可能性はあります。
セキュリティ上問題ないのでしたら、手っ取り早いのはphp-fpmの実行ユーザをApacheの実行ユーザに設定してしまうことです。
※さらにいうとnginxの実行ユーザもApacheの実行ユーザにしてしまうと幸せになれるかも。
それがダメならファイルのユーザなりパーミッションを書き換えていくしかなさそうです。
起動方法にも注意
Apache+mod_php環境ではphpの設定を反映したい場合にはApacheのプロセスを再起動すればOKでしたが、nginxとphp-fpmはあくまで別プロセスなのでphpの設定を変更したらnginxではなくphp-fpmの再起動をしなくてはなりません。
SSL証明書は連結してあげればOK
Apacheではサーバ証明書(SSLCertificateFile)と中間証明書(SSLCertificateChainFile)と2ファイル設定するが、nginxではサーバ証明書、中間証明書の順に1ファイルに連結してあげてssl_certificateに設定する。
\ | apache | nginx |
---|---|---|
サーバ証明書 | SSLCertificateFile | ssl_certificate |
中間証明書 | SSLCertificateChainFile | - |
秘密鍵 | SSLCertificateKeyFile | ssl_certificate_key |
<VirtualHost _default_:443>
SSLCertificateFile hogehoge.crt
SSLCertificateKeyFile hogehoge.key
SSLCertificateChainFile hogehoge.ca
</VirtualHost>
# hogehoge.crt > hogehoge.pem
# hogehoge.ca >> hogehoge.pem
http {
server {
listen 443 ssl;
ssl_certificate hogehoge.pem
ssl_certificate_key hogehoge.key
}
}
SSLv3は無効化しておこう
nginxではデフォルトでSSL3.0が有効になっている。
POODLE脆弱性対策として、SSLv3を無効化しておこう。
http {
server {
listen 443 ssl;
...
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ## 使えるプロトコルをTLS1, 1.1, 1.2のみとする
POSTできる容量に注意
ApacheではデフォルトでPOSTできるBODYのサイズ(LimitRequestBody)が2GBなので気にならないですが、nginxではデフォルトは1MBに設定されています。
WordpressやownCloudで大きめなファイルをアップロードしたい場合は変更必須です。
http {
client_max_body_size 100m;
}