Monday, 11 August 2014

Deploying Rails application on Digital Ocean Ubuntu VPS using Capistrano, Passenger and Nginx

As a part of a New Year's resolution I started learning Ruby on Rails (it was more than 5 years since I last picked up a new programming language!). Ruby and Rails are really fun to learn especially if you start with a toy application. But I found Rails deployment to be a bit more involved than Java deployment. I don't mean using a platform such as Heroku - this really removes all the grunt out of it. I mean deploying Rails while keeping control over the entire stack - i.e. starting from bare metal.

Deploying Rails

There are tons of tutorials on this subject but the clearest I could find is the one written by Chris Oliver. I followed it quite literally. I chose the Ubuntu 12.04 and rvm and I've been using the most recent versions of the other packages as available from the Ubuntu 12.04 repositories:

Phusion Passenger version 4.0.48
*** LOCAL GEMS ***
bigdecimal (1.2.4)
bundler (1.6.2)
bundler-unload (1.0.2)
executable-hooks (1.3.2)
gem-wrappers (1.2.4)
io-console (0.4.2)
json (1.8.1)
minitest (4.7.5)
psych (2.0.5)
rake (10.1.0)
rdoc (4.1.0)
rubygems-bundler (1.4.4)
rvm (
test-unit (

On the dev machine I installed, among others,

capistrano (3.2.1)

Despite following the tutorial to the letter I was getting HTTP 500 after deployment.

Setting the correct path for passenger_ruby

I posted a question on Chris's blog and he kindly suggested that Nginx is the likely culprit. After inspecting


I found the following error message

You've set the `PassengerRuby` (Apache) or `passenger_ruby` (Nginx) option to '/home/deploy/.rvm/rubies/ruby-2.1.2/bin/ruby'. However, because you are using RVM, this is not allowed: the option must point to an RVM wrapper script, not a raw Ruby binary. This is because RVM is implemented through various environment variables, which are set through the wrapper script. 

To find out the correct value for `PassengerRuby`/`passenger_ruby`, please read:

The error message is handily descriptive and checking the above links makes it clear that I had to execute

$ which passenger-config
to find the path to the passenger-config executable. Running it produced:
$ deploy@drop1:~$ /usr/bin/passenger-config --ruby-command

passenger-config was invoked through the following Ruby interpreter:
  Command: /home/deploy/.rvm/gems/ruby-2.1.2/wrappers/ruby

Relaxing the privileges for the parent directories of the app 

Fixing the ruby path did a change - I started getting HTTP404 instead of HTTP500. Checking the log again I found
directory index of {public directory of the app} is forbidden
After a bit of googling it turned out that relaxing the privileges to ALL parent directories is what is needed. I executed
$ sudo chmod g+x,o+x
for each of the parent directories.Than re-starting nginx eliminated the problem. Voila!