Ubuntu 12.04 + ruby 1.9.3 + nginx + unicorn + Redmine 2.0.3

@ さんにおすすめされたので、試しに導入してみました。

インストールしたPCは

  • CPU Pentium 3 450MHz
  • メモリ 256MB

という残念なスペックのものですが、nginx + unicornの組み合わせは強力なようで、2〜3人で使う分には十分快適でした。(重い処理でも2秒以内にはレスポンスが返ってくることが多い)

Apache + passenger という組み合わせも検証してみましたが、メモリが足りずにスワップが頻発してしまい、使い物になりませんでした。

OSのインストールと初期設定

真っさらの状態からUbuntu 12.04(Server)をインストールしました。
OSのインストール時に一緒にインストールするものを選択する画面では、OpenSSHのみ選択しておきました。

インストールが終わったら、SSHufwだけ軽く設定して、これから必要となるパッケージをインストールします。

MySQLをインストールする際にパスワードとして使う文字列を聞かれるので、インストール中にお茶を飲みに行く際には注意。

sudo apt-get update && sudo apt-get upgrade && sudo apt-get install git build-essential zlib1g-dev libssl-dev libreadline-dev libyaml-dev libxml2-dev libxslt-dev libsqlite3-dev mysql-server libmysqlclient-dev libpcre3-dev python-software-properties sysv-rc-conf
パッケージ 必要な理由
git rbenv等をダウンロードするのに便利(git-coreから名称変更になった)
build-essential Rubyをビルドするのに必要
zlib-1g-dev 〜 libsqlite3-dev Rubyのビルドに含めていないと、ビルドし直すハメになる(Ruby on Rails 3.2 を Ubuntu にインストールする手順をかなり丁寧に説明してみました - Rails 雑感 - Ruby on Rails with OIAX)
mysql-server データベースにはMySQLを使う
libmysqlclient-dev RubyからMySQLを利用する際にmysql2というgemを利用するが、そのgemをインストールする際に必要
libpcre3-dev nginxが要求するらしい(未確認)
python-software-properties launchpadのaptリポジトリの追加が簡単になる。nginxのリポジトリを追加するのに使った
sysv-rc-conf スタートアップの管理に便利

rbenv + ruby_buildのインストール

Ubuntu 12.04からapt-getでrbenvをインストールできるようになったのですが、インストール時になぜか ruby 1.8 + ruby 1.9 がインストールされる謎仕様なので、apt-getを使わずにインストールしました。

rbenvの初期化設定は、.bash_profile や .zsh_profile に書くのが普通ですが、bashしか利用しないので .profile に記述しました。

rbenvインストール
# ホームディレクトリで作業する
$ cd ~

# ~/.rbenv にrbenvをダウンロード
$ git clone git://github.com/sstephenson/rbenv.git .rbenv

# パスを追加したり、初期化設定を書き込んだり
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.profile
$ echo 'eval "$(rbenv init -)"' >> ~/.profile
ruby_buildインストール
$ mkdir src
$ cd src
$ git clone git://github.com/sstephenson/ruby-build.git
$ cd ruby-build

# ここは sudo でないといけないらしい(http://d.hatena.ne.jp/tackman/20120320/1332231611)
$ sudo ./install.sh

設定を読みこませるために、一旦ログアウトしてから入り直す。

Ruby 1.9.3-p194 をインストール
# インストールできるRubyのリストを表示
$ rbenv install -l

# 1.9.3-p194をインストール(非常に時間が掛かる)
$ rbenv install 1.9.3-p194

# 1.9.3-p194を通常使うRubyとして設定する
$ rbenv global 1.9.3-p194

# bundleというパッケージマネージャをインストール
$ gem install bundle

# RubyからMySQLを利用する際には、コレを入れておくとパフォーマンスが劇的に改善するとのこと http://redmine.jp/guide/RedmineInstall/
$ gem install mysql2

# インストールしたgemをパスに追加する
$ rbenv rehash

# rbenv rehashするのが面倒だと感じるなら、以下のgemも入れておく(Rubyのバージョンごとに必要であることに注意)
$ gem i rbenv-rehash

Redmineのインストール

ここを見たほうが確実だと思います!
Redmineのインストール | Redmine.JP

$ cd ~/src

# ダウンロード
$ wget http://rubyforge.org/frs/download.php/76259/redmine-2.0.3.tar.gz

# 解凍
$ tar zxvf redmine-2.0.3.tar.gz 

# /var/redmine に入れることにした
$ sudo mv redmine-2.0.3 /var/redmine
$ cd /var/redmine

# 必要なパッケージをインストールする
# プロダクト環境しか要らない(--without development test)
# mysqlしか使わない(--without postgresql sqlite)
# 画像処理のライブラリは、導入が面倒くさそうなので外す(--without rmagick)
# インストール先はvendor/bundle
$ bundle install --without development test rmagick postgresql sqlite --path vendor/bundle

MySQLの設定

# パスワード付きでrootでログイン
$ mysql -u root -p

# データベース名は"redmine" で文字コードをUTF-8にする
> create database redmine character set utf8;

