Welcome Guest | Login

Capistrano - Deploying Your Rails Application on HostingRails.com



This is a wiki article created by HostingRails users. Please login or signup to make edits.




WHY USE CAPISTRANO? : Using Capistrano in conjunction with a Subversion repository makes deploying and updating your production application much easier and reliable. There is a little bit of setup involved, but once you have everything in place updating your live app is as simple as "$ cap deploy"!



Notes and Updates : Capistrano 2.0 has recently been released and has many changes and improvements. This tutorial is designed with Capistrano 1.4.1 in mind, and will not work with Capistrano 2.0. If you would like to deploy your Rails app with Capistrano 2.0, it is recommended that you read through this tutorial first to gain a better understanding of what Capistrano does and how it works with SVN (your subversion repo).  Then, for detailed instructions on how to deploy with the latest version of Capistrano, see this Capistrano 2.0 tutorial.



This tutorial makes the following assumptions about your setup.
  1. You have a local, or development, machine where you develop your Ruby on Rails application. This is where you develop and test your code. (Because we don't develop and test on live servers... right!?)
  2. You want to deploy your local/development Rails app on your live/production HostingRails account.
  3. You want to setup, or have already setup, a Subversion repository on your live/production HostingRails account. This is where you will keep all revisions of your code, yes, on the live/production server, in Subversion (svn).
    • This tutorial covers how to setup basic single-user svn repository access to get your app up and running quickly.
    • For more advanced instructions on how to setup a Subversion repository for single-user and/or multi-user access, see this Subversion tutorial, but for now, read on...


How Capistrano Works

In our setup everything is done on your local computer. With the exception of some minor setup on your HostingRails account, you shouldn't need to do much to the live server. Which is in your best interest, and those who share the same server as you. With a few Capistrano commands you will be able to setup the initial directories on the server, deploy your application, run migrations, rollback to previous versions of your code, and restart your mongrel server or fcgi processes for starters. While Capistrano can do a number of customized tasks, this tutorial will focus on simple deployment to get you started.



== Get Started =>

1. Setup your local/development server with Termios gem and Capistrano 1.4.1

One of the first things you may want to do is install the Termios gem. This gem, which is not available for Windows, will help to protect your password from being sent in the clear. And install Capistrano just in case you don't have it on your local machine.
localmachine [~]$ gem install termios # Not on Windows
localmachine [~]$ gem install -y capistrano -v 1.4.1
A nice time saver is to use ssh_keys. Capistrano will ask for your password several times as it is making changes to your code on HostingRails, and setting up ssh_keys, though optional, streamlines the process just a little more. This is not a complicated process and there are a number of tutorials online.



2. Setup a Subversion repository on your live/production HostingRails account

Next you want to have a repository on your HostingRails account. We'll setup a basic repository here, then check it out to our local machine.

Note : In this tutorial, we are going to use HostingRails as an example name of our Rails application.  Make sure to replace "hostingr" with your HostingRails username, "hostingrails.com" with your domainname.com, and "hostingrails" with your Rails application name.

hostingr@hostingrails.com [~]$ mkdir -p ~/svn/hostingrails
hostingr@hostingrails.com [~]$ svnadmin create ~/svn/hostingrails
hostingr@hostingrails.com [~]$ mkdir -p ~/tmp/hostingrails/{tags,branches,trunk}
hostingr@hostingrails.com [~]$ svn import ~/tmp/hostingrails file:///home/hostingr/svn/hostingrails -m "Created Repository"
At this point you have enough setup on your HostingRails account for single-user access to Subversion. You can now check out your repository at:

localmachine [~]$ svn co svn+ssh://hostingr@hostingrails.com/home/hostingr/svn/hostingrails/trunk
However, if you would like multi-user access to the svn repository, or would like to setup http access to your repository you will need to follow this tutorial: Multi-User SVN - Setup Instructions



3. Check Out Your Subversion Repository

Next we are going to add your existing Rails app to the Subversion repository. If you don't have an existing app, you will need to create one.

localmachine [~]$ svn co svn+ssh://hostingr@hostingrails.com/home/hostingr/svn/hostingrails/trunk hostingrails_dev
or, if you have setup multi-user access:

localmachine [~]$ svn co http://svn.hostingrails.com/svn/hostingrails/trunk hostingrails_dev
Next, you will need to copy your existing Rails app on your local machine into the version we just checked out

localmachine [~]$ cp -R hostingrails/* hostingrails_dev
Now you can see if Subversion recognizes the updated files and directories:

localmachine [~]$ cd hostingrails_dev
localmachine [~/hostingrails_dev]$ svn status
You should get something like this:

?      test
?      app
?      tmp
?      log
?      Rakefile
?      script
?      components
?      config
?      db
?      doc
?      lib
?      README
?      vendor
?      public
Now, just add them to the repository:

localmachine [~/hostingrails_dev]$ svn add test app tmp log Rakefile script components config db doc lib README vendor public
You will see a list of the files that were added with an 'A' next to indicating that the files will be added on the next commit. You will see something like this:

A         test
A         test/fixtures
A         test/fixtures/contact_mailer
A         test/fixtures/contact_mailer/notify
A         test/fixtures/contact_mailer/validate_email
A         test/fixtures/contacts.yml
A         test/functional
A         test/functional/website_controller_test.rb
A         test/integration
# and so on
Next, lets commit the Rails app to the repository

localmachine [~/hostingrails_dev]$ svn commit -m "Added Rails Application"
This may take a few minutes depending on the size of your application. You will see the list of files appear again followed by this:

Transmitting file data .................................................................
Committed revision 2.
Now your will be able to edit your code on your local machine and have the changes reflected in newer revisions simply by adding and committing files. Of course, you may want certain files and directories excluded from the repository. But, for this tutorial, we will go ahead and leave the app as is.



4. Add Capistrano Functionality

Make sure you are in the top level of your Rails app on your local machine and enter the following:

localmachine [~/hostingrails_dev]$ cap --apply-to .
Note: If using Capistrano 2.0: cap --apply-to no longer works and has been replaced with capify

You should see:
      exists  config
     create  config/deploy.rb
     exists  lib/tasks
     create  lib/tasks/capistrano.rake
So Capistrano added two files, deploy.rb in the config directory and capistrano.rake in the lib/tasks directory. We will customize Capistrano to work with our HosingRails account by editing the deploy.rb file.

Notice that the extension is .rb, this means it is a Ruby file and we can use all the typical Ruby syntax to write "Recipes" to help us handle the necessary tasks to deploy our application to the server.

So open the deploy.rb file and we'll start customizing the deployment process.

The first thing we want to do is set our application variables. So let's modify this first section of the file:

# =============================================================================
# REQUIRED VARIABLES
# =============================================================================

# User specific variables

set :domain, "hostingrails.com"   # change this
set :user, "hostingr"             # change this
set :application, "hostingrails"  # change this
# set :mongrel_port, "****"       # change this
# set :mongrel_nodes, "*"   # change this


set :rails_env, :production
set :deploy_to, "/home/#{user}/apps/#{application}"
set :chmod755, %w(app config db lib public vendor script tmp public/dispatch.cgi public/dispatch.fcgi public/dispatch.rb)
set :use_sudo, false
set :repository, "svn+ssh://#{user}@#{domain}/home/#{user}/svn/#{application}/trunk"
# set :repository, "http://svn.#{domain}/svn/#{application}/trunk"

# NOTE: As of Capistrano 2.1, anyone using Windows should allocate a PTY explicitly.
# Otherwise, you will see command prompts (such as requests for SVN passwords) act funny.
# default_run_options[:pty] = true
Alright, we added a few more variable in addition to just editing the existing variables. Here's a brief explanation of each variable:

  • :domain is simply the domain name of your application. You can use as static IP or a HostingRails temporary domain if you don't want to use a permanent domain name yet.
  • :user is your HostingRails user name.
  • :application is an arbitrary name you create to identify your application on the server
  • :mongrel_port is the port number assigned to HostingRails customers who have purchased static memory
  • :mongrel_nodes is the number of nodes for HostingRails customers who have purchased more than 50 MB of memory and you need to specify this number when using a Mongrel Cluster
  • :rails_env simply sets the environment.
  • :deploy_to is the path on your HostingRails account where Capistrano will deploy your app. This is the first instance in our deploy file where we see our previous variables being used.
  • :chmod755 is an array of files/directories that need special permissions. This is very important if you want to deploy your application properly on your HostingRails account.
  • :use_sudo specifies to Capistrano that it does not need to append 'sudo' before all the commands it will run; also very important for deploying on you HostingRails account.
  • :repository identifies where your Subversion repository is located. Here we assume your repository is on your HostingRails account, but you can specify another location if you need to. Also note which type of svn you are using (either single-user or multi-user) and comment/uncomment the appropriate line.
The next section of the deploy.rb file contains the role definitions. Capistrano by default created three roles, but you can add others if you need to. The default roles are:

role :web, "www01.example.com", "www02.example.com"
role :app, "app01.example.com", "app02.example.com", "app03.example.com"
role :db,  "db01.example.com", :primary => true
role :db,  "db02.example.com", "db03.example.com"
Since most HostingRails users will have the same domain name for their web, app, and database, we can simply use our domain variable we set earlier.

# =============================================================================
# ROLES
# =============================================================================

role :web, domain
role :app, domain
role :db,  domain, :primary => true
Notice that we have removed the second, or slave, database definition. If you have multiple databases, one serving as a master (indicated with the :primary => true) and others serving as slaves, then you can add the address for the slave databases.

The next group of variables that we will work with are the Optional Variables. Since we have declared these already you can either delete them, or leave them commented out.

Next if you have setup your HostingRails account with your SSH Keys then you can use the next line to inform Capistrano where your keys exist on your local machine. Otherwise, just leave the line remmed out.

# =============================================================================
# SSH OPTIONS
# =============================================================================
ssh_options[:keys] = %w(/full/path/to/your/ssh_key/id_rsa)
Next is the first set of tasks. The first grouping is for FCGI apps.

# =============================================================================
# FCGI TASKS
# =============================================================================

# Uncomment these tasks if using FCGI to serve your Rails Application

desc "FCGI is already running, so we don't really need the spinner script, but we have it create the initial symlink for us"
task :spinner, :roles => :app do
 run "rm -rf /home/#{user}/public_html;ln -s #{current_path}/public /home/#{user}/public_html"
end

desc "Restart the FCGI Process"
task :restart, :roles => :app do
 run "cd #{current_path}; killall dispatch.fcgi"
 cleanup
end
These two tasks will cover the basics if you are using FCGI. The first task is :spinner. Capistrano wants to start an FCGI process for your application. However, since HostingRails servers are already setup for FCGI, we don't need to tell the server to start FCGI. Instead, we simply tell the :spinner to create our initial symlink. The spinner script will only be used when you cold deploy your app, which we will cover later.

The :restart task is run every time you deploy your app and does two commands. First it kills any running FCGI process so the server will serve the latest revision of your code. And it also performs a cleanup task. Every time you deploy your application, Capistrano saves a full copy of your Rails app. Over time this will begin to fill up your alloted space. Cleanup removes all but the last five revisions of your code. This is customizable if you want to keep fewer or more revisions.

The next group of tasks are for apps running on a single instance of Mongrel.

# =============================================================================
# MONGREL TASKS
# =============================================================================

# Uncomment these tasks if using Mongrel to serve your Rails Application

# desc "Start Mongrel for the first time and create the symlink"
# task :spinner, :roles => :app do
#   run "cd #{current_path} && mongrel_rails start -e production -p #{mongrel_port} -d"
#   run "rm -rf /home/#{user}/public_html;ln -s #{current_path}/public /home/#{user}/public_html"
# end
#
# desc "Restart Mongrel"
# task :restart, :roles => :app do
#   run "cd #{current_path} && mongrel_rails stop"
#   run "cd #{current_path} && mongrel_rails start -e production -p #{mongrel_port} -d"
#   cleanup
# end
This performs the same basic tasks as the FCGI tasks. On a cold deploy, it will start mongrel for the first time and create the symlink. For every subsequent deployment, it will stop mongrel, start it again, and run the clean up task.

The last group of specific tasks are for Mongrel Clusters.

# =============================================================================
# MONGREL CLUSTER TASKS
# =============================================================================

# Uncomment these tasks if using Mongrel to serve your Rails Application

# desc "Start Mongrel for the first time and create the symlink"
# task :spinner, :roles => :app do
# run "cd #{current_path} && mongrel_rails cluster::configure -e production -p #{mongrel_port}0 -N #{mongrel_nodes} -c #{current_path} --user #{user} --group #{user}"
# run "cd #{current_path} && mongrel_rails cluster::start"
# run "rm -rf /home/#{user}/public_html;ln -s #{current_path}/public /home/#{user}/public_html"
# run "mkdir -p #{deploy_to}/#{shared_dir}/config"
# run "mv #{current_path}/config/mongrel_cluster.yml #{deploy_to}/#{shared_dir}/config/mongrel_cluster.yml"
# run "ln -s #{deploy_to}/#{shared_dir}/config/mongrel_cluster.yml #{current_path}/config/mongrel_cluster.yml"
# end
#
# desc "Restart Mongrel"
# task :restart, :roles => :app do
#   run "ln -s #{deploy_to}/#{shared_dir}/config/mongrel_cluster.yml #{current_path}/config/mongrel_cluster.yml"
#   run "cd #{current_path} && mongrel_rails cluster::restart"
#   cleanup
# end
NOTE: Make sure you have entered in your crontab properly on your account. Capistrano does not need the crontab to deploy your application, but if the server is ever rebooted, your mongrel instances will not be restarted properly without the crontab in place.

Lastly, we have our general tasks.

# =============================================================================
# TASKS
# =============================================================================

desc "Set the proper permissions for directories and files on HostingRails accounts"
task :after_deploy do
 run(chmod755.collect do |item|
   "chmod 755 #{current_path}/#{item}"
 end.join(" && "))
end
This takes the array we set earlier (:chmod755) and changes the permissions on the listed directories and files. Notice that this task is run :after_deploy. So once Capistrano has deployed the latest code, it will then issue the chmod command. Unless you have the proper permissions in place on your Rails application, it will not function properly on your HostingRails account. This way you don't have to worry about changing permissions on your local machine, or doing this manually after every deploy.

So our deploy.rb file should look something like this now:

# =============================================================================
# REQUIRED VARIABLES
# =============================================================================

# User specific variables

set :domain, "hostingrails.com"    # change this
set :user, "hostingr"              # change this
set :application, "hostingrails"   # change this
# set :mongrel_port, "****"        # change this
# set :mongrel_nodes, "*"          # change this


set :rails_env, :production
set :deploy_to, "/home/#{user}/apps/#{application}"
set :chmod755, %w(app config db lib public vendor script tmp public/dispatch.cgi public/dispatch.fcgi public/dispatch.rb)
set :use_sudo, false
# set :repository, "svn+ssh://#{user}@#{domain}/home/#{user}/svn/#{application}/trunk"
set :repository, "http://svn.#{domain}/svn/#{application}/trunk"

# =============================================================================
# ROLES
# =============================================================================

role :web, domain
role :app, domain
role :db,  domain, :primary => true

# =============================================================================
# SSH OPTIONS
# =============================================================================
ssh_options[:keys] = %w(/Users/hostingrails/.ssh/id_rsa)

# =============================================================================
# FCGI TASKS
# =============================================================================

# Uncomment these tasks if using FCGI to serve your Rails Application

desc "FCGI is already running, so we don't really need the spinner script, but we have it create the initial symlink for us"
task :spinner, :roles => :app do
 run "rm -rf /home/#{user}/public_html;ln -s #{current_path}/public /home/#{user}/public_html"
end

desc "Restart the FCGI Process"
task :restart, :roles => :app do
 run "cd #{current_path}; killall dispatch.fcgi"
 cleanup
end

# =============================================================================
# MONGREL TASKS
# =============================================================================

# Uncomment these tasks if using Mongrel to serve your Rails Application

# desc "Start Mongrel for the first time and create the symlink"
# task :spinner, :roles => :app do
#   run "cd #{current_path} && mongrel_rails start -e production -p #{mongrel_port} -d"
#   run "rm -rf /home/#{user}/public_html;ln -s #{current_path}/public /home/#{user}/public_html"
# end
#
# desc "Restart Mongrel"
# task :restart, :roles => :app do
#   run "cd #{current_path} && mongrel_rails stop"
#   run "cd #{current_path} && mongrel_rails start -e production -p #{mongrel_port} -d"
#   cleanup
# end

# =============================================================================
# MONGREL CLUSTER TASKS
# =============================================================================

# Uncomment these tasks if using Mongrel to serve your Rails Application

# desc "Start Mongrel for the first time and create the symlink"
# task :spinner, :roles => :app do
# run "cd #{current_path} && mongrel_rails cluster::configure -e production -p #{mongrel_port}0 -N #{mongrel_nodes} -c #{current_path} --user #{user} --group #{user}"
# run "cd #{current_path} && mongrel_rails cluster::start"
# run "rm -rf /home/#{user}/public_html;ln -s #{current_path}/public /home/#{user}/public_html"
# run "mkdir -p #{deploy_to}/#{shared_dir}/config"
# run "mv #{current_path}/config/mongrel_cluster.yml #{deploy_to}/#{shared_dir}/config/mongrel_cluster.yml"
# run "ln -s #{deploy_to}/#{shared_dir}/config/mongrel_cluster.yml #{current_path}/config/mongrel_cluster.yml"
# end
#
# desc "Restart Mongrel"
# task :restart, :roles => :app do
#   run "ln -s #{deploy_to}/#{shared_dir}/config/mongrel_cluster.yml #{current_path}/config/mongrel_cluster.yml"
#   run "cd #{current_path} && mongrel_rails cluster::restart"
#   cleanup
# end

# =============================================================================
# TASKS
# =============================================================================

desc "Set the proper permissions for directories and files on HostingRails accounts"
task :after_deploy do
 run(chmod755.collect do |item|
   "chmod 755 #{current_path}/#{item}"
 end.join(" && "))
end


Now that everything is in place, you can commit your changes to the Subversion repository if you want:

localmachine [~/hostingrails_dev]$ svn add config/deploy.rb lib/tasks/capistrano.rake
localmachine [~/hostingrails_dev]$ svn commit -m "Configured application for Capistrano"


5. Last Step - Setup Your HostingRails Account

Next we need to setup our HostingRails account. This is where our hard work pays off with Capistrano. From your local machine enter the following commands:

localmachine [~/hostingrails_dev]$ cap setup
And you should see something like this:

  * executing task setup
 * executing "umask 02 &&\n    mkdir -p /home/hostingrails/apps/hostingrails /home/hostingr/apps/hostingrails/releases
/home/hostingr/apps/hostingrails/shared /home/hostingr/apps/hostingrails/shared/system &&\n  
mkdir -p /home/hostingr/apps/hostingrails/shared/log &&\n    mkdir -p /home/hostingr/apps/hostingrails/shared/pids"
   servers: ["hostingrails.com"]
Password:
   [hostingrails.com] executing command
   command finished
If you ssh into your account you should see that Capistrano created the directories ~/apps/hostingrails (or your rails app name) and also a releases, shared, and a revisions.log file.

Next you need to run a cold deploy.

localmachine [~/hostingrails_dev]$ cap cold_deploy
You should see something like:

  * executing task cold_deploy
 * executing task update
** transaction: start
 * executing task update_code
 * querying latest revision...

# and a lot of other lines. And if everything went fine you should see.

   command finished
** transaction: commit
 * executing task spinner
Next we can do a full deploy

localmachine [~/hostingrails_dev]$ cap deploy
Or if you want Capistrano to run your migration files (be sure to have your database and database.yml setup properly).

localmachine [~/hostingrails_dev]$ cap deploy_with_migrations
And everything should be deployed properly.

If you ever run into problems and need to rollback to a previous revision of your code simple enter:

localmachine [~/hostingrails_dev]$ cap rollback
As you make revisions to your code on your local machine and are ready to deploy your updated application to the production server all you have to do is:

localmachine [~/hostingrails_dev]$ svn commit -m "Your Custom Reference Message";cap deploy
And Capistrano will take care of the rest!



Troubleshooting

Make sure to edit your local public/.htaccess before deploying, as detailed here.

Additional Resources



Hello Guest! In order to edit this article you must be an active client with us, please log in or sign up today!






Previous URLs for this page here and here