更新履歴
- 2020-05-08
- もう5年近く前に書いた記録だが、未だにこの手法は現役で有効
- sudoersの部分を加筆修正、secure_pathを使うやり方を追加した
概要
いっつも「あれどうやんだっけ」と若干悩むので、そのままコピペ出来るリファレンスとして作成。と言いつつもDebian/Ubuntuは若干不足。
Installation steps
Install dependent packages
CentOS 7
# 全てrootユーザーで実行
sudo su -
yum -y group install development
# ruby-buildに必要なパッケージをインストールする
# OS毎に必要なパッケージの一覧がruby-buildのWikiに記載されているので、最新版の一覧はWiki参照
# https://github.com/sstephenson/ruby-build/wiki
yum install -y gcc openssl-devel libyaml-devel libffi-devel readline-devel zlib-devel gdbm-devel ncurses-devel
Debian 8 / Ubuntu 14.04
# 全てrootユーザーで実行
sudo su -
apt-get install build-essential -y
apt-get install git -y
# ruby-buildに必要なパッケージをインストールする
# OS毎に必要なパッケージの一覧がruby-buildのWikiに記載されているので、最新版の一覧はWiki参照
# https://github.com/sstephenson/ruby-build/wiki
apt-get install autoconf bison build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev libgdbm3 libgdbm-dev
Install rbenv and ruby
# 本体
git clone https://github.com/sstephenson/rbenv.git /usr/local/opt/rbenv
# プラグイン
# - ruby-build (必須)
# - rbenv-gemsets
git clone https://github.com/sstephenson/ruby-build.git /usr/local/opt/rbenv/plugins/ruby-build
git clone https://github.com/jamis/rbenv-gemset.git /usr/local/opt/rbenv/plugins/rbenv-gemset
cat << 'EOF' > /etc/profile.d/rbenv.sh
export RBENV_ROOT="/usr/local/opt/rbenv"
export PATH="$RBENV_ROOT/bin:$PATH"
eval "$(rbenv init -)"
EOF
source /etc/profile.d/rbenv.sh
rbenv install -l
# list of versions available
export TARGET_RUBY=2.2.4
rbenv install $TARGET_RUBY
# check
RBENV_VERSION=$TARGET_RUBY ruby -v
# bundlerだけはruby version globalなgemとしてインストールする
RBENV_VERSION=$TARGET_RUBY gem install bundler
Configure sudo
2パターンある。
- secure_pathを無効化する
- secure_pathにrbenv関連のパスを追加する
以下、CentOS 7の例。
CentOS 7
cat << 'EOF' > /etc/sudoers.d/rbenv
Defaults !secure_path
Defaults env_keep += "PATH"
Defaults env_keep += "RBENV_ROOT RBENV_VERSION RBENV_GEMSETS"
EOF
cat << 'EOF' > /etc/sudoers.d/rbenv
Defaults env_keep += "RBENV_ROOT RBENV_VERSION RBENV_GEMSETS"
EOF
visudo
# secure_pathに以下を追加する
# - /usr/local/opt/rbenv/shims
# - /usr/local/opt/rbenv/bin
# デフォルト
Defaults secure_path = /sbin:/bin:/usr/sbin:/usr/bin
# 変更後
Defaults secure_path = /usr/local/opt/rbenv/shims:/usr/local/opt/rbenv/bin:/sbin:/bin:/usr/sbin:/usr/bin
rbenvグループでrbenv関連のコマンドをNOPASSWDで実行できるようにする。
グループは既にあるグループを使っても良いし、ユーザー単位で指定出来るならグループは作らなくても良い。以下は rbenv
グループを別途作成する例。
cat << 'EOF' > /etc/sudoers.d/rbenv_nopasswd
Cmnd_Alias RBENV = /usr/local/opt/rbenv/bin/
%rbenv ALL = (ALL) NOPASSWD: RBENV
EOF
visudo
# エラーが出ないかチェック
# これを実行することにより /etc/sudoers.d/* のファイルのパーミッションも是正してくれる
# グループ作成
# -rを付けてシステムグループにしておく
groupadd -r rbenv
# 作成したグループにユーザーを追加する
#gpasswd -a hoge rbenv
Install passenger
rbenv gemset create $TARGET_RUBY passenger
RBENV_VERSION=$TARGET_RUBY RBENV_GEMSETS=passenger gem install passenger
rbenv rehash
RBENV_VERSION=$TARGET_RUBY RBENV_GEMSETS=passenger passenger-install-apache2-module
# パッケージのチェックで不足が表示されたら追加でインストールして再度実行
passenger-install-apache2-module
でコンパイルが成功すると、最後にApacheのconfig記載例が表示されるので、コピーしておく。このパスはrubyやpassengerのバージョン、passengerをインストールしたgemsetの名前などによって変わるので注意。またconfigの記載場所はディストリによってポリシーが違い変わってくるので、よしなに。
以下、CentOS 7の例。
CentOS 7
vim /etc/httpd/conf.modules.d/02-passenger.conf
LoadModule passenger_module /usr/local/opt/rbenv/versions/2.2.4/gemsets/passenger/gems/passenger-5.0.21/buildout/apache2/mod_passenger.so
vim /etc/httpd/conf.d/passenger.conf
<IfModule mod_passenger.c>
PassengerRoot /usr/local/opt/rbenv/versions/2.2.4/gemsets/passenger/gems/passenger-5.0.21
PassengerDefaultRuby /usr/local/opt/rbenv/shims/ruby
PassengerInstanceRegistryDir /var/lib/passenger
</IfModule>
PassengerDefaultRuby
は表示されたものではなく、rbenvのshimを指定しておく。こうしておくと、passengerを使うアプリのディレクトリにある.ruby-version
のrubyでそのアプリは動かしてくれるようになる。1つのApache+Passengerで、複数のアプリを、アプリごとにrubyのバージョンを分けて実行できる。
以下、続き。
# PassengerInstanceRegistryDirで指定したディレクトリを作成 (詳細は下記参照)
# 予め作っておかないとhttpdの起動に失敗する
mkdir /var/lib/passenger
systemctl restart httpd
CentOS 7の場合、PassengerInstanceRegistryDir
を指定しておかないとpassenger-config restart-app
等ができなくなる。
上記リンク先はPassenger 4の場合についての記載だが、5でも同じ。ただ指定するパラメータが4の時はPassengerTempDir
だったのが、5ではPassengerInstanceRegistryDir
に変わった。passenger-config
等を実行するときは環境変数PASSENGER_INSTANCE_REGISTRY_DIR
を指定して実行する。
PASSENGER_INSTANCE_REGISTRY_DIR=/var/lib/passenger RBENV_VERSION=2.2.4 RBENV_GEMSETS=passenger passenger-config restart-app /
sudo
経由で呼び出すときは、この環境変数が引き継がれるようにenv_keepに項目を足すか、sudo -E
で実行する必要がある。
補足
cronから使う
rbenvで作ったアプリをcronから呼び出すときは、crontabの中で環境変数を設定してあげるか、呼び出すコマンドの頭の方に環境変数を設定するワンライナーを追加する。
RBENV_ROOT=/usr/local/opt/rbenv
PATH=/usr/local/opt/rbenv/shims:/usr/local/opt/rbenv/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
0 3 * * * cd /var/www/rails/hoge/current && bundle exec rake fuga
その他もろもろ
- rbenv-binstubsはsystem-wide installでは使えない。残念。なのでsystem-wideなrbenvの時はいちいちbundle execする必要あり。
- そもそもsystem wideインストールするのってどうなのよ、という意見はご尤も。ただ内部向けのアプリとか小さいものなら、結構一台のサーバーに詰め込んでデプロイするなんて状況は普通にありそうなので、そういう時はなんだかんだでrbenv入ってると楽だよね、という話。