Chronicling the trials and tribulations of developing for the modern web.



Automate the deployment of any PHP project using Capistrano.

Posted by Pat Nakajima on May 30, 2007 in PHP.

This recipe has been completely updated. To view the revised version, check here: Deploy any project using Capistrano 2.

A little while back, I posted a Capistrano recipe for deploying Mint alongside a Rails application, and it’s been one of this blog’s most popular posts to date. The recipe itself could be more flexible, but if you’re willing to work within its constraints, it does a good job of simplifying the deployment of Mint and its somewhat frequent updates.

Recently though, I was working on a PHP project, and I decided that the time had come to rewrite my Mint recipe to allow deployment of any PHP project, totally independent of Rails. I set to work, and I’m happy to share the result.

Requirements

  • Capistrano 2 Preview 2 (Again, Jamis Buck’s blog is an excellent resource)
  • Knowledge of the command line
  • The ability to configure your web server (I used Apache)

Before you get started

Make sure you’ve created the deployment directory on your remote server before you use this recipe. Make sure that this directory’s permissions allow your deployment user to write to it. For the time being, that will require you to ssh into that server. In the future, I’ll make the Cap task do it for you.

Also make sure you’ve configured your web server to route requests to your application as necessary. (I’ve pastied a sample VirtualHost configuration for Apache.)

The recipe

  
    require 'capistrano/recipes/deploy/strategy'
    # Capistrano PHP Deployment Recipe
    # Created by Pat Nakajima

    # TODO  Create a setup task that would create apache conf file for the project.

    # Set your project name here, it's probably best to use the domain name.
    set :application, "your-project-domain" 

    # Roles (You probably won't need to modify these.)
    role :app, application
    role :web, application
    role :db,  application, :primary => true

    # Set the location of your PHP project in your repository.
    set :repository,  "your-project-repository-url" 

    # Deployment Settings
    # Set the location that you'd like as your project's destination.
    # I created a separate folder from my Rails apps to put things like this.
    set :deploy_to, "/var/www/sites/#{application}" 
    set :deploy_via, :checkout

    namespace :deploy do
      namespace :php do

        # Strips much of Capistrano's default deployment process because
        # it's tailored for Rails apps, and we don't need most of it.
        desc "Deploy a PHP project." 
        task :default do
          update_code
          symlink
        end

        task :update_code, :except => { :no_release => true } do
          on_rollback { run "rm -rf #{release_path}; true" }
          strategy.deploy!
          finalize_update
        end

        # This part is borrowed from Geoffrey Grosenbach.
        # Overridden since PHP doesn't have some of the Rails directories
        task :finalize_update, :except => { :no_release => true } do
          # Make directories writeable by the deployment user's group
          run "chmod -R g+w #{release_path}" if fetch(:group_writable, true)
        end

        # Symlinks 
        task :symlink, :except => { :no_release => true } do
          on_rollback { run "rm -f #{current_path}; ln -s #{previous_release} #{current_path}; true" }
          run "rm -f #{current_path} && ln -s #{release_path} #{current_path}" 
        end

        task :restart, :roles => :app do
          # Do nothing (I have a different recipe to restart Apache.)
        end

      end
    end
  

Usage

To use this recipe, make sure you’re in your project’s root directory, then run the following command:

cap deploy:php

If you decide to use this recipe, please share your experience in the comments of this post. Your feedback will help me make this recipe better.