Posted at

ChefでUbuntuにnvmを入れてnode.jsのバージョンを管理する(Ubuntu12.04)

More than 3 years have passed since last update.

Chefでnode.jsを入れる話と、その際に苦労した話。


Ubuntuにnode.jsを入れる方法それぞれ


1. apt-getで標準リポジトリから入れる


  • 標準リポジトリで入るnodeのバージョン古すぎる

  • コマンド名がnodejsになるのでnpmの実行でこける

  • 回避方法はあるが面倒そう

  • ので、不採用


2. ppa(personal package archives)で入れる


  • バージョンの切り替えが大変そうなので不採用


3. nvmで入れる


  • 新しいバージョンも入るしバージョン切り替えも楽そうなので採用


Chefでnvmからnode.jsを入れる

最終的には以下のようなコードで動いた。


recipes/default.rb


# 標準パッケージのnodejsが入っていた場合はアンインストール
apt_repository "nodejs" do
action :remove
only_if { ::File.exists?("/usr/bin/nodejs") }
end

# nvmインストール
git "/usr/local/nvm" do
repository "git://github.com/creationix/nvm.git"
reference "master"
action :sync
end

template "/etc/profile.d/nvm.sh" do
source "nvm.sh.erb"
mode 00644
end

# nvm listした際のエラー回避
directory '/usr/local/nvm/alias' do
action :create
end

directory '/usr/local/nvm' do
owner 'root'
group 'root'
mode '0755'
action :create
end

bash "install nodejs" do
code <<-EOC
source /usr/local/nvm/nvm.sh
nvm install
#{node["versions"]["nodejs"]}
EOC
creates "/usr/local/nvm/#{node["versions"]["nodejs"]}"
end

# npm install
%w{grunt-cli redis-commander cmdparser browserify-middleware readline-browserify}.each do |p|
bash "npm install" do
code <<-EOC
source /usr/local/nvm/nvm.sh
npm install -g grunt-cli
EOC
not_if "npm -g ls 2> /dev/null | grep '^[├└]─[─┬] #{p}@'"
end
end



ハマったところ

Chefではリソース毎に設定される環境変数は閉じている(正確にいえば、リソース内で環境変数を設定する場合はchefのコードとして明示的に記述する必要がある)。

上記を知らなかったために苦労した。

例えば

template "/etc/profile.d/nvm.sh" do

source "nvm.sh.erb"
mode 00644
end

上記でnvmをセットアップするシェルを読み込んでいるが、

bash "install nodejs" do

code <<-EOC
source /usr/local/nvm/nvm.sh
nvm install
#{node["versions"]["nodejs"]}
EOC
creates "/usr/local/nvm/#{node["versions"]["nodejs"]}"
end

ここでは上記のシェルで設定された環境変数が受け継がれない。

(だからbashリソース内でnvm.shを再び読み込ませている)

上記のコードで

bash "install nodejs" do

code <<-EOC
nvm install
#{node["versions"]["nodejs"]}
EOC
creates "/usr/local/nvm/#{node["versions"]["nodejs"]}"
end

と書いて実行すると、npm command not foundとなってしまう。


おしまい

たぶん基本的なことなんだろうけど、知らなかったためにつらい思いをした。