リバースプロキシを必要としており、当初、Apache でいこうかとも思っていたのだが、より軽量(メモリ消費量が少ない)で、パフォーマンスの高い Web サーバがないものかと物色していた。
nginx というロシア製のエンジンがなかなかよさそうなので、しばらく使ってみることにした。ちなみに、読み方は「エンジンエックス」のようだ。
ついでに、 Apache + Passenger で運用していた環境も nginx + Passenger に変更した。その際の設定メモを残しておく。
Table of Contents
Open Table of Contents
作業の前提
ここでの作業の前提としては、
- 既に Rails アプリケーションが動作する環境は構築されている
- 既存 Web アプリの環境としては、Apache2 + Passenger。
- サーバは Ubuntu 10.04 (Lucid)。Ruby は Enterprise Ruby を使用。
となる。
$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=10.04
DISTRIB_CODENAME=lucid
DISTRIB_DESCRIPTION="Ubuntu 10.04.1 LTS"
$ ruby -v
ruby 1.8.7 (2010-04-19 patchlevel 253) [i686-linux], MBARI 0x8770, Ruby Enterprise Edition 2010.02
Passenger がインストールされている必要があるので、インストールされていない場合は、インストールしておく。
nginx のインストール
nginx は、OS のパッケージ管理システム、もしくは、ソースからのビルドでもインストールを行える。
ここでは、Passenger をインストールすることで利用可能な passenger-install-nginx-module
コマンドで nginx のインストールを行う。
Passenger の nginx モジュールの組み込みの為に、nginx 自体リビルドし直す必要があるので、事前に nginx がインストールされている必要はない。
# passenger-install-nginx-module
Welcome to the Phusion Passenger Nginx module installer, v2.2.14.
This installer will guide you through the entire installation process. It
shouldn't take more than 5 minutes in total.
Here's what you can expect from the installation process:
1. This installer will compile and install Nginx with Passenger support.
2. You'll learn how to configure Passenger in Nginx.
3. You'll learn how to deploy a Ruby on Rails application.
Don't worry if anything goes wrong. This installer will advise you on how to
solve any problems.
Press Enter to continue, or Ctrl-C to abort.
--------------------------------------------
Checking for required software...
* GNU C++ compiler... found at /usr/bin/g++
* Ruby development headers... found
* OpenSSL support for Ruby... found
* RubyGems... found
* Rake... found at /usr/local/bin/rake
* rack... found
* OpenSSL development headers... found
* Zlib development headers... found
--------------------------------------------
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 0.7.65 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.
Enter your choice (1 or 2) or press Ctrl-C to abort:
ここでは、1 を選択する。
1 を選択した場合、/tmp
にソースがダウンロードされ、Passenger のインストーラが勝手にビルドしてくれる。
この後の質問でデフォルトのまま進めると、configure
のパラメータは以下の通りとなる。
# ./configure --prefix='/opt/nginx' --add-module='/usr/local/lib/ruby/gems/1.8/gems/passenger-2.2.14/ext/nginx'
引き続き、幾つか質問に答えていくが、基本デフォルトのままで進める。
-----
Nginx with Passenger support was successfully installed.
The Nginx configuration file (/opt/nginx/conf/nginx.conf)
must contain the correct configuration options in order for Phusion Passenger
to function correctly.
This installer has already modified the configuration file for you! The
following configuration snippet was inserted:
http {
...
passenger_root /usr/local/lib/ruby/gems/1.8/gems/passenger-2.2.14;
passenger_ruby /usr/local/bin/ruby;
...
}
After you start Nginx, you are ready to deploy any number of Ruby on Rails
applications on Nginx.
Press ENTER to continue.
-----
--------------------------------------------
Deploying a Ruby on Rails application: an example
Suppose you have a Ruby on Rails application in /somewhere. Add a server block
to your Nginx configuration file, set its root to /somewhere/public, and set
'passenger_enabled on', like this:
server {
listen 80;
server_name www.yourhost.com;
root /somewhere/public; # <--- be sure to point to 'public'!
passenger_enabled on;
}
And that's it! You may also want to check the Users Guide for security and
optimization tips and other useful information:
/usr/local/lib/ruby/gems/1.8/gems/passenger-2.2.14/doc/Users guide Nginx.html
Enjoy Phusion Passenger, a product of Phusion (www.phusion.nl) :-)
http://www.modrails.com/
Phusion Passenger is a trademark of Hongli Lai & Ninh Bui.
インストール完了。
これで、Passenger のモジュールを組み込んだ nginx が /opt/nginx
配下(デフォルトで進めた場合)にインストールされている。
とりあえず起動してみて、正常にインストールされているか確認する。
# /opt/nginx/sbin/nginx
確認する。
# netstat -lt
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 *:www *:* LISTEN
tcp 0 0 *:ssh *:* LISTEN
# ps faux | head -1 && ps faux | grep nginx | grep -v grep
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 7435 0.0 0.2 5672 692 ? Ss 20:46 0:00 nginx: master process /opt/nginx/sbin/nginx
nobody 7438 0.0 0.4 5836 1108 ? S 20:46 0:00 \_ nginx: worker process
上記の ps のプロセス、RSS(使用メモリ)の結果を見てもわるように、なかなか省エネな Web サーバだ。
ブラウザから確認してみると、とてもシンプルなご挨拶を確認できる。
一旦停止しておく。
# /opt/nginx/sbin/nginx -s stop
init script を用意する
init script を用しておく。
にある init script をそのまま使わせてもらう。
#! /bin/sh
## BEGIN INIT INFO
# Provides: nginx
# Required-Start: $all
# Required-Stop: $all
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: starts the nginx web server
# Description: starts nginx using start-stop-daemon
# see [Setup Ruby Enterprise Edition, nginx and Passenger (aka mod_rails) on Ubuntu](http://programmingzen.com/2009/11/20/setup-ruby-enterprise-edition-nginx-and-passenger-aka-mod_rails-on-ubuntu/)
## END INIT INFO
PATH=/opt/nginx/sbin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/opt/nginx/sbin/nginx
NAME=nginx
DESC=nginx
test -x $DAEMON || exit 0
# Include nginx defaults if available
if [ -f /etc/default/nginx ] ; then
. /etc/default/nginx
fi
set -e
. /lib/lsb/init-functions
case "$1" in
start)
echo -n "Starting $DESC: "
start-stop-daemon --start --quiet --pidfile /opt/nginx/logs/$NAME.pid \
--exec $DAEMON -- $DAEMON_OPTS || true
echo "$NAME."
;;
stop)
echo -n "Stopping $DESC: "
start-stop-daemon --stop --quiet --pidfile /opt/nginx/logs/$NAME.pid \
--exec $DAEMON || true
echo "$NAME."
;;
restart|force-reload)
echo -n "Restarting $DESC: "
start-stop-daemon --stop --quiet --pidfile \
/opt/nginx/logs/$NAME.pid --exec $DAEMON || true
sleep 1
start-stop-daemon --start --quiet --pidfile \
/opt/nginx/logs/$NAME.pid --exec $DAEMON -- $DAEMON_OPTS || true
echo "$NAME."
;;
reload)
echo -n "Reloading $DESC configuration: "
start-stop-daemon --stop --signal HUP --quiet --pidfile /opt/nginx/logs/$NAME.pid \
--exec $DAEMON || true
echo "$NAME."
;;
status)
status_of_proc -p /opt/nginx/logs/$NAME.pid "$DAEMON" nginx && exit 0 || exit $?
;;
*)
N=/etc/init.d/$NAME
echo "Usage: $N {start|stop|restart|reload|force-reload|status}" >&2
exit 1
;;
esac
exit 0
上記を /etc/init.d/nginx
に保存する。
確認する。
# /etc/init.d/nginx status
* could not access PID file for nginx
# /etc/init.d/nginx start
Starting nginx: nginx.
# netstat -lt
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 *:www *:* LISTEN
tcp 0 0 *:ssh *:* LISTEN
# ps faux | grep nginx | grep -v grep
root 6866 0.0 0.2 5672 696 ? Ss 20:23 0:00 nginx: master process /opt/nginx/sbin/nginx
nobody 6869 0.0 0.4 5836 1108 ? S 20:23 0:00 \_ nginx: worker process
# /etc/init.d/nginx stop
Stopping nginx: nginx.
# ps faux | grep nginx | grep -v grep
OK だ。
init script として登録しておく。
# update-rc.d -f nginx defaults
Adding system startup for /etc/init.d/nginx ...
/etc/rc0.d/K20nginx -> ../init.d/nginx
/etc/rc1.d/K20nginx -> ../init.d/nginx
/etc/rc6.d/K20nginx -> ../init.d/nginx
/etc/rc2.d/S20nginx -> ../init.d/nginx
/etc/rc3.d/S20nginx -> ../init.d/nginx
/etc/rc4.d/S20nginx -> ../init.d/nginx
/etc/rc5.d/S20nginx -> ../init.d/nginx
これで service コマンドでも使用可能となる。
# service nginx start
Starting nginx: nginx.
# service nginx status
* nginx is running
nginx の設定
※ nginx の設定については、別記事 Design Recipe 別館 Blog - Nginx の設定概要 にも記載しました。
現在 /opt/nginx
が nginx のホームディレクトリになっている。
インストール直後のディレクトリ構成は以下の通り。
# pwd
/opt/nginx
# ll
total 28
drwx------ 2 nobody root 4096 Jan 28 07:23 client_body_temp
drwxr-xr-x 2 root root 4096 Jan 28 07:06 conf
drwx------ 2 nobody root 4096 Jan 28 07:23 fastcgi_temp
drwxr-xr-x 2 root root 4096 Jan 28 07:06 html
drwxr-xr-x 2 root root 4096 Jan 28 07:28 logs
drwx------ 2 nobody root 4096 Jan 28 07:23 proxy_temp
drwxr-xr-x 2 root root 4096 Jan 28 07:06 sbin
上記の conf
ディレクトリ配下に、nginx のメインの(デフォルトで見に行く)設定ファイル nginx.conf
が存在する。
nginx の設定ファイルへの設定の記述は、DSL チックなわかり易いシンタックスとなっている。
必要なディレクティブ(Directive)を記述し、ディレクティブ毎に用意されているシンタックスにそって必要な設定を記述する。 コアとなるディレクティブは、以下のページで確認できる。
それぞれのディレクティブ毎に**シンタックス(syntax)の説明がある。nginx には、スコープ的な意味合いのコンテキスト(context)という概念があり、そのディレクティブが利用できるコンテキスト(context)**もこのレファレンスでが確認できる。
よく使われるディレクティブとしては、http
、server
、location
があり、http
は Web サーバとして共通の設定、server
はバーチャルサーバ毎の設定、location
は、URI 毎の設定となり、それぞれがそれぞれのコンテキストを持つ。
Apache などの設定ファイルに慣れていれば、パッと見で分りやすいと思うが、初めて見た時に一瞬戸惑った location
ディレクティブの modifier の部分についてだけメモしておく。
location
ディレクティブのシンタックスは以下の通りとなっている。
location [=|~|~*|^~|@] pattern { ... }
loation ブロックには、リクエスト URI に対するパターンを指定でき、以下のような記述になる。
server {
server_name example.com;
location /admin/ {
# http://example.com/admin/
}
}
http://example.com/admin/
が URI に指定されれば、上記のブロックの中の記述が適用される。
上記の URI に対するパターンの記述の前に幾つかの modifier が指定できる。その意味は以下の通り。
何も指定しない
- 上記の例のパターン。
/admin/
だけでなく、/admin/abc
などもマッチするが、他のパターンの指定で URI により適したパターンがある場合にはそちらが優先される。
- 上記の例のパターン。
=
- 定義されたパターンに完全一致する。
パターンは文字列のみを利用可能。
マッチするパターンが見つかった場合には、そこでパターンの検索は終了する。
- 定義されたパターンに完全一致する。
^~
- URI が指定したパターンで始まる場合にマッチする。
マッチするパターンが見つかった場合には、そこでパターンの検索は終了する。
- URI が指定したパターンで始まる場合にマッチする。
~
- 指定した正規表現にマッチする。
case-sensitive(大文字小文字を識別する)となる。
- 指定した正規表現にマッチする。
~*
- 指定した正規表現にマッチする。
case-insensitive(大文字小文字を識別しない)となる。
- 指定した正規表現にマッチする。
@
- named location block を定義する。
try_filesi
やerror_page
など他のディレクティブで参照することができる。
- named location block を定義する。
このパターンの指定と適用条件は若干の慣れが必要そうだ。
nginx + Passenger の設定を行う
nginx のインストール自体は問題なくいっているようなので、次に Passenger、Rails アプリとの連携部分の設定を行う。
インストール直後の conf/nginx.conf
をみてみると、passenger-install-nginx-module
がインストール時に必要最低限な設定を記述してくれているのが確認できる。
http {
passenger_root /usr/local/lib/ruby/gems/1.8/gems/passenger-2.2.14;
passenger_ruby /usr/local/bin/ruby;
これに対して、Rails アプリ固有の情報を追加しておく。最低限必要な設定は以下の 2 つになる。
- rails アプリの public ディレクトリを root として登録
- passenger を有効化
nginx.conf に上記の 2 つの設定を追加しておくことになる。
location / {
root /var/www/railsapp/public; # rails app の public ディレクトリを指定
passenger_enabled on; # passenger を有効にしておく
index index.html index.htm;
}
passenger-install-nginx-module
コマンドが生成した nginx.conf
に対して、とりあえず Rails アプリを動作させる為の必要最低限の変更を行った行った部分は以下の通りとなる。
# diff -u nginx.conf{,.org}
--- nginx.conf 2011-01-28 07:36:39.247744848 +0900
+++ nginx.conf.org 2011-01-28 07:06:32.652382472 +0900
@@ -44,8 +44,7 @@
#access_log logs/host.access.log main;
location / {
- root /var/www/railsapp/public;
- passenger_enabled on;
+ root html;
index index.html index.htm;
}
設定を再読込する。
# /opt/nginx/sbin/nginx -s reload
これで Rails アプリが利用可能となっている。
SSL を有効にする
SSL を有効にする。 設定は、http コンテキストの中に HTTPS を受ける server のコンテキストを追加する。
# HTTPS server
#
server {
listen 443;
server_name localhost;
ssl on;
ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem; # サーバ証明書を指定
ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key; # サーバ証明書の秘密鍵を指定
ssl_session_timeout 5m;
ssl_protocols SSLv2 SSLv3 TLSv1;
ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
ssl_prefer_server_ciphers on;
location / {
root /var/www/railsapp/public;
passenger_enabled on;
index index.html index.htm;
}
}
上記を nginx.conf
に追記して、設定のシンタックスを確認する。
# /opt/nginx/sbin/nginx -t
[emerg]: unknown directive "ssl" in /opt/nginx/conf/nginx.conf:110
configuration file /opt/nginx/conf/nginx.conf test failed
ssl ディレクティブは使えないよ、と怒られる。標準ビルドでは、SSL のモジュールは組み込まれていない為だ。
nginx は、1 つのバイナリファイルで簡潔している潔さがあり、Apache などと違い、動的なモジュールの追加を行わない。
必要なモジュールを追加する場合には、必要なモジュールを指定して、nginx をビルドし直すことになる。
(ちなみに、本運用に入った後に、モジュールを追加する場合などには、サーバ自体は止めずにモジュールの追加を行う方法は用意されているので安心。)
SSL のモジュールを追加で組み込むことにする。
Passenger の passenger-install-nginx-module
コマンドでインストールした時は、以下の configure オプションとなっていた。
# ./configure --prefix='/opt/nginx' --add-module='/usr/local/lib/ruby/gems/1.8/gems/passenger-2.2.14/ext/nginx'
なので、今回は、--with-http_ssl_module
を追加して configure からビルドし直す。
/tmp
に先にインストールを行った先のソースが残っていることを前提にする。
(サーバのリブートをしてると消されているはずなので注意。)
再度 passenger-install-nginx-module
を起動する。
# passenger-install-nginx-module
Welcome to the Phusion Passenger Nginx module installer, v2.2.14.
This installer will guide you through the entire installation process. It
shouldn't take more than 5 minutes in total.
Here's what you can expect from the installation process:
1. This installer will compile and install Nginx with Passenger support.
2. You'll learn how to configure Passenger in Nginx.
3. You'll learn how to deploy a Ruby on Rails application.
Don't worry if anything goes wrong. This installer will advise you on how to
solve any problems.
Press Enter to continue, or Ctrl-C to abort.
--------------------------------------------
Checking for required software...
* GNU C++ compiler... found at /usr/bin/g++
* Ruby development headers... found
* OpenSSL support for Ruby... found
* RubyGems... found
* Rake... found at /usr/local/bin/rake
* rack... found
* OpenSSL development headers... found
* Zlib development headers... found
--------------------------------------------
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 0.7.65 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.
Enter your choice (1 or 2) or press Ctrl-C to abort: 2
前回 passenger-install-nginx-module
を起動した時は、ここで 1 を選択したが、ここでは、 2 を選択する。
--------------------------------------------
Where is your Nginx source code located?
Please specify the directory: /tmp/nginx-0.7.65
--------------------------------------------
Where do you want to install Nginx to?
Please specify a prefix directory [/opt/nginx]:
--------------------------------------------
Extra Nginx configure options
If you want to pass extra arguments to the Nginx 'configure' script, then
please specify them. If not, then specify nothing and press Enter.
If you specify nothing then the 'configure' script will be run as follows:
./configure --prefix='/opt/nginx' --add-module='/usr/local/lib/ruby/gems/1.8/gems/passenger-2.2.14/ext/nginx'
Extra arguments to pass to configure script: --with-http_ssl_module
“Extra arguments to pass to configure script” で、--with-http_ssl_module
を追加する。
--------------------------------------------
Confirm configure flags
The Nginx configure script will be run as follows:
./configure --prefix='/opt/nginx' --add-module='/usr/local/lib/ruby/gems/1.8/gems/passenger-2.2.14/ext/nginx' --with-http_ssl_module
Is this what you want? (yes/no) [default=yes]: yes
configure オプションを確認して yes で続行。ビルドが行われる。
再度設定を確認する。
# /opt/nginx/sbin/nginx -t
the configuration file /opt/nginx/conf/nginx.conf syntax is ok
configuration file /opt/nginx/conf/nginx.conf test is successful
SSL モジュールを組み込んでいるので、今度は OK だ。 これで SSL も利用可能となっている。