nginx+UnicornでRedmineを動かす 2/3 「nginx+Unicornの設定」編

nginx(エンジンエックス)はロシアで開発されているWebサーバ兼リバースプロキシサーバです。消費リソースが低く、高負荷状態でも性能が劣化しにくい特徴があり、GitHubやHeroku、WordPress.comで採用されるなど近年人気が高まっています。

nginx単体では動的なコンテンツを取り扱えないため、nginxでRailsアプリを動作させるためにはアプリケーションサーバとの連携が必要になります。

Rails用のアプリケーションサーバとしてはPassengerなどが有名ですが、最近ではこちらも低消費リソースで高負荷に対応したUnicornが注目されています。

Unicornの設定

nginx+UnicornでRedmineを動作させるにあたり、まずはアプリケーションサーバであるUnicornのセットアップから始めます。Unicornの概要については以下のページが参考になります。

Unicornのインストール

gemでUnicornをインストールします。

$ sudo gem install unicorn

Unicornの設定

RedmineにUnicorn用の設定ファイルを追加します。設定ファイルの内容は以下のページを参考にしました。

$ vim /var/www/redmine/config/unicorn.rb
    # ワーカーの数
    worker_processes 1
    # ソケット経由で通信する
    listen File.expand_path('tmp/sockets/unicorn.sock', ENV['RAILS_ROOT'])
    # ログ
    stderr_path File.expand_path('log/unicorn.log', ENV['RAILS_ROOT'])
    stdout_path File.expand_path('log/unicorn.log', ENV['RAILS_ROOT'])
    # ダウンタイムなくす
    # preload_app true

    before_fork do |server, worker|
      defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect!

      old_pid = "#{ server.config[:pid] }.oldbin"
      unless old_pid == server.pid
        begin
          # SIGTTOU だと worker_processes が多いときおかしい気がする
          Process.kill :QUIT, File.read(old_pid).to_i
        rescue Errno::ENOENT, Errno::ESRCH
        end
      end
    end

    after_fork do |server, worker|
      defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection
    end

preload_appをtrueにするとmasterプロセスの使用メモリが増えるため無料VPSの貧弱メモリ環境ではOFFにしました。通常はONでよいと思います。(参考:unicornのpreload_app - motsatのブログ)

Unicornの起動

unicorn_railsコマンドでUnicornを起動します。

$ cd /var/www/redmine
$ unicorn_rails -c config/unicorn.rb -E production -D
    -c : 設定ファイル
    -E : RAILS_ENV(デフォルトはdevelopment)
    -D : デーモンとして動作

psコマンドでmasterプロセスとworkerプロセスが動いていることを確認します。

$ ps auxf

Unicornの操作

Unicornの終了や再起動はkillコマンドによるシグナルの送信で行います。

$ cd /var/www/redmine
終了
    $ kill -QUIT `cat tmp/pids/unicorn.pid`
再起動
    $ kill -HUP `cat tmp/pids/unicorn.pid`

nginxの設定

続いてnginxをセットアップしていきます。nginxの概要・使い方については以下のページが参考になります。

Apacheの無効化

nginxのセットアップを始める前に、apacheを無効化しておきます。

$ sudo chkconfig httpd off
$ sudo service httpd stop

nginxのインストール

nginxはEPELリポジトリからインストールすることもできますが、nginxの公式リポジトリで最新版が提供されているため、こちらを利用します。

$ wget http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm
$ sudo rpm -ivh nginx-release-centos-6-0.el6.ngx.noarch.rpm
$ cat /etc/yum.repos.d/nginx.repo
    # nginx.repo

    [nginx]
    name=nginx repo
    baseurl=http://nginx.org/packages/centos/6/$basearch/
    gpgcheck=0
    enabled=1
$ sudo yum install nginx
$ sudo service nginx start

サービス起動後、ブラウザからアクセスすると初期ページが確認できます。

nginx 初期画面 nginx 初期画面

nginxの設定確認

標準の設定ファイルは以下の場所にあります。内容をひと通り確認しておきましょう。

$ cat /etc/nginx/nginx.conf
$ cat /etc/nginx/conf.d/default.conf

nginxのUnicorn連携設定

nginxの設定ファイルを変更して、静的ファイル以外はリバースプロキシでUnicornのソケットへ通信を通すようにします。設定内容は以下のページを参考にしました。

なお、「unicorn-redmine」としている部分(2箇所)は、ドメイン名等に関係なく任意の名前を付けることができます。

