Posts Tagged ‘PHP’

Deploying Drupal with Capistrano

Mikamai, the company I work for, has just released Montalbano.tv, 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, "application.name"
 
# 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,  "git@github.com:username/project.git"
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, "first.server.address.com"
role :app, "second.server.address.com", :primary => true
role :web, "first.server.address.com"
role :web, "second.server.address.com", :primary => true
role :db, "first.server.address.com"
role :db, "second.server.address.com", :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}"
  end
 
  # symlink shared directories
  task :symlink, :except => { :no_release => true } do
    sudo "ln -s #{shared_path}/files #{latest_release}"
  end
end
 
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)
  end
 
  task :restart do
    # nothing to do here since we're on mod-php
  end
end
 
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"
    end
  end
 
  # change ownership
  namespace :permissions do
    task :fix, :except => { :no_release => true } do
      sudo "chown -R www-data:www-data #{latest_release}"
    end
  end
 
end