Capistrano
From DreamHost
Capistrano automates the deployment, migration, upgrades and rollbacks of your Rails applications.
Contents |
Getting Started
| The instructions provided in this article or section are considered advanced. You are expected to be knowledgeable in the UNIX shell. |
This assumes you are deploying your rails application to your DreamHost server for the first time. See Ruby on Rails for more information.
Set up sub-domain
- Domains > Manage Domains > Add new domain / sub-domain. (This will take a while to "cook" in the background, so do it first!)
- Enable FastCGI support
- append /current/public instead of just the default directory (domain name) suggested to the location.
- USE: newapp.yourdomain.com/current/public
- and NOT: newapp.yourdomain.com
- After DNS allows access to your http://newapp.yourdomain.com domain, manually delete the /current/public and /current directories that were created by DH.
- This is so that later in this tutorial, cap deploy can create a symlink to /current, allowing Capistrano and Subversion to live happily together. Thanks to topfunky.com for the troubleshooting tip!
Set up new database
- Goodies > MySQL (This will also take a while to "cook")
- Optionally, follow rails conventions for MySQL and create the dbname newapp_production.
- Setup a server for the db: mysql.yourdomain.com (Rails calls this the host).
- Take note of the dbname, username and password you setup, as you'll need this in your database.yml
Your database.yml file should look something like this:
development: # [...your development settings for local machine ...] test: # [...your test settings for local machine ...] production: adapter: mysql encoding: utf8 database: newapp_production #following rails db naming convention username: newapp_dbo_user password: newapp_dbo_pass host: mysql.yourdomain.com port: 3306 #not necessary since its the standard mysql port
Notes:
By default your database.yml often comes generated with a socket connector. Don't use socket for Dreamhost.
Replace/comment out the socket:
#socket: /var/run/mysqld/mysqld.sock
and add the host (mysql server name setup in the panel) and port number:
host: mysql.yourdomain.com port: 3306
I included the port here for completeness; but since DH uses the standard mysql port, its technically not necessary.
Subversion
This step should happen after DH DNS has created your newapp.yourdomain.com and it resolves in your browser. If you do this step before that has happened, you may have to delete your subversion repository and recreate it agian.
Unless you intend to let Capistrano create your subversion repository elsewhere, you'll want to establish your subversion repository in Goodies > Subversion in DreamHost's control panel. (You can also set it up at another subversion host, if you wish. It makes sense to do it manually, if the host will not let Capistrano do it.)
Environment Configuration
Important: Read the Ruby on Rails page before you proceed, especially the "To set up Rails on a subdomain" section.
Force Production RAILS_ENV
Previously, it was recommended to uncomment the RAILS_ENV line in config/environment.rb. However, Dreamhost now defaults to 'production' environment, so this is no longer necessary. You can skip this step.
Typically, with a default rails app, the RAILS_ENV line comes commented out (#) in config/environment.rb file. Committing the environment.rb file with the line uncommented will cause havoc on your dev environment each time you update your code from the repository.
If your using Capistrano, you can cleverly surpass this problem and force 'production' environment during deployment by add the following the task in your Capfile:
desc "Restarting after deployment"
task :after_deploy, :roles => [:app, :db, :web] do
run "sed 's/# ENV\\[/ENV\\[/g' #{deploy_to}/current/config/environment.rb > #{deploy_to}/current/config/environment.temp"
run "mv #{deploy_to}/current/config/environment.temp #{deploy_to}/current/config/environment.rb"
end
Fix Dispatcher Shebang!
Modify the Ruby she-bang lines. Most are fine. The ones in public/dispatch.* are wrong. Change them to:
#!/usr/bin/env ruby
Fix .htaccess to use Dispatcher
In public/.htaccess, change the RewriteRule for the dispatcher to use the FastCGI dispatcher instead:
RewriteRule ^(.*)$ dispatch.fcgi [QSA,L]
Add these rules immediately after RewriteEngine On to display a maintenance page if it exists on the file system:
RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f
RewriteCond %{SCRIPT_FILENAME} !maintenance.html
RewriteCond %{SCRIPT_FILENAME} !^(.+).(gif|jpg|css|js|swf)$
RewriteRule ^.*$ /system/maintenance.html [L]
Automate Deployment with Capistrano ("capify")
From your RAILS_ROOT, execute the following commands:
$ capify .
The above will create the two files ('Capfile' and 'deploy.rb') inside your rails root, that Capistrano uses to do deployment. The output should look something like this:
[add] writing `./Capfile' [add] writing `./config/deploy.rb' [done] capified!
$ svn add Capfile config/deploy.rb
The above line adds the new Capistrano files to your subversion repository.
Edit config/deploy.rb, setting :application and :repository properly. All roles should point to your newly created web host. :deploy_to should point to the top-level of the web directory you set up earlier (NOTE: leave current/public off the end). On DreamHost's shared hosts, sudo can't be used to restart the app. So set :use_sudo to false. Set :deploy_via to :export so as not to create a .svn in your world-accessible directory.
Your config/deploy.rb should resemble:
set :user, 'dhuser' # Your dreamhost account's username
set :domain, 'servername.dreamhost.com' # Dreamhost servername where your account is located
set :project, 'myapp_name_from_repository' # Your application as its called in the repository
set :application, 'myapp.mydomain.com' # Your app's location (domain or sub-domain name as setup in panel)
set :applicationdir, "/home/#{user}/#{application}" # The standard Dreamhost setup
# version control config
set :scm_username, 'YOUR_SVN_USERNAME'
set :scm_password, 'YOUR_SVN_PASSWORD'
set :repository, "http://svn.my_subversion_domain/#{project}/trunk/"
# roles (servers)
role :web, domain
role :app, domain
role :db, domain, :primary => true
# deploy config
set :deploy_to, applicationdir
set :deploy_via, :export
# additional settings
default_run_options[:pty] = true # Forgo errors when deploying from windows
#ssh_options[:keys] = %w(/Path/To/id_rsa) # If you are using ssh_keys
set :chmod755, "app config db lib public vendor script script/* public/disp*"
set :use_sudo, false
Note that the db role specifies where migrations should be run, not where the database is located. That's why the domain should be the one where you have shell access, not your database's domain.
If you've configured a SSH public/private key, you may set the ssh_options[:keys] variable to prevent Capistrano from asking for your password.
Deployment with Capistrano
NOTE: Commit the changes (covered above) in environment, config, and .htaccess / dispatch.* files to your subversion repository prior to deploying.
Prepare deploy environment
First setup server environment by running:
cap deploy:setup
Note: cap deploy:setup creates the releases and shared folders. Running cap migrate after might give you a file not found bash error as capistrano tries to cd the current folder; never mind this and simply skip to cap deploy.
If your repository and config/deploy.rb are set up properly, cap deploy will create a current symlink to the active release folder after exporting it from your repository.
Deploy
After setting up the environment, run a "cold" deployment (first time only):
cap deploy:cold
From then on, to deploy new versions, run:
cap deploy # or: cap deploy:migrate
It might go without saying, but you'll need the command line version of Subversion installed on your development server for the above commands to work.
Maintenance via Capistrano
To revert instantly from a disastrous deployment, run:
cap deploy:rollback
If you need to stop for serious maintenance:
cap deploy:web:disable
Run this when you're ready to face the world again:
cap deploy:web:enable
Update your production server with latest changes from svn:
cap deploy #or: more explicitly... cap deploy:stop cap deploy:update cap deploy:start
Miscellaneous Tasks
To see the tasks available to you, from your RAILS_ROOT run:
$ cap -T
Will give you a listing of all the tasks available. Run the following for a specific task to get the description:
$ cap -e [taskname]
Keep Generated Files Between Deployments
If your Rails app stores any files on the file system, these aren't kept in SVN so they will need to be kept such that they aren't lost when you re-deploy a new version. The "shared" directory is intended for this, and you can symlink files that you store under "shared" to where they belong within your deployment. You can use a Capistrano event hook to make a task for this in the Capfile so that this works transparently every time you re-deploy.
In this example, files that you want to appear at public/files/uploads are stored under shared/uploads:
desc "Link shared files"
task :before_symlink do
run "rm -drf #{release_path}/public/files/uploads"
run "ln -s #{shared_path}/uploads #{release_path}/public/files/uploads"
end
The directory will now act like it's part of the current deployment, but won't be lost when you re-deploy.
Gotchas
Default shell
Note that Capistrano assumes your default shell is bash (or perhaps some other sh variant). If you get "if syntax" errors when attempting to deploy, this may be the problem. To fix it, log into the Dreamhost control panel and change your shell to bash.
Freezing Rails vs. Third party code
If you're freezing Rails for deployment (as is wise following the aborted debut of Rails 1.1 at DreamHost) you will need to take special precautions. One way is to set svn:externals on vendor/ to rails http://dev.rubyonrails.org/svn/rails/tags/rel_1-1-0 (for Rails 1.0) instead of running rake freeze_gems. The downside is that your deployments will depend on dev.rubyonrails.org being reachable. Tracking your third party dependencies in your own repositories avoids this problem.
- Using svn:externals on vendor/: Ruby on Rails hosting (scroll down to the update)
- The disadvantage of 'svn:externals'
cap deploy gets stuck 'subversion is asking for a password'
You need to make sure the account you’re using with Capistrano (i.e. your dreamhost account) can access your Subversion repository from the app server where the cap script is running. The solution seems to be to SSH into your dreamhost server and svn co your_repos into a temp directory. It’ll prompt you for the username and password, and once you’ve entered it successfully, it’ll remember it. Then you’ll be able to deploy without any problems.
"svn export" results in 'Killed by signal 15'
If you are pulling your code from your local environment using svn+ssh:// URLs, you will likely get a "Killed by signal 15" error message:
Try running this command from your DreamHost server:
svn list svn+ssh://username@offsite.com/abs/path/to/svn/repos/rails_apps/test_foo
foo
bar
config
...
Killed by signal 15
To get around this, you can change the ":deploy_via, :export" to ":deploy_via, :copy" which will do the local checkout and then push a tar.gz file to the DH server. This also works if you're not using DH svn server, or your svn repository is not accessible over the internet (ie: behind a firewall).
Resources
- Feb 2008 - Deploying Ruby on Rails with Capistrano on DreamHost
- Rails Manual: Capistrano
- Capistrano 1.1 changes
- RailsMachine video
- Nuby on Rails Dreamhost Capistrano Writeup and Task
- Notes on a June 2006 presentation of Capistrano by Mike Clark
- Deploying Rails with Edge and Engines to Dreamhost using Capistrano
- Deploying to Dreamhost with Capistrano
- How To Deploy your first rails app to Dreamhost using Capistrano in Windows
SwitchTower
Capistrano was known as SwitchTower until March 2006. Graeme Mathieson's excellent quick-start guide for SwitchTower (the principal source for this article) can be found here: Using SwitchTower with Ruby on Rails and DreamHost.