$ cd /etc/nginx/conf.d/
$ sudo cp -p default.conf default.conf.bak
$ sudo vim default.conf
    upstream unicorn-redmine {
        server unix:/var/www/redmine/tmp/sockets/unicorn.sock fail_timeout=0;
    }
    server {
        listen       80;
        server_name  localhost;

        ~中略~

        #location / {
        #    root   /usr/share/nginx/html;
        #    index  index.html index.htm;
        #}

        location / {
            root   /var/www/redmine/public;
            index  index.html index.htm;

            if (-f $request_filename) { break; }
            proxy_set_header X-Real-IP  $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $http_host;
            proxy_pass http://unicorn-redmine;
        }

        ~中略~

    }

設定ファイルの構文をチェックし、nginxを再起動します。

$ sudo nginx -t
$ sudo service nginx restart

ブラウザからアクセスして動作を確認します。

Redmine 初期画面 Redmine 初期画面

Unicorn起動スクリプトの作成と実行ユーザの設定

運用にあたり、少し追加の設定をしておきます。

Unicorn起動スクリプト

Unicornの起動スクリプトを作成して、OS起動時に自動的にUnicornが起動するようにしましょう。また、これによりserviceコマンドでUnicornの操作が可能になります。

起動スクリプトは以下のページを参考にしました。

$ sudo vim /etc/init.d/unicorn_redmine
    #!/bin/bash
    #
    # unicorn_redmine Startup script for unicorn.
    #
    # chkconfig: - 85 15
    # description: redmine on unicorn start/stop script.
    #

    set -u
    set -e

    APP_NAME=redmine
    APP_ROOT="/var/www/$APP_NAME"
    CNF="$APP_ROOT/config/unicorn.rb"
    PID="$APP_ROOT/tmp/pids/unicorn.pid"
    ENV=production
    UNICORN_OPTS="-c $CNF -E $ENV -D"
    old_pid="$PID.oldbin"

    cd $APP_ROOT || exit 1

    sig () {
            test -s "$PID" && kill -$1 `cat $PID`
    }
    oldsig () {
            test -s $old_pid && kill -$1 `cat $old_pid`
    }

    case ${1-help} in
    start)
            sig 0 && echo >&2 "Already running" && exit 0
            cd $APP_ROOT ; unicorn_rails $UNICORN_OPTS
            ;;
    stop)
            sig QUIT && exit 0
            echo >&2 "Not running"
            ;;
    force-stop)
            sig TERM && exit 0
            echo >&2 "Not running"
            ;;
    restart|reload)
            sig HUP && echo reloaded OK && exit 0
            echo >&2 "Couldn't reload, starting instead"
            unicorn_rails $UNICORN_OPTS
            ;;
    upgrade)
            sig USR2 && exit 0
            echo >&2 "Couldn't upgrade, starting instead"
            unicorn_rails $UNICORN_OPTS
            ;;
    rotate)
            sig USR1 && echo rotated logs OK && exit 0
            echo >&2 "Couldn't rotate logs" && exit 1
            ;;
    *)
            echo >&2 "Usage: $0 <start|stop|restart|upgrade|rotate|force-stop>"
            exit 1
            ;;
    esac
$ sudo chmod +x /etc/init.d/unicorn_redmine
$ sudo chkconfig unicorn_redmine on
$ sudo chkconfig --list unicorn_redmine
unicorn_redmine 0:off   1:off   2:on    3:on    4:on    5:on    6:off

Unicornのワーカープロセス実行ユーザ設定

Unicornのワーカープロセス実行ユーザを設定し、指定したユーザでRedmineを実行するようにしましょう。

ユーザを追加し、Redmine関連ファイルの所有権を変更します。

$ sudo useradd -s /sbin/nologin redmine
$ sudo chown -R redmine:redmine /var/www/redmine

Unicornの設定ファイル末尾にワーカープロセス実行ユーザ・グループの指定を追加します。

$ sudo vim /var/www/redmine/config/unicorn.rb
    user 'redmine', 'redmine'

Unicornの再起動

Unicornを再起動してserviceコマンドが使用できることと、ワーカープロセスの実行ユーザが変更されたことを確認します。

$ sudo service unicorn_redmine stop
$ sudo service unicorn_redmine start
$ ps auxf

以上でnginxとUnicornの設定は完了です。

その他参考ページ

本文中でリンクした以外の参考ページは以下のとおり。

おわりに

無事、nginx+UnicornでRedmineを動作させることができました。HOST1FREEの無料VPS環境でも、それなりに実用的なレスポンスで使えています。

今回はひとまずRedmineをトップディレクトリで動作させましたが、最終的にはサブディレクトリで使用したいと思っています。PassengerであればRailsBaseURIなどで対応できるはずですが、nginx+Unicornの場合どのように設定すれば良いのか、まだよく分かっていません。

nginx+UnicornでRedmineをサブディレクトリに設置する方法について、動作確認情報等ありましたらコメントからご連絡いただけると助かります。

追記@2012/07/30

サブディレクトリへの設置方法について確認できたため、「サブディレクトリ」編を追加しました。

連載一覧

blog comments powered by Disqus