Redmine を Nginx + Unicorn で動かす

前回までのあらすじ

Nginx を Apache のリバースプロキシに設定した。

今日の目標

現在 Apache + Passenger で動いている Rails アプリの Redmine を Nginx + Unicorn に切り替えてみよう。

Redmine は /var/www/redmine に設置されている。

Gem の追加

Redmine の gem に unicorn を追加する。

もしRedmine本体は使用しないgem(例: mongrel, fcgi)もロードしたい場合、 Gemfile.local というファイルをRedmineのディレクトリに作成してください。 Redmineのインストール — Redmine Guide 日本語訳

ということなので Gemfile.local を作成した。

# Gemfile.local
gem "unicorn"

インストール。

$ bundle install

Unicorn の設定

Redmine の config ディレクトリに unicorn.rb というファイルを作成した。

worker_processes 1

timeout 60

listen File.expand_path("tmp/sockets/unicorn.sock", ENV['RAILS_ROOT'])

pid File.expand_path("tmp/pids/unicorn.pid", ENV['RAILS_ROOT'])

stdout_path File.expand_path("log/unicorn.stdout.log", ENV['RAILS_ROOT'])
stderr_path File.expand_path("log/unicorn.stderr.log", ENV['RAILS_ROOT'])

preload_app true
GC.respond_to?(:copy_on_write_friendly=) and GC.copy_on_write_friendly = true

before_fork do |server, worker|
  # この設定はpreload_app trueの場合に必須
  defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect!

  # USR2シグナルで旧プロセスを終了させる
  old_pid = "#{server.config[:pid]}.oldbin"
  if old_pid != server.pid
    begin
      sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU
      Process.kill(sig, File.read(old_pid).to_i)
    rescue Errno::ENOENT, Errno::ESRCH
    end
  end
end

after_fork do |server, worker|
  # この設定はpreload_app trueの場合に必須
  defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection
end

とりあえず socket のパス。これ大事。

tmp/sockets/unicorn.sock

pid のパス。これも大事。

tmp/pids/unicorn.pid

Unicorn 起動

え、Unicorn て Apache とか Nginx とかとは別口で起動しておかないといけないの?

後で自動化できないか調べなきゃ。

$ bundle exec unicorn_rails -c config/unicorn.rb -D -E production

コマンドのオプションは -c で設定ファイル指定、-E で動作モード指定、-D がデーモン化。

終了の仕方は力ずく。

$ kill -quit 'cat /var/www/redmine/tmp/pids/unicorn.pid'

Nginx の設定

/etc/nginx/sites-available/ に設定ファイルを作成して /etc/nginx/sites-enabled/ からリンクを張る。

upstream redmine {
  server unix:/var/www/redmine/tmp/sockets/unicorn.sock;
}

server {
  listen 80;
  server_name redmine.tepidworks.jp;

  location / {
    root /var/www/redmine/public;

    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 X-Forwarded-Proto $scheme;
    proxy_set_header Host $http_host;
    proxy_pass http://redmine;
  }
}

if ( -f $request_filename ) { break; } があるので、静的ファイルへのアクセスは Rails を通さないで Nginx が直接返す。*1

Nginx 再起動

$ sudo service nginx restart

無事アクセスできた。

*1:少なくとも、確認した限り静的ファイルへのアクセスでは Rails がログを吐かなかったので Unicorn に処理は渡っていないはず。