Configuring a WHM (cPanel) server to support RVM and Passenger

The well-known hosting control panel WHM (aka cPanel) support for ruby seems to have been mostly dropped and basically nothing ruby-related is currently manageable through the control panel.

Inspired by this post by Dave James Miller I went on to test the installation of the ruby stack on a cPanel server. In the end, I got a nice setup with a Spree store using Passenger with RVM.

Following I’ll present the steps that ended up working for me.

What was used

  • CentOS 6.4
  • cPanel 11.36

What we’re going to install

Ruby Version Manager makes it easy to install multiple versions of Ruby into your home directory. We’ll use that to install Ruby 1.9.3 separately from the cPanel-provided version 1.8.7.

Phusion Passenger (a.k.a. mod_rails) is an Apache module that lets you run multiple Rails apps under a single Apache instance.

Install RVM, Ruby & Phusion Passenger

1. Create a new user

For this I decided to go out of the cPanel way of doing things and just add a user the “old fashioned way”:

useradd ruby

This way, we avoid having to attribute a subdomain and even allowing it to login to the machine using a password. Given that the server does not allow password-less (apart from private keys et al) ssh attempts I can’t think of an easier way to setup a user for this purpose. Simply su to the user and setup your authorized key (you can probably just run /bash/bin –login).

2. Install RVM with the user created (ruby)

Login as the user ruby and install RVM:

bash < <(curl -s

You should probably re-login now in order to activate RVM.

After this, you’ll need to make sure you have everything the server needs for RVM. A useful step is to make RVM autolibs read-only (so it doesn’t try to run sudo commands):

rvm autolibs read-only

Now, you can run

rvm requirements

In my case, one of the missing requirements was libyaml-devel. To install it, you probably have to add the RHEL EPEL Repos for CentOS. Back as root, run:

rpm -Uvh remi-release-6*.rpm epel-release-6*.rpm

Once installed you should see some additional repo definitions under the /etc/yum.repos.d directory.

$ ls -1 /etc/yum.repos.d/epel* /etc/yum.repos.d/remi.repo

You should no be able to install all the requirements mentioned by rvm.

3. Install Ruby

Now, to install ruby, it’s the usual RVM command:

rvm install 1.9.3
rvm --default 1.9.3

You could just as well go for version 2.0.0 of ruby.

4. Install Bundler

You’ll also need Bundler installed, so let’s install it now:

gem install bundler

5. Install Phusion Passenger

gem install passenger

Passenger will give you some code to add to your Apache config – make a note of it.

Now log in as root again and add that code to /usr/local/apache/conf/includes/pre_main_global.conf. e.g. My code was:

LoadModule passenger_module /home/ruby/.rvm/gems/ruby-1.9.3-p429/gems/passenger-4.0.4/libout/apache2/
PassengerRoot /home/ruby/.rvm/gems/ruby-1.9.3-p429/gems/passenger-4.0.4
PassengerDefaultRuby /home/ruby/.rvm/wrappers/ruby-1.9.3-p429/ruby
PassengerResolveSymlinksInDocumentRoot on

Please refer to Passenger Documentation about the PassengerResolveSymlinksInDocumentRoot option that I added. Basically it allows me to use the default ~/public_html as a symlink to the real path in my Rails apps.

Now rebuild Apache config:

cp /usr/local/apache/conf/httpd.conf /usr/local/apache/conf/httpd.conf.bak-modrails
/usr/local/cpanel/bin/apache_conf_distiller --update
/etc/init.d/httpd restart

6. Share RVM across accounts

Since all ruby apps are controlled by myself I decided to go for a shared installation of RVM. To allow other users to have full access to the rvm installation, just run:

chmod -R g+w ~/.rvm/
find ~/.rvm/ -type d -exec chmod g+s {} \;

This will give group (ruby) writing permissions on files and folders inside RVM. Now, just need to add the user to the ruby group to give them access:

usermod -a -G ruby ruby_user

Last step to share rvm, which was a bit tricky but I finally got it working by appending the following to each ruby_user’s .bashrc (or .bash_profile):

PATH=$PATH:/home/ruby/.rvm/bin # Add RVM to PATH for scripting

export rvm_prefix='/home/ruby/'
export rvm_path='/home/ruby/.rvm'
source /home/ruby/.rvm/scripts/rvm

7. Use gemsets in Passenger

In order to use gemsets I followed RVM's Passenger integration guide, and used the .ruby-version config file in the project root:

echo [email protected] > .ruby-version

Then in the rails project, add a new file config/setup_load_paths.rb with:

if ENV['MY_RUBY_HOME'] && ENV['MY_RUBY_HOME'].include?('rvm')
gems_path = ENV['MY_RUBY_HOME'].split(/@/)[0].sub(/rubies/,'gems')
ENV['GEM_PATH'] = "#{gems_path}:#{gems_path}@global"
require 'rvm'
RVM.use_from_path! File.dirname(File.dirname(__FILE__))
rescue LoadError
raise "RVM gem is currently unavailable."

# If you're not using Bundler at all, remove lines bellow
ENV['BUNDLE_GEMFILE'] = File.expand_path('../Gemfile', File.dirname(__FILE__))
require 'bundler/setup'

I’m yet to test using different versions of ruby but this works like a charm for gemsets without the need to install them to the vendor/bundle path.

Technorati Tags: ,,,