UPDATE: I’ve moved from BlueHost, as their quality sucks and techsupport is unable to offer any solution for timeouts/500/503 HTTP errors.

These days developers are being offered with lots of options to host their apps. You can choose everything – from Amazon, to Google, to Heroku.

But sometimes you want to run your app with a set of different programming languages, frameworks, and databases. This is something that a typical PaaS provider can’t offer, so you need a general-purpose hosting.

Here is a brief tutorial on how to setup Rails web application on BlueHost, using git SCM and Capistrano deployment tool.

BlueHost Setup

Important Note: BlueHost charges you for the whole 1 or 3 years – depending on the plan you choose – immediately. So if you want per-month subscription, you have to contact them directly. In this case they charge $30 “setup fee”.

After you’ve successfully purchased your brand new BlueHost account, you have to make some additional tweaks.

BlueHost has “Ruby on Rails” button in cPanel, but you can safely leave it alone – it doesn’t do anything useful:

Bluehost Rails

What we need to tweak, though, is our ~/.bashrc file. Add these lines to the bottom of this file:

export HPATH=$HOME
export GEM_HOME=$HPATH/ruby/gems
export GEM_PATH=$GEM_HOME:/usr/lib64/ruby/gems/1.9.3
export GEM_CACHE=$GEM_HOME/cache
export PATH=$PATH:$HPATH/ruby/gems/bin
export PATH=$PATH:$HPATH/ruby/gems

In order to conveniently deploy our projects to BlueHost over SSH, we would need to add our public key to the list of allowed keys.

To do so, we have to edit ~/.ssh/authorized_keys file on BlueHost, adding there contents of our local ssh/is_rsa.pub file.

Now we can login to BlueHost from our local host without a password prompt. More on SSH keys generation and passwordless login is here.

git Setup

In case you never worked with git before, here is a brief crash course:

  1. Setup an empty git repository in your Rails application under a root folder: $ git init . 

  2. Add all project files into a repository: $ git add . 

  3. Commit files: git commit -m "Initial commit" 

  4. That’s pretty much it – your git repository is ready. If you want more details, check this great book.

Capistrano + Rails Setup

Capistrano is nothing more than another Rails gem. So we just add it to our Gemfile:

gem 'capistrano'

And install it:

$ bundle install

Now we have to initialize Capistrano configuration:

$ capify .

This command creates several files, which Capistrano needs to work properly. One which is of particular interest for us is config/deploy.rb. Default settings make no sense for our setup, so we re-create this file from scratch:

# Automatic "bundle install" after deploy
require 'bundler/capistrano'

# Application name
set :application, "application-name"

# BlueHost SSH user
set :user, "bluehost_user"

# App Domain
set :domain, "application-name.com"

# We don't need sudo on BlueHost
set :use_sudo, false

# git is our SCM
set :scm, :git

# master is our default git branch
set :branch, "master"

# Use local git repository
set :repository, "."

# Checkout, compress and send a local copy
set :deploy_via, :copy
set :deploy_to, "/home/#{user}/rails_apps/#{application}"

# We have all components of the app on the same server
server domain, :app, :web, :db, :primary => true

namespace :deploy do
  task :start do ; end
  task :stop do ; end

  # Touch tmp/restart.txt to tell Phusion Passenger about new version
  task :restart, :roles => :app, :except => { :no_release => true } do
    run "touch #{File.join(current_path, 'tmp', 'restart.txt')}"
  end
end

# Clean-up old releases
after "deploy:restart", "deploy:cleanup"

The final touch is to tune public/.htaccess file to let BlueHost mod_rails know how to treat our web app. Don’t forget to change home_dir and user_dir to the real folders:

Options -MultiViews
PassengerResolveSymlinksInDocumentRoot on
RailsEnv production
RackBaseURI /
SetEnv GEM_HOME /home_dir/user_dir/ruby/gems

Deploy!

Now we have everything in place. Let’s go:

$ git add .
$ git commit -m 'Add Capistrano'
$ cap deploy:setup
$ cap deploy
$ cap deploy:migrate

That’s it! Don’t forget to commit your changes and then use cap deploy or cap deploy:migrate (for DB migration) command every time you need to push a new version to your BlueHost hosting.