Tealeaf Academy Blog

Teaching Ruby on Rails Courses

Use Capistrano 3 to Deploy Rails Applications - a Step-by-Step Tutorial

Well, we have a well-developed application built with our laptop, but we want it to be seen by the entire world. Even better, we want to automate this process in order to push our new super-duper features in seconds with only one command on our development machine:

1
cap production deploy

What do we do?

In this article we will cover automated deployment of a Ruby on Rails application to a VPS (Virtual Private Server). We will install a Ubuntu Linux Server (14.04 LTS) and prepare our project for automated deployment with Capistrano 3.

We will use DigitalOcean as a VPS server provider, because they have good technology with competitive prices. There are other alternatives like Amazon EC2, OVH, Linode, Dreamhost …. but the steps would be very similar.

The Automated Deployment Process with Capistrano

For web applications, deployment means a sequence of steps to enable a feature on the production server after having built it locally. It typically involves copying over the source code and optionally, updating system and server configurations, updating the database, restarting the server and services, etc.

Capistrano is a program that allows developers to automate the deployment process using a Ruby based script. It provides core functions to help you to:

  • Use a version control system (git, mercurial, svn..) to manage your app code to maintain good development practices
  • Run system commands, such as installing new gems using bundler or running database migrations
  • Pre-process, compile and obfuscate assets such as CSS/Javascript files
  • Rollback the latest deployment if error happens.

In addition to the core functions, Capistrano also supports a wide variety of community provided hooks and extensions that allows you to:

  • Manage your app server (unicorn, thin, puma…)
  • Manage your ruby version with Rbenv, RVM,…
  • Setup your database (Postgres, MySQL, MongoDB…)
  • Deploy your crontab for scheduled tasks with ‘whenever’ gem
  • Many other features

Let’s now walk through an example of setting up a production server and deploy a Ruby on Rails app with Capistrano:

Step 1. Prepare SSH login on VPS (DigitalOcean)

After creating an account, first we should create our SSH credentials to authenticate with the production server. If you don’t have a pair of ssh keys you can create them following this instructions.

1
cat ~/.ssh/id_rsa.pub

Now copy it to “SSH Keys >> Add SSH Key” with DigitalOcean:

Step 2. Create the server

Now we will create a Droplet, which is a hosted server:

We can choose:

  • Name: capistrano
  • Size: 1024 MB
  • Region: your nearest available one
  • Image: Ubuntu 14.04 x64
  • Add SSH keys: check the one you created

Your root password will be emailed to you, but you do not need it if you have configured your ssh key properly:

We can access the server console with the IP address from the email (make sure to replace with your own ip)

1
ssh [email protected]

Step 3. Server Setup

Now you should install git and other packages to setup the server as a Rails production server.

1
2
apt-get update
apt-get install git gcc autoconf bison build-essential libssl-dev libyaml-dev libreadline6 libreadline6-dev zlib1g zlib1g-dev libsqlite3-dev

Also you need to install ‘rbenv’ as described in the ‘How to Install Ruby on Rails on Ubuntu Linux’ post, in “Step 3. Install Ruby with RBENV”.

You also need to install bundler which will manage gems versions for you.

1
gem install bundler

Step 4. Setting up Capistrano in your Rails project

Go to the directory of your Rails project. We recommend to use rbenv to manage your ruby versions, so if you haven’t done so, fix your project ruby version. If you want to use version 2.1.2,

1
rbenv local 2.1.2

You need to add these gems to the Gemfile:

1
2
3
4
group :development do
  gem 'capistrano-rails'
  gem 'capistrano-rbenv', '~> 2.0', require: false
end

Install and initialize capistrano:

1
2
bundle install
cap install

The latest Capistrano version right now is 3.2.1, which is very different from version 2. Version 3 is multistage by default with two environments: staging and production. So you will have config/deploy/production.rb and config/deploy/staging.rb added to Capfile and deploy.rb files.

In Capfile uncomment:

1
2
3
require 'capistrano/rails'
require 'capistrano/rbenv'
require 'capistrano/bundler'

