Introduction

I could not find an updated documentation on how to setup properly a rails application on Dreamhost, so I thought I'd share the information I gathered.. First off, thanks to the Phusion team, with Passenger (a.k.a. mod_rails), it's now very convenient, easy, and cheap to run a rails application on Dreamhost.

Also, special thanks to Todd Huss for discovering the multi dreamhost user hack. Basically, you need to run each of your rails application on Dreamhost under a different shell user. Their process monitor, will start killing your processes when the total memory per user exceeds 200 MB of virtual memory (VSZ).

So here's the guide, even perfect newbees and skript-kiddies should be able to follow :

The complete step by step

INFO : Let Capistrano create the directory structure on the server BEFORE you set the public dir of your application in the edit domain section of the Control Panel. This will avoid you conflicts when Capistrano attemps to create the symlinks.

  1. First, configure your new rails application using Dreamhost Control Panel :

    1. Create a new repository for your application (screenshot)

    2. Create a new shell / SSH user (read why here) with the same name as your application (screenshot)

    3. Create a new database (screenshot)

  2. Add your application to your repository
    1. Create your rails skeleton (if it's done yet), on your local machine (assuming you use *nix, but should be similar on Windows)
      
      
      $ rails myrailsapp --freeze
    2. Add your application to the repository
      1
      2
      3
      4
      5
      
      $ cd myrailsapp
      $ svn mkdir http://svn.myrailsappdomain/myrails/trunk
      $ svn checkout http://svn.myrailsappdomain/myrails/trunk ./
      $ svn add  *
      $ svn commit
    3. Exclude database configuration, temporary files, and any user upload directory from the source control :
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      
      $ svn copy config/database.yml config/database.yml.example
      $ svn remove config/database.yml -f
      $ svn propset svn:ignore "database.yml" config/
      $ svn remove tmp/*
      $ svn propset svn:ignore "*" tmp/
      # If you need to share unversionned user-uploaded files, between deploys :
      $ mkdir public/uploads
      $ svn add public/uploads
      $ svn propset svn:ignore "*" public/uploads/
      $ svn remove log/*
      $ svn propset svn:ignore "*" log/
      $ svn remove db/*.sqlite3
      $ svn propset svn:ignore "*.sqlite3" db/
      $ svn commit
  3. Next, create the Capistrano recipe :
    1. Create recipe skeleton :
      1
      2
      3
      4
      5
      
      $ cd /path/to/your/myrailsapp
      $ capify .
      [add] writing `./Capfile'
      [add] writing `./config/deploy.rb'
      [done] capified!
    2. Replace the content of config/deploy.rb with the following :
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      
      #############################################################
      ## General
      #############################################################
      set :application, "myrailsapp"
      
      
      #############################################################
      ## Servers 
      #############################################################
      set :use_sudo, false    # Dreamhost does not support sudo
      set :user, application  # Dreamhost SSH User
      set :domain, "myrailsapp.domain.com"
      
      server domain, :app, :web
      role :db, domain, :primary => true
      
      
      #############################################################
      ## Subversion
      #############################################################
      set :scm, :subversion
      set :scm_user, application   # Sets 'my_svn_user' instead, if you are using different name than your app.
      set :scm_auth_cache, true  # Prompts for password once
      set :scm_password, Proc.new { Capistrano::CLI.password_prompt("SCM password for #{scm_user}:") }
      set :repository,  "http://svn.myrailsappdomain/#{application}/trunk"
      set :deploy_to, "/home/#{user}/#{domain}"
      # keeps a local checkout of the repository on the server to get faster deployments
      set :deploy_via, :remote_cache
      
      
      #############################################################
      ## Tasks
      #############################################################
      
      namespace :deploy do
        desc "Restart Application (using tmp/restart.txt)"
        task :restart_passenger do
          run "touch #{current_path}/tmp/restart.txt"
        end
      
        desc "Restarts your application."
        task :restart do
          restart_passenger
        end
      
        desc "Link shared files"
        #task :before_symlink do
        before :symlink do
          run "rm -drf #{release_path}/public/uploads"
          run "ln -s #{shared_path}/uploads #{release_path}/public/uploads"
          run "rm -f #{release_path}/config/database.yml"
          run "ln -s #{shared_path}/database.yml #{release_path}/config/database.yml"
        end
      end
  4. Then, prepare the directory structure on the server :
    1. Create the Capistrano structure (releases/, shared/), by typing this on your local machine :
      
      
      $ cap deploy:setup
    2. Login to your server to manually create your shared directories and files (if any)
      1
      2
      
      $ ssh myrailsapp.domain.com
      [tootsie]$ cd myrailsapp/shared
    3. Configure your database on the server (you don't want this file in your repository) :
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      
      # config/database.yml
      
      development:
        adapter: sqlite3
        database: db/development.sqlite3
        timeout: 5000
      
      test:
        adapter: sqlite3
        database: db/test.sqlite3
        timeout: 5000
      
      production:
        adapter: mysql
        encoding: utf8
        database: myrailsapp
        username: myrailsapp
        password: [your_db_password]
        host: mysql.[myrailsapp.domain].com
        timeout: 5000
    4. Create your upload directory (OPTIONAL) :
      
      
      [tootsie]$ mkdir uploads
  5. Deploy your application. Note : it will only prompt for your SVN password at the first deploy.
    
    
    $ cap deploy
  6. And finally the most important, configure your domain like this :

[UPDATE 2008/07/01]

If you need to install custom gems on your account, you can find more info here, here and here.

References

  1. http://labs.peritor.com/webistrano/wiki/ConfigurationParameter
  2. http://groups.google.ca/group/capistrano/browse_thread/thread/6ef7c7c212547eab (for scm_password)
  3. http://groups.google.com/group/capistrano/browse_thread/thread/ae7b16a16abf4e5d (for task hookups with namespaces)
  4. http://groups.google.com/group/capistrano/web/deploying-on-dreamhost
  5. http://gabrito.com/post/ruby-on-rails-dreamhost-plugin
  6. http://www.railsforum.com/viewtopic.php?id=8118
  7. Dreamhost Wiki : Capistrano
  8. Dreamhost Wiki : Ruby_on_Rails
  9. Capistrano Manual

7 Responses to “Capistrano 2 Recipe for Dreamhost Shared Hosting and mod_rails”

  1. David Says:
    Hi David, I'm really glad that you posted this procedure, and I've been trying to execute it. When attempting to deploy, I receive the following message: * executing 'deploy' * executing 'deploy:update' ** transaction: start * executing 'deploy:update_code' Server refused our key Could you help to try to identify why this error occurred? A person checking the auth.log said that he didn't see any failed authentication keys, and I've been able to connect through putty with keys. Thank you! David
  2. David On Laptop Says:
    Hi David, You have to tell Capistrano to encrypt the communication with your private RSA key. Set the ssh_options[:keys] to point to your private key on your local machine. Add this in the recipe file: ssh_options[:verbose] = :debug ssh_options[:keys] = 'path/to/my/ssh/key/id.rsa' Comment the :verbose line once your setup is working. Note, that you first need, to add your public key on your Dreamhost account in $HOME/.ssh/authorized_keys. Which you probably have already done, if Putty is working for you. if it still is not working, try adding these 2 lines: ssh_options[:port] = 22 ssh_options[:user] = 'ssh_user' Hope that helps!
  3. Deariehita Says:
    nice work, guy
  4. Tak Says:
    I am following your tutorial and got this error trying to add my app to a repository doing - svn checkout. 'svn not recognized as internal or external command'. I am on Windows XP and rails 2.2.2. Do I have to install gem for svn command to work?
  5. David On Laptop Says:
    @Tak : Yes, you need to install subversion (SVN) on your machine. You can download an excellent GUI (visual interface) for Windows from Tigris : lhttp://tortoisesvn.tigris.org/ . AND/OR you can simply use the command-line version (to use in the DOS prompt) : http://subversion.tigris.org/
  6. richy Says:
    hi! tnx for this post! i have a small problem with it: when i created i subversion project in the dh panel (svnproj.dreamhosters.com) it wont create additional folder structure like svnproj.dreamhosters.com/trunk etc... i think the trunk folder is needed for svn to work - so: should i add folders manually?
  7. David On Laptop Says:
    @Richy : You are right the folders trunk, branches, tags are NOT created by default, i forgot about that. These folders are a simply regular folders following a naming convention; you have to create them manually. They are NOT required by Subversion to work, but it is a good practise to use a trunk subfolder, in case later on you start branching (svn book, chapter 6 i think). I updated the article, all you need to do is "svn mkdir http://svn.myrailsappdomain/myrails/trunk" before the initial checkout.

Leave a Reply

If you can read this, you don't use a typical webbrowser that plays nice with CSS.
Please do not fill in anything here!