Edited at

Apacheからnginxへ移行する際に気になったことメモ

More than 3 years have passed since last update.

最近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です。


nginx.conf

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で管理した方が楽そう。


nginx-php.conf

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;
}


nginx.conf

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


httpd.conf

<VirtualHost _default_:443>

SSLCertificateFile hogehoge.crt
SSLCertificateKeyFile hogehoge.key
SSLCertificateChainFile hogehoge.ca
</VirtualHost>


nginx用に証明書を生成

# hogehoge.crt > hogehoge.pem

# hogehoge.ca >> hogehoge.pem


nginx.conf

http {

server {
listen 443 ssl;
ssl_certificate hogehoge.pem
ssl_certificate_key hogehoge.key
}
}


SSLv3は無効化しておこう

nginxではデフォルトでSSL3.0が有効になっている。

POODLE脆弱性対策として、SSLv3を無効化しておこう。


nginx.conf

http {

server {
listen 443 ssl;
...
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ## 使えるプロトコルをTLS1, 1.1, 1.2のみとする

https://www.nginx.com/blog/nginx-poodle-ssl/


POSTできる容量に注意

ApacheではデフォルトでPOSTできるBODYのサイズ(LimitRequestBody)が2GBなので気にならないですが、nginxではデフォルトは1MBに設定されています。

WordpressやownCloudで大きめなファイルをアップロードしたい場合は変更必須です。

http://nginx.org/en/docs/http/ngx_http_core_module.html#client_max_body_size


nginx.conf

http {

client_max_body_size 100m;
}