Chef で rbenv + Passenger の環境を構築する

rbenv + Passenger な環境の構築におおいにハマったのでメモ。

環境

  • CentOS 5.9
  • Chef 11.4.4
  • Berkshelf 1.4.3

Berksfile

rbenv と Apache のレシピは Berkshelf で取ってくる。
ここで注意点。 OpsCode Community サイトから取得できる rbenv のレシピ(http://community.opscode.com/cookbooks/rbenv) は rbenv 自体は入れられるが、
これで入れた rbenv 環境下で passenger をビルドすることができないっぽい。

rbenv 環境下でスクリプトを実行できるリソース定義はないものかと探したところ、
https://github.com/fnichol/chef-rbenv を使えばできそうだったのでこちらを採用する。

使い方は http://fnichol.github.io/chef-rbenv/ を参照。

# Berksfile
site :opscode
cookbook 'ruby_build'
cookbook 'rbenv', github: "fnichol/chef-rbenv"
...
$ berks install --path cookbooks

passenger のレシピ

$ knife cookbook create passenger -o site-cookbooks

で cookbook を作成して以下のとおりレシピを記述する。

# site-cookbooks/passenger/recipes/default.rb

# Ruby 2.0.0 をインストールし、デフォルトに設定する
include_recipe "rbenv::system"
rbenv_ruby "2.0.0-p0"
rbenv_global "2.0.0-p0"

# Passenger のインストール
rbenv_gem "passenger" do
  version "4.0.2"
end

# Apache モジュールのビルドに必要なパッケージのインストール (注: CentOS のみ対応)
include_recipe "build-essential"
package "httpd-devel"
if node['platform_version'].to_f < 6.0
  package 'curl-devel'
else
  package 'libcurl-devel'
  package 'openssl-devel'
  package 'zlib-devel'
end

# Apache モジュールのビルド・インストール
conf_path = "/etc/httpd/conf.d/passenger.conf"
unless File.exists?(conf_path)
  rbenv_script "passenger_module" do
    code <<-CODE
      passenger-install-apache2-module --auto
      echo LoadModule passenger_module `passenger-config --root`/libout/apache2/mod_passenger.so >> #{conf_path}
      echo PassengerRoot `passenger-config --root` >> #{conf_path}
      echo PassengerDefaultRuby `rbenv which ruby` >> #{conf_path}
    CODE
  end
end

Apache のインストールなどは省略。

ちょっと大雑把な記述だけど、ここでは fnichol/chef-rbenv の cookbook を使うことで rbenv_script という resource が使えるようになるのがポイント。
rbenv_script の resource 内では指定した rbenv の環境下 (デフォルトでは global) でスクリプトが実行できる。

execute resource を使用した場合は、せっかく入れた rbenv が使われず、システムの ruby (入っていれば) が使われてハマる。

以上で rbenv + Passenger な環境が簡単に手に入るようになりました。