# redmineが使うユーザー名も"redmine"にする。パスワードは適切に付ける
> create user 'redmine'@'localhost' identified by '********';

# redmine(DB)の権限をredmine(ユーザー名)にすべて渡す
> grant all privileges on redmine.* to 'redmine'@'localhost';

RedmineMySQLを使えるようにする

$ cd /var/redmine

# 設定例をコピーする
$ cp config/database.yml.example config/database.yml

# 設定を書く
$ vim config/database.yml
# production環境の設定を変更する
production:
  adapter: mysql2
  database: redmine
  host: localhost
  username: redmine
  password: ********
  encoding: utf8
# セッションストアの秘密鍵を生成
$ bundle exec rake generate_secret_token

# データベースの初期設定を行う
$ RAILS_ENV=production bundle exec rake db:migrate

# デフォルトデータを設定(強く推奨と書かれていた)
# 言語を聞かれるので、ja と入力
$ RAILS_ENV=production bundle exec rake redmine:load_default_data
# テストが行える(Ctrl+Cで終了)
$ bundle exec rails s -e production

Unicornのインストールと設定

# unicornをbundleに管理させる
$ echo "gem 'unicorn'" >> Gemfile.local

# インストール(Redmineのインストール時に行ったのと同じコマンド)
$ bundle install --without development test rmagick postgresql sqlite --path vendor/bundle

ここで、unicornの設定ファイルを書かないといけないのですが、よく分からないので

~/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/unicorn-4.3.1/examples

に入っている設定をコピー&編集しました。

設定ファイルはココにあります

こだわったポイントは、

  • メモリが少ないので、worker_processesは1に(1プロセス50MBほど消費する)
  • userはwww-dataに(あとでredmineのディレクトリの権限を変更)
  • timeoutはデフォルトの60秒に(30秒だと、unicornを起動した後の最初のアクセスがタイムアウトになる)
  • メモリが少ないので、preload_app は使用しない
  • メモリが少ないので、masterプロセスを再起動したときに、以前のmasterプロセスを止める(old_pid = "#{server.config[:pid]}.oldbin" のところ)

このファイルを config/unicorn.rb として保存します。
実行するには、

# -c 設定ファイルを指定
# -E 環境を指定
# -D デーモン化
$ bundle exec unicorn_rails -c config/unicorn.rb -E production -D

Unicornの起動スクリプト

実際に運用するためには、Unicornのデーモンが自動的に起動するようにしなければいけません。
そのために起動スクリプトはここから拝借しました。
nginx + unicornでrails3.1が動作する環境を作る - A Peak Never Ending !

USR2というシグナルを投げていたりしますが、それの意味はこちらを参照下さい
次世代RailsサーバーUnicornを使ってみた | TechRacho

私の環境にあわせて編集してできたファイルがこちらになります
https://gist.github.com/3616832#file_unicorn

これを /etc/init.d/unicorn として配置し、自動起動するように設定します。

sudo sysv-rc-conf unicorn on

nginxのインストールと設定

若干ではありますが、apt-getで入るバージョンが古いので、nginx公式のリポジトリから落としてきます。

こちらを参考にしました。
InstallJa

今回は特に問題なく新しいバージョンのものがインストールできましたが、気になる方はこちらを参考にして、バージョンを指定すると良いと思います。
apt-getで特定のバージョンをインストールする - Ryoの開発日記

$ sudo add-apt-repository ppa:nginx/stable
$ sudo apt-get update
$ sudo apt-get install nginx

ここで、Redmineのディレクトリの権限を変更しておきましょう。

cd /var/redmine
sudo chown -R www-data:www-data files log tmp public/plugin_assets
sudo chmod -R 755 files log tmp public/plugin_assets

nginxの設定ファイルは /etc/nginx にあります。
debian系のapacheの設定ファイルの作法のように、sites-available に設定ファイルを書き、それを有効にするというのが「正しい」書き方のようです。

しかしながら簡単にするため、今回は/etc/nginx.confを直接編集しました。

作法に則って書きたい方は、こちらを参考にしてみてください
http://prototype-beta.com/server/entry/12_ubuntu%E3%81%A7nginx_+_unicorn_-_%E8%A8%AD%E5%AE%9A%E7%B7%A8

また、nginx.confの設定例も

~/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/unicorn-4.3.1/examples

に入っているものをコピー&編集しました。

exmaplesに入っている設定は、キャッシュを有効に利用してくれる、なかなか優秀な設定だという噂が。。。

書いた設定がこちらになります。
https://gist.github.com/3616832#file_nginx.conf

text/htmlが重複しているという旨のエラーメッセージが表示された方はこちらを参照下さい。
http://shiken.infrabu.info/nginx/nginx%E3%82%A8%E3%83%A9%E3%83%BC%EF%BC%88warn-duplicate-mime-type-texthtml%EF%BC%89/

起動する

$ sudo service nginx restart

普通にアクセスすればredmineのトップページが表示されるはずです。

メモリに余裕がある方は、unicornのworker_processを増やしたり、preload_appを有効にしてみると良いのではないでしょうか。