Rack Application Hosting on Ubuntu Lucid using RVM and Passenger

Thanks to Ruby Version Manager (rvm) and Phusion Passenger setting up a server to run rack (and therefore rails or sinatra) applications is very simple.

This post is an update to my earlier post that used Ruby Enterprise Edition directly rather than allowing a choice of ruby versions through rvm. It also assumes that you have a server following the Ubuntu Lucid VPS Base Build post.

With the impending release of Rails 3, this post will cover the installation of Ruby 1.9.2, although the steps are applicable for other rubies.

Updated 2010-08-01: Ruby 1.9.2 rc2 is now available so updated to use correct paths. Application config now sets up an example Hello World rack application.

Updated 2010-08-30: Rails 3, Ruby 1.9.2, Bundler 1.0 released - see rails 3 hosting all in one for updated instructions.


It is a good idea to create a passenger user to install rvm for so that other users do not modify it by accident. You can also deploy your applications using this user. The passenger user needs sudo rights for installing packages using apt-get and running the passenger install script.

sudo adduser passenger
sudo usermod -G passenger,www-data,sudo passenger
su - passenger

You can remove the sudo right after completing the installation using the following:

sudo usermod -G passenger,www-data passenger

Its also a good idea to generate a key pair for ssh too. The public key can be stored in ~passenger/.ssh/authorized_keys and if you use ssh agent forwarding you do not need to store the private key on the server. This is very useful if you use something like capistrano to handle your deployments.


rvm is installed locally for each user rather than a single install for the server. This allows different versions to be used by different users on the server. Unfortunately, only one ruby version can be used with passenger at the moment due to the way passenger hooks into apache.

Install using the preferred script:

bash < <( curl http://rvm.beginrescueend.com/releases/rvm-install-head )

There are some warnings about issues with return in .bashrc. This appears to be a red herring for Ubuntu as mentioned in this post.

Simply edit .bashrc and add the following line at the bottom:

[[ -s $HOME/.rvm/scripts/rvm ]] && source $HOME/.rvm/scripts/rvm

Log out and log in again as passenger to ensure the scripts work as expected. You can test rvm is available correctly by running:

type rvm | head -n1

You should then see the following output:

rvm is a function

You can view the notes about requirements for installing the different rubies by running rvm notes. The list of packages at the time of writing had dependency conflicts which can be circumvented by removing libreadline5-dev.

To install the packages (requires sudo):

sudo apt-get install openssl curl git-core subversion autoconf \
                     build-essential bison zlib1g zlib1g-dev \
                     libssl-dev libxml2-dev libreadline5 libreadline-dev \
                     libreadline6-dev libsqlite3-0 libsqlite3-dev sqlite3

To install the rubies, first 1.8.7 as the notes indicate, followed by 1.9.2:

rvm install 1.8.7
rvm use 1.8.7
rvm install 1.9.2
rvm use --default 1.9.2

You can can now verify the ruby version and install some gems, e.g.:

ruby -v
gem install rails --pre


Passenger is very easy to install. rvm provides some instructions specifically for passenger.

Tell rvm the desired version of ruby to use:

rvm 1.9.2 --passenger

Install the gem and run the installation script. It will tell you what dependencies you are missing and how to install them:

gem install passenger
rvmsudo /home/passenger/.rvm/gems/ruby-1.9.2-rc2/bin/passenger-install-apache2-module

I had to run the following to fix the missing dependencies:

sudo apt-get install apache2-prefork-dev libapr1-dev libaprutil1-dev

Passenger provides some instructions on how to configure apache, although, due to the way rvm works, the value of PassengerRuby should be different. I like to treat passenger as a mod for apache, allowing it to be enabled and disabled as required through the a2enmod and a2dismod commands respectively.

To enable passenger, create /etc/apache2/mods-available/passenger.load with the following contents:

LoadModule passenger_module /home/passenger/.rvm/gems/ruby-1.9.2-rc2/gems/passenger-2.2.15/ext/apache2/mod_passenger.so

and /etc/apache2/mods-available/passenger.conf with the following contents:

PassengerRoot /home/passenger/.rvm/gems/ruby-1.9.2-rc2/gems/passenger-2.2.15
PassengerRuby /home/passenger/.rvm/bin/passenger_ruby

then enable the module and restart apache:

sudo a2enmod passenger
sudo /etc/init.d/apache2 restart

Application config

Each rack/rails application is made available through a virtual host directive in the apache configuration. The recommended way to do this is to create a file named after the site, e.g. example.com in /etc/apache2/sites-available and then enable and disable the site as required using the a2ensite and a2dissite commands respectively.

I find it useful to have a simple Hello World rack application to verify the installation. The application can be run as a subdomain to allow testing and can be enabled and disabled as desired.

I prefer to put all web applications in /var/www and have users be able to create applications if they are a member of www-data:

sudo chown www-data:www-data /var/www
sudo chmod g+w /var/www

Now, create the necessary directory structure for an application:

cd /var/www
mkdir hw.example.com
cd hw.example.com
mkdir public
mkdir tmp

Create /var/www/hw.example.com/config.ru with the following contents:

app = proc do |env|
  [200, { "Content-Type" => "text/html" }, ["hello, world"]]
run app

Create /etc/apache2/sites-available/hw.example.com with the following contents:

<VirtualHost *:80>
    ServerName hw.example.com
    DocumentRoot /var/www/hw.example.com/public
    <Directory /var/www/hw.example.com/public>
        AllowOverride all
        Options -MultiViews

Enable the site, and then view it in your browser:

sudo a2ensite hw.example.com
sudo /etc/init.d/apache2 reload

This can then be disabled and reenabled if needed for debugging any issues at a later date:

sudo a2dissite hw.example.com
sudo /etc/init.d/apache2 reload


blog comments powered by Disqus
Fork me on GitHub