Deploying Drupal with Capistrano

Mikamai, the company I work for, has just released, the companion site to one of the most successful TV shows in Italy.

I was the technical director of this Drupal based project, and while I was happy we chose Drupal, because it allowed us to deliver all the features they needed on time, I almost panicked when they told us the production setup would have two servers, both with database and web serving duties.

The database replication was standard MySql master-master setup, but I had to develop a strategy to keep the two code-bases on the two servers synchronized.

Being a Ruby programmer at heart, I selected the only tool that never fails me in circumstances like the one we had: Capistrano.

Unfortunately, while Capistrano is all easy to use with Rails, I had to write a custom Drupal-tailored Capfile.

Here it is, in its entirety, in case you ever need to deploy Drupal with cap (now I always deploy Drupal with cap, since I have the recipe ready :) ):

load 'deploy' if respond_to?(:namespace) # cap2 differentiator
# Standard configuration
set :user, "username"
set :password, "password"
set :application, ""
# I like to deploy the code in /var/apps
# and then link it to the webserver directory
set :deploy_to, "/var/apps/#{application}"
# SCM Stuff configure to taste, just remember the repository
# here I used github as main repository
set :repository,  ""
set :scm, :git
set :branch, "master"
set :repository_cache, "git_master"
set :deploy_via, :remote_cache
set :scm_verbose,  true
# Two servers, double fun
# You really don't need app, web and db here,
# but I used all of them just to be sure.
# Usually only web is ok.
role :app, ""
role :app, "", :primary => true
role :web, ""
role :web, "", :primary => true
role :db, ""
role :db, "", :primary => true
after 'deploy:setup', 'drupal:setup' # Here we setup the shared files directory
after 'deploy:symlink', 'drupal:symlink' # After symlinking the code we symlink the shared dirs
# Before restarting the webserver we fix all the 
# permissions and then symlink it to production
before 'deploy:restart', 'mikamai:permissions:fix', 'mikamai:symlink:application'
namespace :drupal do
  # shared directories
  task :setup, :except => { :no_release => true } do
    sudo "mkdir -p #{shared_path}/files"
    sudo "chown -R #{user}:#{user} #{deploy_to}"
  # symlink shared directories
  task :symlink, :except => { :no_release => true } do
    sudo "ln -s #{shared_path}/files #{latest_release}"
namespace :deploy do
  # adjusted finalize_update, removed non rails stuff
  task :finalize_update, :except => { :no_release => true } do
    sudo "chmod -R g+w #{latest_release}" if fetch(:group_writable, true)
  task :restart do
    # nothing to do here since we're on mod-php
namespace :mikamai do
  # symlinking to production
  namespace :symlink do
    task :application, :except => { :no_release => true } do
      sudo "rm -rf /var/www/montalbano"
      sudo "ln -s #{latest_release} /var/www/montalbano"
  # change ownership
  namespace :permissions do
    task :fix, :except => { :no_release => true } do
      sudo "chown -R www-data:www-data #{latest_release}"

3 Responses to “Deploying Drupal with Capistrano”

  1. How to ease Drupal development with Capistrano | A Tempest of Thoughts Says:

    [...] following tasks should be used together with the tasks in my Deploying drupal with Capistrano article. I took advantage of deploy:cold not being needed with Drupal, and added a callback to it, [...]

  2. Sweeter, Nicer Drupal with Capistrano | Unconventional Everything Says:

    [...] it.. fortunately we are all Ruby on Rails developers and Capistrano always lends an helping hand. Here are Giovanni’s thoughts and experience on using Capistrano to deploy Drupal applications in our projects. Enjoy the [...]

  3. Interviewed! | A Tempest of Thoughts Says:

    [...] is not the first time I write about Montalbano (as you can see from my previous drupal centered post), but last time I wrote because I wanted to show a clever approach to deploying Drupal, this [...]