Amazon Linux に WebSocketのプロキシに対応した nginx 1.4.0 をインストールしてみた

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

nginxは1.3.13からWebSocketのプロキシに対応したようです。
このフィーチャーを取り込んだ安定版1.4.0をAmazon Linuxにインストールしてみました。

まずはyumで古いバージョンをインストール

$ sudo yum install nginx
Loaded plugins: priorities, security, update-motd, upgrade-helper
Setting up Install Process
Resolving Dependencies
--> Running transaction check
---> Package nginx.x86_64 1:1.2.7-2.8.amzn1 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

====================================================================================================================================================================================================================
 Package                                        Arch                                            Version                                                    Repository                                          Size
====================================================================================================================================================================================================================
Installing:
 nginx                                          x86_64                                          1:1.2.7-2.8.amzn1                                          amzn-main                                          449 k

Transaction Summary
====================================================================================================================================================================================================================
Install       1 Package(s)

Total download size: 449 k
Installed size: 1.1 M
Is this ok [y/N]: y

yumでインストールできるのは1:1.2.7-2.8というバージョンでした。(※2013/05/02現在)

1.4.0をソースからビルド

まずはビルドに必要パッケージをインストール

$ sudo yum install gcc perl-ExtUtils-Embed pcre pcre-devel zlib zlib-devel

次にnginxとモジュールのソースをとってくる

$ sudo mkdir /usr/local/src/nginx && cd /usr/local/src/nginx
$ sudo wget http://nginx.org/download/nginx-1.4.0.tar.gz
$ sudo wget http://www.openssl.org/source/openssl-1.0.1e.tar.gz
$ sudo wget http://labs.frickle.com/files/ngx_cache_purge-2.1.tar.gz
$ sudo tar xvzf nginx-1.4.0.tar.gz
$ sudo tar xvzf openssl-1.0.1e.tar.gz
$ sudo tar xvzf ngx_cache_purge-2.1.tar.gz

nginx-1.4.0をビルド!

$ cd nginx-1.4.0
$ sudo ./configure --prefix=/usr/local/nginx-1.4.0 \
--sbin-path=/usr/local/sbin/nginx \
--with-openssl=/usr/local/src/nginx/openssl-1.0.1e \
--add-module=/usr/local/src/nginx/ngx_cache_purge-2.1 \
--conf-path=/etc/nginx/nginx.conf \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--http-client-body-temp-path=/var/lib/nginx/tmp/client_body \
--http-proxy-temp-path=/var/lib/nginx/tmp/proxy \
--http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi \
--http-uwsgi-temp-path=/var/lib/nginx/tmp/uwsgi \
--http-scgi-temp-path=/var/lib/nginx/tmp/scgi \
--pid-path=/var/run/nginx.pid \
--lock-path=/var/lock/subsys/nginx \
--user=nginx \
--group=nginx \
--with-file-aio \
--with-ipv6 \
--with-http_ssl_module \
--with-http_realip_module \
--with-http_addition_module \
--with-http_sub_module \
--with-http_dav_module \
--with-http_flv_module \
--with-http_mp4_module \
--with-http_gzip_static_module \
--with-http_random_index_module \
--with-http_secure_link_module \
--with-http_degradation_module \
--with-http_stub_status_module \
--with-http_perl_module \
--with-mail \
--with-mail_ssl_module \
--with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic' \
--with-ld-opt=' -Wl,-E'

$ sudo make
$ sudo make install

ビルドが全て終わったらシンボリックリンクを貼っておきます

$ sudo ln -s /usr/local/nginx-1.4.0 /usr/local/nginx

古いバージョンを削除し1.4.0に差し替え

設定ファイルと起動スクリプトを退避させてから古いバージョンを削除します。

$ sudo cp /etc/init.d/nginx ~/nginx.orig
$ sudo mv /etc/nginx /etc/_nginx
$ sudo yum remove nginx
Loaded plugins: priorities, security, update-motd, upgrade-helper
Setting up Remove Process
Resolving Dependencies
--> Running transaction check
---> Package nginx.x86_64 1:1.2.7-2.8.amzn1 will be erased
--> Finished Dependency Resolution

Dependencies Resolved

====================================================================================================================================================================================================================
 Package                                       Arch                                           Version                                                      Repository                                          Size
====================================================================================================================================================================================================================
Removing:
 nginx                                         x86_64                                         1:1.2.7-2.8.amzn1                                            @amzn-main                                         1.1 M

Transaction Summary
====================================================================================================================================================================================================================
Remove        1 Package(s)

Installed size: 1.1 M
Is this ok [y/N]: y

削除できたら退避させておいたファイルを戻しておきます

$ sudo mv ~/nginx.orig /etc/init.d/nginx
$ sudo mv /etc/_nginx /etc/nginx

WebSocketをリバプロできるようにコンフィグを書き換え

例えばNode.jsでSocket.ioを使って3000番ポートでアプリを起動しておいて、ブラウザからは80番でアクセスできるようにする場合を考えてみます
普通にproxy_passをlocationブロックの中で使えばいいのですが、http 1.1から別のプロトコルにスイッチするためのヘッダをセットしないと行けないようです。

/etc/nginx/nginx.conf

http {

    ... 省略 ...

    server {
        listen       80;
        server_name  localhost;

        location / {
            proxy_pass http://127.0.0.1:3000/;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
        }

        error_page  404              /404.html;
        location = /40x.html {
            root   /usr/share/nginx/html;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /usr/share/nginx/html;
        }
    }
}

コンフィグを書き換えたら一応チェックを実行しておいてください。

$ sudo /etc/init.d/nginx configtest
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

上記のメッセージが出れば成功です。
起動スクリプトの方もパスを通しておきます。22行目を以下のように変更しました。

- nginx="/usr/sbin/nginx"
+ nginx="/usr/local/sbin/nginx"

また/etc/sysconfig/nginxもなくなっているので作成しておきます。

/etc/sysconfig/nginx

NGINX=/usr/local/sbin/nginx

以上の設定でブラウザからSocket.ioを使用してサーバのアドレスに80で接続を測ればWebSocket接続が成功するはずです。
nginxを起動するには以下のコマンドを実行してください。

sudo /etc/init.d/nginx start
nginx を起動中:                                            [  OK  ]

まとめ

WebSocketはとても便利ですが、リバースプロキシがネックになっていたケースもあると思います。新しいnginxで柔軟にポートを変更できるようになって嬉しいですね!

参考にした記事