I am actually stunned how many PHP developers still remote into their production environment via SSH and manually run the necessary git commands to update their production branch. While that is the most advanced and flexible option available I dont think it makes sense for smaller projects where the deployment routine is pretty straightforward. There are some services that automate that process and are pretty good at it.

Note this article is for Capistrano v2 and will not work with the current stable release, which is v3

Personally I have experience with Beanstalk, I havent used any other repository hosting that offer deployment feature so I can’t really compare it but as far as I know there are no decent alternatives ( please correct me in the comments if I am wrong ). So what if we want to use a similar feature with our github or bitbucket (I personally love the second because of the free unlimited private repositories) hosted repository and not pay for it. Well the easiest way to do that is to use Capistrano to automate the deployment routine.

Some preparations

Since Capistrano was originally developed for use with Rails its naturally coded in Ruby so you will need to install Ruby on your machine first. Note we are installing Capistrano version 2 in this article, which is not longer the current stable version. After that run the following commands in your cmd/termial:

gem install capistrano -v 2.15.5 gem install railsless-deploy

I am assuming you already have set up your repository and everything is working nicely. One other thing that you might want to do is enable public key SSH authentication to the machine you want to deploy to, so you dont have to enter your password every time you do that, but I will show you an example where you can deploy without having public key setup for the SSH.

In the root directory of your PHP project run the following command:

capify .

That will enable Capistrano and create the necessary files for you: Capfile in the project root and config/deploy.rb

Modify the Capfile so it reads the following:

require 'railsless-deploy' load 'config/deploy'

The first line allows the deployment of non-rails based applications by loading the appropriate extension and the second line loads the configuration file that Capistrano generated for us automatically in the config directory. You can also move the deploy.rb file in another location and change the load directive in the Capfile.

Minor Tweaks

Now we have to modify out deploy.rb file to look like this:

set :application, "App name" set :repository, "https://username:password@yourrepository.org/project-repository.git" set :user, 'shh_username' set :scm, :git set :deploy_to, "/full/path/to/your project" set :deploy_via, :remote_cache set :use_sudo, false set :copy_exclude, [".git", ".DS_Store", ".gitignore", ".gitmodules", "Capfile", "config/deploy.rb"] server "server name", :app

The above code assumes that you dont have a private key ssh connection but instead you will have to manually enter the ssh password each time you deploy your project.

If you do have private key SSH connection and key authentication setup for your repository then you can modify the repository URL not to use the username and password. The configuration is as simple as possible and pretty much self-explanatory. We define :deploy_via, :remote_cache so that a git checkout is cached on each server to speed up deployment and not have to checkout the entire repository each time we deploy. Also :use_sudo is set to false because on certain systems sudo is enabled only in terminal sessions and it takes some effort to configure it so that it works. The :copy_exclude list of files will still be in your repository but they will be excluded from the deployment.

Now you can try running

cap deploy

in your project root or

cap deploy:rollback

if you want to deploy a previous version, in case something broke.

If everything worked fine, you will notice that Capistrano creates a couple of folders in your project root folder on the machine you want to deploy. Namely the folder releases and a symlink current. The way Capistrano functions is that it will keep versions of the previous releases in the releases folders and symlink to the correct one in with the current link which will update every time you run cap deploy or cap deploy:rollback. Naturally you might have to change your web server configuration so that it points to the current directory (symlink), instead of the project root.

Final Deployment

Now in a lot of cases you will need to have some sort of assets that will be shared between all releases – for example file uploads and other similar data. Capistrano makes that very easy too. Just add the following snippet to your deploy.rb file:

namespace :testproject do task :symlink, :roles => :app do run "ln -nfs #{shared_path}/file_uploads #{release_path}/your_file_uploads_directory" end end after "deploy:symlink", "testproject:symlink"

The following snippets show how easy it is to create custom tasks that will be execute after a certain event in the deployment process, in out case that is the deploy:symlink, so after Capistrano finished creating symlink we call our custom task testproject:symlink which will create a symlink of project_root/shared/file_uploads to the current release path which will also be included in the current directory as it is a symlink to the current release.

Keep in mind the following directories have to be created on your server prior to the initial deployment:

project_root/releases

project_root/shared

and have the appropriate permissions. For instance the shared directory should be writeable by the same user that is expected to write to your application file uploads directory.

That is the absolute fastest and simplest way to deploy your PHP app with Capistrano, but of course it is a lot more powerful and customizable, supporting multiple environments, many more custom commands and 3rd party extensions. As a starting poing, go over the Wiki.