「さくらのVPS」でっていうのがいいタイトルなのかどうかわからないけど、実際のところはDebina 6で構築する話。ApacheをWebサーバとして公開していたRedmine/Trac/Subversionをある機会でNginxに切り変えることにした。
Nginxにする動機
正直なところ、個人利用のRedmineやTracでパフォーマンスを気にする必要もあまりなく、これ単独でNginxにする動機はない。背景にはレンタルサーバで公開しているWordPressのblogをNginx+php-fpmを利用する形でさくらのVPS 2Gに移行しようと思っていたことがある。するとPort 80をNginxに明け渡さないといけなくなるため他のサービスも対応が必要になる。
方針
今回は以下の方針でいくことにする
- RedmineはNginx+passengerで公開
- Trac/SubversionはApacheをバックエンドにしてNginxをリバースプロキシとして公開
Trac/Subversionはもうreadonlyでほとんど使っていないので本来はRedmine/Gitに移行したいところなのである。必要なものは移行したが開発を辞めてしまったYahoo! WidetやMovableTypeプラグインなどは移行コストと構築コストを考えたときに後者を取ってしまっているのが現状である。今回もさくらのVPS 2Gに構築したときも悩んだがやはり面倒になったのでそのままTrac/Subversionを構築してしまった。パフォーマンスを気にする必要もなく、メンテナンスコストを掛けたくないので別にApacheのままでいいという判断である。
対してRedmineについては現在も利用しているし、Railsはそれほど設定に悩まなそうなので(これは甘い見通しだったが)Nginxに移行してみようと考えた。
Nginxのインストール
なお、ここからの手順はすべてrootで実行している。
Debian squeezeからインストールしたら、Nginx 0.7だった。ちょっと古いと思いunstableから入れようかと思ったがdotdebという便利なリポジトリがあるようなのでこれを使ってみることに。
dotdebリポジトリを追加
/etc/apt/sources.list
に以下を追加。
# dotdeb.org
deb http://packages.dotdeb.org stable all
deb-src http://packages.dotdeb.org stable all
GnuPG キーの追加のため以下を実行する。
cd /tmp
wget http://www.dotdeb.org/dotdeb.gpg
cat dotdeb.gpg | apt-key add -
とりあえず更新
aptitude update
nginx-extrasのインストール
https://docs.google.com/a/moolfreet.com/spreadsheet/ccc?key=0AjuNPnOoex7SdG5fUkhfc3BCSjJQbVVrQTg4UGU2YVE#gid=0
nginx-extrasではPassengerに対応してくれている。サイコー。
http://www.dotdeb.org/2011/05/07/rails-user-dotdeb-now-supports-passenger/
というわけでインストールする。
aptitude install nginx-extras
デフォルトだとport 80を使うようになっているのでApacheを動かしているとNginxは開始できないと思われる。
Nginxの設定
細かい調整は今後必要になってくる、とりあえずサーバのバージョン情報を返すのを無効にしておく。
server_tokens off;
Passenger(Ruby On Rails)のために以下のコメントを外しておく。
##
# nginx-passenger config
##
# Uncomment it if you installed nginx-passenger
##
passenger_root /usr;
passenger_ruby /usr/bin/ruby;
Virtual Hostの設定
Debian/UbuntuでApacheとおなじみの管理方式になっている。nginx.confよりsites-enabled/*
がIncludeされており、sites-availableにサイトごとの設定を書いて、sites-enabeldにシンボリックリンクを張る方式である。
a2ensite/a2dissite
と同様のコマンドngxensite/ngxdissite
がインストールされていた。これを使うとsites-availableにファイルを置いておけば有効・無効(シンボリックリンクの生成・削除)は以下のように行える。
# 有効にする
ngxensite (ファイル名)
# 無効にする
ngxdissite (ファイル名)
a2ensiteでは複数のファイルを指定できたが、ngxensiteで複数指定しても最初のファイルしか有効にならなかった。
Apacheの設定変更
Apacheはバックエンドとして動かすことになるのでいくつかの設定変更が必要になってくる。
Portの変更
VirutalHostで公開しているのでそれぞれのPortを変更する。まずListeningのPort変更。
NameVirtualHost *:8081
Listen 8081
mod_rpafのインストール
NginxをリバースプロキシとしてApacheをバックエンドで動作させる場合、Apacheから見て接続してくるクライアントはNginxである。同じサーバで動かすので同じホストからアクセスされることになる。この場合、ログのリモートホストが127.0.0.1で出力されたり、グローバルIPで接続を制限していても127.0.0.1からのアクセスなので素通りになったりして面倒なことになる。
これらを解決するのがmod_rpafである。mod_rpafはリバースプロキシが送ってくるX-Forwarded-Forなどのヘッダを見てリバースプロキシのリクエスト元をリモートホストとして処理してくれる。
mod-rpafもaptでインストールできた。
aptitude install libapache2-mod-rpaf
a2enmod rpaf
デフォルトの設定は以下のようになっていたのでApacheとNginxを同一サーバで動かすならこのままでいい。
<IfModule mod_rpaf.c>
RPAFenable On
RPAFsethostname On
RPAFproxy_ips 127.0.0.1
</IfModule>
X-Forwarded-Forのヘッダの設定などはNginx側で行う必要があるがそれはこのあとに記載する。
サイトの設定
さて、いよいよここからApacheからNginxへの移行のためのサイト設定になる。
まずApacheのVirutalHostのポートを以下のようにして変更しておく。
<VirtualHost *:8081>
次にNginxのサイト設定を行う。説明の都合で一つにまとめると以下のような感じになる。
server {
root /usr/share/nginx/www;
index index.html
server_name example.com;
location / {
try_files $uri $uri/ /index.html;
}
location /redmine {
passenger_enabled on;
passenger_base_uri /redmine;
}
location /trac {
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:8081;
}
location /svn {
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:8081;
}
location ~ /\.ht {
deny all;
}
}
Trac/Subversionはそれぞれサブディレクトリで公開していたので、それぞれのlocationでproxy_passtとして同じサーバでポート8081で動いているApacheを指定し、X-Forwarded-Forの設定を行なっている。
ドキュメントルートがデフォルト(/usr/share/nginx/www)のままだが実際にはApacheの際のドキュメントルートと同じものを設定している。そのためApacheの.htで始まるファイルを返してしまわないようにアクセスを拒否する設定をいれている。
Redmineもサブディレクトリで公開している。nginx.confでpassenger_rootとpassenger_rubyの設定は有効にしたのでここでは、passenger_enabled、passenger_base_uriの設定を追加している。ちなみにRailsアプリをサブディレクトリで公開するための設定はPassengerのサイトに書いてあった。他にもいろいろな情報があって参考になる。
http://www.modrails.com/documentation/Users%20guide%20Nginx.html#deploying_rails_to_sub_uri
Nginxのログローテーション
Apacheにはrotatelogsという専用モジュールへログファイルをpipeして日付をファイル名につけてローテーションできたがNginxではそのような機能はなく、logrotateを使うのが基本のようである。デフォルトでは以下のようなファイルがインストールされていた。
/var/log/nginx/*.log {
daily
missingok
rotate 52
compress
delaycompress
notifempty
create 0640 www-data adm
sharedscripts
prerotate
if [ -d /etc/logrotate.d/httpd-prerotate ]; then \
run-parts /etc/logrotate.d/httpd-prerotate; \
fi; \
endscript
postrotate
[ ! -f /var/run/nginx.pid ] || kill -USR1 `cat /var/run/nginx.pid`
endscript
}
logrotateを調べたところdateextというオプションがあるのでdailyと併用すれば日付の名前をつけてローテーションできるようだ。確かlogrotateにはログを恒久的に残すという仕様はなかったと思うので、rotateの設定で世代を沢山残すようにするか自分でファイルをコピーするかしないといけない。
置き換え
ひと通り設定が終わったので、Apache/Nginxを再起動する。Nginxのデフォルトサイトは無効にしておく。ブラウザでアクセスできれば成功となる。
ngxdissite default
ngxensite example
/etc/init.d/apache restart
/etc/init.d/nginx restart
参考になったもの
このエントリを書いている時点で日本語の本はこれしかないと思われる。最初の情報としてはかなり訳にたつ。
Nginxの設定に書けるDirective一覧。新しいサービスはドラスティックに変わっていくのでまずはオフィシャルな情報をチェックするに限る。
Nginx – Directive Index
RedmineのようなRuby On RailsをApache/Nginxで実行させるPassengerのNginx向けのドキュメント、各種設定について参考になる。
Phusion Passenger users guide, Nginx version
まとめ
細かい設定などまだまだ勉強することは多いが、設定の書き方など結構フレキシブルな感じがある。例えばaccess_logがlocationディレクティブでも書けるので今回のようにサービスごとにサブディレクトリに分けている場合はサービスごとにログファイルを運用することも可能である。(Aapcheでも同様のことはできるがちょっと面倒というか設定に可読性があまりないと思う)
まだまだ何をするにせよApacheからNginxへの翻訳が必要な状況だが使っていくうちに覚えるであろうと信じたい。今回はあくまでWordpressを持ってくるための事前準備なので、次はWordpressの移行に取り組みたい。
試行錯誤集
うまくいった手順だけを書くと簡単に見えてしまうが、ここにたどり着くまでいろいろあった。同じことにハマった人のために紹介しておく。
X-Forwarded-Forの設定は明示的に必要
Apacheにmod_rpafを入れたらそれでokと思っていたがApacheのログが127.0.0.1になる。Nginxはproxy_passを設定してもX-Forwarded-Forの設定は自前でする必要があるようだ。しばらくApache側の設定反映を疑ったため時間を浪費した。
gem passengerは使わなくていい
Passengerのインストール方法をみるとNginxへのインストールには、
gem install passenger
passenger-install-nginx-module
を実行すればよくて、最初はこれに従ってみたところ以下のような質問が表示された。
Automatically download and install Nginx?
Nginx doesn't support loadable modules such as some other web servers do,
so in order to install Nginx with Passenger support, it must be recompiled.
Do you want this installer to download, compile and install Nginx for you?
1. Yes: download, compile and install Nginx for me. (recommended)
The easiest way to get started. A stock Nginx 1.0.10 with Passenger
support, but with no other additional third party modules, will be
installed for you to a directory of your choice.
2. No: I want to customize my Nginx installation. (for advanced users)
Choose this if you want to compile Nginx with more third party modules
besides Passenger, or if you need to pass additional options to Nginx's
'configure' script. This installer will 1) ask you for the location of
the Nginx source code, 2) run the 'configure' script according to your
instructions, and 3) run 'make install'.
Whichever you choose, if you already have an existing Nginx configuration file,
then it will be preserved.
え、せっかくaptでnginx入れたのに何いってんの?ちょっと待ってちょっと待ってちょっと待って。でキャンセルした。そう、この方法でインストールする場合、Passenger機能の付いたnginxをビルドして新規にインストールすることになる。でもやっぱり管理上、aptで運用したい。
libapache2-mod-passengerがあるんだからnginxのパッケージもあるんじゃないのとapt-cache search passengerで検索してnginx-extrasが見つかったのでgem uninstall passengerで消えてもらった。
passenger-install-nginx-moduleを実行するためにいろんなパッケージを入れたのはここだけの秘密。
nginx-fullはnginx-extrasの上位版ではない
dotdebからnginxをインストールするとnginx-fullがインストールされる。さらにnginx-extrasをインストールしようとするとnginx-fullと衝突したので、nginx-fullはnginx-extrasを包括しているんだろうと勝手に勘違いしてしまった。そのためpassengerの設定をしようとすると「 unknown directive “passenger_root” 」とか言われて怒られる。
nginx-fullとnginx-extrasのパッケージの情報を表示してみたところ以下のようにモジュールが異なっていた。
(nginx-full)
Standard HTTP Modules:
Core, Access, Auth Basic, Auto Index, Browser, Charset, Empty GIF, FastCGI,
Geo, Gzip, Headers, Index, Limit Requests, Limit Zone, Log, Map, Memcached,
Proxy, Referer, Rewrite, SCGI, Split Clients, SSI, Upstream, User ID, UWSGI
Optional HTTP Modules:
Addition, Debug, GeoIP, Gzip Precompression, HTTP Sub, Image Filter, IPv6,
RealIP, Secure link, Stub Status, SSL, WebDAV, XSLT
Other Modules:
File AIO
Mail Modules:
Mail Core, IMAP, POP3, SMTP, SSL
Third Party Modules:
Auth PAM, Cache purge, Echo, Syslog, Upstream Fair Queue
(nginx-extras)
Standard HTTP Modules:
Core, Access, Auth Basic, Auto Index, Browser, Charset, Empty GIF, FastCGI,
Geo, Gzip, Headers, Index, Limit Requests, Limit Zone, Log, Map, Memcached,
Proxy, Referer, Rewrite, SCGI, Split Clients, SSI, Upstream, User ID, UWSGI
Optional HTTP Modules:
Addition, Debug, WebDAV, Flash Streaming Video, GeoIP, Gzip Precompression,
HTTP Sub, Image Filter, MP4, RealIP, Stub Status, SSL, XSLT, IPv6, Embedded
Perl, Secure Link, Random Index
Mail Modules:
Mail Core, POP3, IMAP, SMTP, SSL
Third Party Modules:
Echo, Embedded Lua, http push, Nginx Development Kit, Upload module,
Upload Progress, HttpHeadersMore, Upstream Fair Queue, Chunkin, Auth PAM
Modules added by Dotdeb:
File AIO, Syslog, Cache purge, Passenger
というわけで nginx-extras > nginx-full である。nginx-fullを削除して、nginx-extrasを入れなおすはめになった。