4 min read

Deploy Rails 3 with Passenger/Apache on Dreamhost

Now DH has Rails 3.04, and this guide should still be valid

20100917: Rails3 is still broken, I think it could be this Bundler 1.0 bug (fix) and the rack bug. latest working version is Rails3 Beta4 with Bundler 0.9.x , happy hacking!

PLEASE RETWEET THIS!!

After many tutorials and hacks I got my Rails 3 working on Dreamhost too!

The whole setup involve many components but it's a good investiment if you are planning to develop a new Rails app. The final aim is editing locally your app and sending the new features or fixes incrementally via ssh/Git. 

 +

Summary

I'll cover just some nasty parts but here is an overview of my enviroment.

ruby 1.8.7, rubygems 1.3.7, bundler, rails 3, sqlite, capistrano, git and gedit :P On the shared hosting the environments is slightly different because the web server you must to use is Apache/Passenger, the suggested database is mysql and the text editor available is vim.

Step 1: You need a working Rails 3 environment on Dreamhost

Something like my past instructions but with gems installed in $HOME/.gems
You should have something like:

   _)      |   _) |           
    | |  |  _ \ | |  -_)  -_) 
    |\_,_|_.__/_|_|\___|\___| 
 __/                          
 Welcome to jubilee.dreamhost.com

Any malicious and/or unauthorized activity is strictly forbidden.
All activity may be logged by DreamHost Web Hosting.

Last login: Sat Jun 19 14:14:34 2010 from XX.X1.217.65
[jubilee]$ rails -v
Rails 3.0.0.beta4

The next command will be rails new myapp and just to be sure test it via webrick with rails s

The environment info available on http://mypublicdomain.com:3000/rails/info/properties should look like:

Ruby version	1.8.7 (x86_64-linux)
RubyGems version	1.3.7
Rack version	1.1
Rails version	3.0.0.beta4
Active Record version	3.0.0.beta4
Action Pack version	3.0.0.beta4
Active Resource version	3.0.0.beta4
Action Mailer version	3.0.0.beta4
Active Support version	3.0.0.beta4
Application root	/home/<dh_user>/apps/myapp/current
Environment	development
Database adapter	sqlite3
Database schema version	0

Don't abuse of this feature, it's for testing only. Dreamhost doesn't want you open public ports by yourself.

Step 2: Set up a git repository the right way and Capistrano

This is the hardest part because it is a bit tangled and it depends how you are going to organize your projects and how complex your setup need to be.
This strategy inspired by Github is very clean but I had to edit some parts to got it working.

A couple of assumptions:

  1. git working copy /home/<dh_user>/apps/myapp/current
  2. git repository /home/<dh_user>/reps/myapp

So go to the git repository path and initialize git in this way:

git init --bare

Then go to git working copy and clone the git repository(empty), the add inside your rails app files

and install Capistrano

gem install capistrano

Then run capify . and apply the strategy suggested above with some customizations:

### config/deploy/settings.rb
#############################################################
#	Servers
#############################################################

set :user, 'my-dreamhost-user' #dreamhost-user

#############################################################

Application

#############################################################

set :application, 'myapp' # use your folder app name
set :deploy_to, "/home/#{user}/apps/#{application}" # the live app will be in the "current" subdir
set :shared_path, "/home/#{user}/.gems"

use trunk to deploy to production

set :branch, "master"
set :rails_env, "production"

production

set :domain, 'mydomain.com' # your http://publicdomain.com
role :app, domain
role :web, domain
role :db, domain, :primary => true

#############################################################

Git

#############################################################

set :scm, :git
set :repository, "/home/#{user}/#{application}"

#############################################################

Includes

#############################################################

#############################################################

Settings

#############################################################

default_run_options[:pty] = true
set :use_sudo, false

before "deploy", "deploy:check_revision"

set :ssh_options, {:forward_agent => true}

#############################################################

Post Deploy Hooks

#############################################################

after "deploy:update_code", "deploy:write_revision"
before "deploy:gems", "deploy:symlink"

after "deploy:update_code", "deploy:gems" # You have to run deploy:gems manually after Gemfile changes

after "deploy:update_code", "deploy:precache_assets" #not working for rails3 yet

and

### config/deploy/callbacks.rb
namespace :deploy do

desc "expand the gems"
task :gems, :roles => :web, :except => { :no_release => true } do
run "cd #{current_path}; #{shared_path}/bin/bundle unlock"
run "cd #{current_path}; nice -19 #{shared_path}/bin/bundle install vendor/" # nice -19 is very important otherwise DH will kill the process!
run "cd #{current_path}; #{shared_path}/bin/bundle lock"
end

end

Then apply the changes to the repo

git add .
git commit -am "my first and last commit from Dreamhost"

Now if everything went OK, you should be able to control your remote setup directly from the local development machine!

Come back to local development machine

remote git repo -> local git repo

git clone ssh://dh-user@mypublicdomain.com/home/dh-user/reps/myapp
cd myapp
git config receive.denycurrentbranch

Step 3: Everyday workflow

Edit your code, commit your changes (locally), synchronize the code and restart the (remote) server.

local git -> commit locally -> push new changes on remote git repo -> update, synchronize and restart the live app

In few words git commit -am "my new cool feature" && git push && cap deploy && cap deploy:gems # last command just if you updated the Gemfile

That's all, enjoy and have profit!