Change this line at config/secrets.yml:

1
2
production:
  secret_key_base: d58c2bf6365e5758c5c6081a96d4b7b10fd826021e5415fe92451d19caa8063a75e84c5ed47cff7612e092afb220a4afddd8831ad7c8c200afdee42dd0c0cfa1

The number above may be different from your app. This key validates the integrity of your application cookies and you should generate your own secret by running rake secret and use the result to replace your secret key above. On a more sophisticated deployment you can set this as an environment variable.

Ensure you have a production database configured in your config/database.yml file – the below example assumes you use Postgres as production database.

1
2
3
4
5
6
7
production:
  database: <your database name here>
  adapter: postgresql
  encoding: unicode
  pool: 5
  username: <your username here>
  password: <your password here>

Step 5. Preparing your project to deploy

In config/deploy.rb we can configure our app name and repository (:git by default):

1
2
3
set :application, 'my-app'
set :repo_url, '[email protected]:my-github-username/my-app.git'
set :rbenv_ruby, '2.1.2'

Clear the config/deploy/production.rb file and add the following lines to configure the production environment:

1
server '188.226.190.134', user: 'root', roles: %w{web app}

Right now you can check the server availability through the following command:

1
cap production deploy:check

Step 6. Install Thin on the server

We’ll use Thin, a lightweight Ruby application server as an example here for the production server.

On the production server, install the Thin gem for the global ruby version:

1
gem install thin

With the following command you will generate the Thin script for Ubuntu (/etc/init.d/thin), and create Thin configurations folder (/etc/thin):

1
thin install

Now you can start|stop|restart all your apps on this server with the following commands:

1
2
3
service thin start
service thin stop
service thin restart

But you need to configure how Thin will start your app:

1
thin config -C /etc/thin/my-app -c /var/www/my-app/current --servers 1 -e production

Finally, you can create scripts to restart your app when this is rebooted for any reason:

1
update-rc.d -f thin defaults

Step 7. Installing Thin in your project

Add Thin gem to Gemfile:

1
gem 'thin'

And do not forget to run: bundle install

Add this line to :restart task in your config/deploy.rb:

1
2
3
4
5
6
  desc 'Restart application'
  task :restart do
    on roles(:app), in: :sequence, wait: 5 do
      execute "service thin restart"  ## -> line you should add
    end
  end

Pay attention to this line below. here you are calling the restart task after the publishing process.

1
after :publishing, :restart

To deploy your app, just run:

1
cap production deploy

Now your app is deployed! You should be able to visit it on the production server.

The Deploying Process Under the Hood

The command cap production deploy seems magical. It connects with server and performs all the deployment tasks automatically. But here is the explanation to the basic process we have seen in this post:

  • deploy:starting
    • Rbenv ensures that the version we configured on config/deploy.rb is installed and that it can write on disc
    • Checks git repository
    • Create needed folder tree
      • /var/www
        • capistrano-first-steps
          • shared
            • public
              • assets
          • releases
  • deploy:updating
    • Clone the whole repo in /var/www/capistrano-first-steps/repo
    • Creates a new folder date-time named on /var/www/capistrano-first-steps/releases/20140717180754
    • Copies the project there
  • deploy:publishing
    • Runs bundle install in last release folder
    • Runs assets:precompile copying our minimized assets to shared/public/assets
    • Creates a soft link from last release to /var/www/capistrano-first-steps/current
    • Restart thin server. This is due to this line in config/deploy.rb: after :publishing, :restart . This hooks the deploy:restart task after :publising task
  • deploy:finishing – Logs deployment to revisions.log

You can take a look to the official documentation to see how is the Capistrano deployment flow processed.

Conclusions

Capistrano is a great tool to automate application deployment with good out-of-box support for Ruby on Rails applications. It takes some time to learn the ins and outs of the tool and build up your own deploy script, but once it’s built, it’s pretty easy to use it for automated deployment. It has a rich feature set and with its big community, it can grow with your app to meet more complicated deployment requirements.

Comments