Sunday, December 9, 2012

Ruby on Rails Apache Deployment

Setting up apache + passanger to serve a RoR app on Ubuntu/Debian (VPS Linode)

I'm a Django/Python developer that was tasked with transitioning a Heroku hosted app to a Linode VPS running stock Ubuntu. This turned to be a two day adventure with a lot of dead ends and a fair share of frustration. I had the app running relatively quickly using the `rails server` built in command but could not get apache + mod_passanger to serve it.

I must say that in my opinion RoR cummunity is doing it's self a disservice by not having solid easy to follow deployment instructions - doing a search on ruby on rails deployment returns outdated noise and official page that is of no help.

Below is a quick summary of what I have learned and how I deployed a Ruby on Rails site with Apache on a Ubuntu system running on a Linode VPS. If this blog does help you out I ask that you do +1 or share it; so now let's begin.

Do not use the Ubuntu/Debian system packages

I mean do NOT, this is the route I went which turned out to be like going down a rabbit's hole. The system packages are outdated and even if you get your app working using the build in `rails server` command chances are apache + mod_passnger will still complain with "no such file to load -- bundler/setup" or "Valid types are [:development, :runtime], not nil"

Use the 'Rails Ready' script and follow it to the letter

I forget how I eventually found this but I am soooo glad that I. This magical script compiles and installs the latest version of RoR and either a Ngnix or Apache passenger module. So run it and it will automatically take care of the entire setup process for you. However in the instructions it states to run `passenger-install-apache-module` but it's actually `passenger-install-apache2-module`.

$ wget --no-check-certificate && bash
- I picked the build from source option
$ passenger-install-apache2-module

Test and Deploy your RoR Application

In summary: clone or copy your Ruby on Rails application, install it's required gems, test it, then setup the apache configuration as advised after running `passenger-install-apache2-module`.

$ git clone<your rails application>.git <your rails application>.ca
$ cd <your rails application>.ca/<your rails application>-form/
$ bundle install
$ rails server
=> Booting WEBrick
=> Rails 3.2.8 application starting in development on
=> Call with -d to detach
=> Ctrl-C to shutdown server
=> Ctrl-C to shutdown server
[2012-12-09 00:40:34] INFO  WEBrick 1.3.1
[2012-12-09 00:40:34] INFO  ruby 1.9.3 (2012-11-10) [i686-linux]
[2012-12-09 00:40:34] INFO  WEBrick::HTTPServer#start: pid=6993 port=3000
^C[2012-12-09 00:40:41] INFO  going to shutdown ...
[2012-12-09 00:40:41] INFO  WEBrick::HTTPServer#start done.

Now that we know the app runs on the built in development server we can setup apache using the information provided when we installed passenger; below is an example of the site I was moving over that is a PHP site with a RoR application that is run under a sub url directory.

# /srw/www/<your rails application>.ca/apache-httpd.conf but linked as /etc/apache2/sites-avaiable/<your rails application>.ca

# RoR as per the `passenger-install-apache2-module`
LoadModule passenger_module /usr/local/lib/ruby/gems/1.9.1/gems/passenger-3.0.18/ext/apache2/
PassengerRoot /usr/local/lib/ruby/gems/1.9.1/gems/passenger-3.0.18
PassengerRuby /usr/local/bin/ruby

<VirtualHost *:80>
 ServerName <your rails application>.ca
 ServerAlias www.<your rails application>.ca development.<your rails application>.ca
 # Answering to server alias `development.domain.tld` allows one to develop the site on a development server utilizing 
 # same apache-conf file that will be used on live server. To make this work one only needs to update domain DNS 
 # records for `development.domain.tld` to point a development server and `www.domain.tld` and `domain.tld` to a
 # production server.

 # Canonical - prefix www to `domain.tld` but not `` - however www prefix is no longer popular
 #RewriteEngine on
 #RewriteCond %{HTTP_HOST} ^w+.w+(:d+|)$
 #RewriteRule !"" http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L,NC]

 # Authenticated access to this project, this is only used during development server to prevent unauthorized access. 
 # As a fallback you should have default auth requirement enabled in the global Apache `/etc/apache/conf.d` settings.
 # We also prevent serving of the password logins file however again this is only used for development client access.
 Redirect /apache-logins.htpasswd /
 <Location />
     AuthType basic
        AuthName "Development Area"
        AuthBasicProvider file
        AuthUserFile /srv/www/<your rails application>.ca/apache-logins.htpasswd
        Require user jeremy

 # DocumentRoot where PHP / HTML Files are served from.
 DocumentRoot /srv/www/<your rails application>.ca/        

 # Ruby and Rails application form module - to find your GEM_HOME run 'gem list -d bundler' 
 <Location /<your rails application>-form/>
  RailsEnv development
  #RailsEnv production
  RailsBaseURI /<your rails application>-form
  PassengerAppRoot /srv/www/<your rails application>.ca/<your rails application>-form/
 # Apache log file location and settings; keeping log within project is not recommended as site can be on many servers
 ErrorLog /var/log/apache2/<your rails application>.ca-errors
 CustomLog /var/log/apache2/<your rails application>.ca combined
 # common redirects
  #Redirect permanent /gapps/<your rails application>.ca/
 #Redirect permanent /analytics/



  1. Daniel, I can't thank you enough, I was truggling like you to make it work on a VPS linode , and your posted saved me days of pains !
    Those stackscript are useless for Rails deployment :(

  2. I am glad Vincent this post helped and thank you for posting :) .