Deploy your PHP website with Capistrano

Introduction

The way developers deploy code to web servers is changing. Gone are the days of remembering which files you've changed and manually dragging and dropping files around an FTP client. This deployment method is risky - it's easy to miss a file and therefore break your entire application. FTP is also insecure - no encryption is used when sending your login credentials to the server, or for file transfers. Also, what happens when a visitor is using your application whilst you are uploading - some files might not be fully uploaded and your application will fail.

There are numerous alternatives to FTP, but I'm going to show you how to get started with Capistrano - "A remote server automation and deployment tool written in Ruby". In short, Capistrano allows you to write scripts to execute code on remote servers (and your local machine). We can use this technique to pull code from a version control repository onto our web server and run other commands.

Getting Started

Before we get started, I'm going to make a few assumptions:

  • You're using a Mac (although this should work fine for Linux users too) and have some basic knowledge of using the terminal
  • Your code is kept in version control - if it's not, it should be (I recommend GIT)
  • You've got a dedicated server or VPS to host your application on (I strongly recommend Linode)
  • You use SSH keys to connect to your server(s)
  • You have Ruby installed on your local machine (see the official instructions)
  • You won't be trying this out on a live production application / site (you will have some downtime as you will need to change the path to your web root directory)

First off, install Capistrano by running the following command in your terminal:

gem install capistrano

Next up we're going to install another gem that makes Capistrano a bit friendlier for non-Rails projects, Lee Hambley's Railsless Deploy:

gem install railsless-deploy

That's it - everything we need should now be installed.

Project Setup & Deployment

Navigate to the root directory of your PHP project and run the following command:

capify .

This will create two files that Capistrano will use - Capfile and config/deploy.rb. We now need to modify the Capfile file to tell Capistrano to load the railsless-deploy extension and the deploy script for our project - open the file in your editor and replace the content with the following:

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

You can move the config/deploy.rb file to another location - personally I like to have it at the root level - just remember to update the path to it on the last line of the Capfile file.

The next stage is to update the deploy.rb file to define some settings relating to how our project will be deployed. Here is my starting template (or view it as a Gist) with some pretty syntax highlighting):

############################
## my-php-application.com ##
############################

# Set some options
 set :application, "my-php-application.com" # Set the name of your application
 set :scm, "git" # Set the version control type (I use GIT, SVN + others are also available)
 set :repository, "git@github.com:user/project.git" # Set the path to your version control repository
 set :branch, "master" # Set the branch of the version control repository to deploy from
 set :deploy_to, "/path/to/application/" # The remote path to deploy to (not the web root - you will need to edit this in your web server config later)
 set :user, "some_user" # Remote user to connect via SSH as
 set :runner, "some_user" # Remote user to run commands as
 set :port, 22 # The port number to use for SSH
 set :ssh_options, { :forward_agent => true } # Use SSH agent forwarding (use your personal SSH key for authenticating with your version control repository from your server)
 set :copy_exclude, %w[.DS_Store .git .gitignore Capfile deploy.rb sftp-config.json] # List of files that shouldn't be deployed
 set :keep_releases, 10 # Number of releases to keep on the server (allows you to roll back your application to a previous version)
 set :use_sudo, false # Disable the use of sudo

# Deployment servers
 role :server1, "server1.my-php-application.com" # The domain or IP address of your web server

# After we've deployed, cleanup the old releases
 after "deploy:update", "deploy:cleanup"

Update the variables in this file to what is relevant to you and your application - the comments on each line should help explain what each setting does. There are more settings available (check out the links at the bottom), but this should be enough to get you started.

If you're using GitHub to host your version control repository (you might an issue with other remote hosts too), you will need to ensure that GitHub is in the known_hosts file on your server before you can deploy with Capistrano. To do this, SSH into your server as the user you defined in your deploy.rb file, then run the following command:

ssh git@github.com

If you are presented with a message regarding the authenticity of the host and are prompted to continue, type yes and hit enter. GitHub will return a message and deny you access, but will be added to your known_hosts file and will prevent issues when you come to deploy using Capistrano.

Before you can deploy for the first time, you will need to tell Capistrano to setup your server for deployment (such as creating the required directory structure). To do this, simply run:

cap deploy:setup

You should now be ready to deploy for the first time - but before you do, you check that everything is ready for deployment by running:

cap deploy:check

If the previous two commands have run without any issues, you should now be ready to deploy for the first time! To do this, simply run:

cap deploy

That's it - your project should now be deployed on your server.

Try SSH'ing into the project directory on your server and you should see a directory called releases - each time you deploy, a new sub-directory (named with the timestamp when the deployment took place) will be created in here to store the code for your application. You will also see a symlink called current - this will usually point to your latest deployment. If you needed to rollback your application to a previous version, this symlink would point to the relevant sub-directory in the releases directory.

Finally, you will need to update your web server configuration to ensure the web root now uses the new current symlink that Capistrano created (eg; /var/www/my-php-application.com/current/public_html/). Exactly how you update this will vary depending on your web server software and setup.

Final Words & Further Reading

Capistrano is a powerful tool, and I am by no means an expert - however I hope this guide has helped you to get started. There is so much more you can do with Capistrano such as rolling back deployments and creating custom tasks to run other commands such as updating packages installed through Composer. Until I get round to writing more guides on Capistrano, you might like to check out the following links:

Enjoyed reading this blog post? See all my blog articles »