I've taken an Amazon Linux AMI (based on CentOS) and installed RVM (1.10.3) to it in multi-user fashion (see {1} below). I used that to install ruby 1.9.3-p125, rubygems 1.8.17, and bundler 1.1 as the baseline requirements for most things I'm going to be using the instances for.

I've captured that instance to an AMI, and am now launching it via CloudFormation, with some CloudFormation::Init commands. One of them is to use s3cmd to pull down a private gem from S3, and the next one, the one that fails, is to install that gem. It fails with an error message

2012-03-15 16:53:20,201 [ERROR] Command 20_install_gems (/usr/local/rvm/rubies/ruby-1.9.3-p125/bin/gem install ./*.gem) failed
2012-03-15 16:53:20,202 [DEBUG] Command 20_install_gems output: /usr/local/rvm/rubies/ruby-1.9.3-p125/bin/gem:12:in `require': no such file to load -- rubygems (LoadError)
    from /usr/local/rvm/rubies/ruby-1.9.3-p125/bin/gem:12

Now, that happens during the cfn-init execution - I assume, but haven't checked yet, that cfn-init is being run with an environment different from that of ec2-user (there are no other users on the instance).

If I run gem install mygem.gem in an interactive session then that works fine.

So, my question really, is what should I do to make this work for cfn-init? Have I correctly set up rvm as multi-user?

I've confirmed that cfn-init is being run as the root user, with his restricted environment. How should I source the /etc/profile.d/rvm.sh into root's sessions?

{1} My semi-automated rvm installation steps (run in interactive session as ec2-user):

sudo bash -s stable < <(curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer )
sudo gpasswd -a ec2-user rvm
# iconv-devel is baked into centos' glibc
sudo yum install -y autoconf automake bison bzip2 gcc-c++ git libffi-devel libtool libxml2-devel libxslt-devel libyaml-devel make openssl-devel patch readline readline-devel zlib zlib-devel
source /etc/profile.d/rvm.sh
rvm list known

# in a new session:
rvm install ruby-1.9.3-p125
rvm use 1.9.3 --default
gem update --system
# gems required by public_web-awareness
gem install aws-sdk bundler cocaine sinatra
echo -e "gem: --no-ri --no-rdoc\n" > /home/ec2-user/.gemrc

# delete unnecessary documentation files
rm -rf `gem env gemdir`/doc

sudo -s
sudo echo -e "gem: --no-ri --no-rdoc\n" > /etc/skel/.gemrc
sudo echo -e "gem: --no-ri --no-rdoc\n" > /etc/gemrc
# ctrl + d out of the sudo session

Some environment information:

[ec2-user@ip ~]$ echo $PATH
[ec2-user@ip ~]$ echo $GEM_HOME
[ec2-user@ip ~]$ echo $GEM_PATH
[ec2-user@ip ~]$ echo $BUNDLE_PATH

[ec2-user@ip ~]$ gem list

*** LOCAL GEMS ***

aws-sdk (1.3.6)
bundler (1.1.0)
cocaine (0.2.1)
httparty (0.8.1)
json (1.6.5)
multi_json (1.1.0)
multi_xml (0.4.1)
nokogiri (1.5.1, 1.5.0)
rack (1.4.1)
rack-protection (1.2.0)
rake (0.9.2)
sinatra (1.3.2)
tilt (1.3.3)
uuidtools (2.1.2)
yamler (0.1.0)

So the answer lies in that during CloudFormation::Init, /opt/aws/bin/cfn-init is run by the root user, within a stripped-down environment, and uses /bin/sh as its shell instead of /bin/bash. Being mostly a Windows guy for the last ten or so years I initially didn't realise (remember!) that.

I tried various things, but the thing that worked was adapted from ScoutApp's blog: change the CloudFormation::Init metadata commands to prefix them with bash -l -c ' and suffix ' (so for example gem install foo became bash -l -c 'gem install foo'.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.