Deploying WordPress with Git and Capistrano

In 2011 Mark Jaquith mentioned Capistrano in his presentation at WordCamp San Francisco concluding the deployment of web applications for various test and development purposes could be handled easily and extensibly with the help of Capistrano.

Larger projects tend to further a need for the server environment to be extended in order to manage incoming traffic. At Inpsyde we work with the following setup even at smaller and medium scale projects:

  • local development environment
  • dev server (shared development server)
  • staging/test server (everybody should have this for client approval)
  • live server {n}

What is Capistrano?

Capistrano is a command line application for rolling out web applications to multiple servers. It has been developed for ruby on rails applications in the first place, but it works just as well for applications of all kind including WordPress, of course.

A typical application like a WordPress site usually is managed through a versioning program (GIT, SVN, CVS …). After having developed and tested locally you log in to the server via SSH and load your changes from the repository of the versioning program.

At this point of development Capistrano comes into play. After a short configuration the application will process the following sequence by default

  1. log in to the server via SSH
  2. navigate to the correct directory
  3. upload the modifications from the repository

Additionally, automatic versioning of different deploys is applied within the file directory. This allows us to switch back to an older version. Also the procedure can be extended with advanced automatisms.

Installation Capistrano

Because Capistrano is written in Ruby, Ruby has to be installed on the local environment. Scripts and config files also are to be written in Ruby. Yet with but a little of coding knowledge, that’s a quite easy task.

With the command ruby --version you can find out via command line if Ruby has been installed already. In some Linux distribution Ruby is pre-installed, otherwise it has to be installed via package manager with an apt-get install ruby command (in Debian). For Windows and Mac OS X the following installers can be used:

Ruby comes with its own package manager named gem. Thus, you can install Capistrano afterwards with the following local commands via console:

The first package is the main Capistrano program, with the railsless-deploy package you can deploy non-rails-applications, too. The third package provides a couple of useful extensions for Capistrano, i.e. to enable “staging”.

After that, you should check with

if the installation has been successful. The following message should appear:

Project structure in Git

For our client porjects we only store the wp-content directory in the Git repository. The uploads directory doesn’t get checked in with Git, because we have a separate directory for dynamic data in Capistrano projects. Our Git repository now looks like this:

Project structure on the server

For our project structure on the server the use the following:

The wordpress repository is the root directory of our web site. The directories wp-admin and wp-includes as well as the PHP files within the root directory have to be on the server. wp-content is empty and gets a symlink to your-project/deployments/current. We’ll get back to the shared directory later.


In order for WordPress to resolve symlinks correctly WP_CONTENT_DIR has to be defined. We use the PHP function realpath to do that. It resolves the symlink to the wp-content directory and returns the correct path.

Capify WordPress

After we’re done with preparations now, let’s move on to the fun part: implementing WordPress for Capistrano. In order to do that navigate to wp-content in your console and enter this command:

It creates a special file named Capfile in wp-content and generates a directory config. That directory contains important files for the configuration and deployment of the project. Capfile helps Capistrano load your configurations and scripts.

Let’s take a look at Capfile first. In order to do so we open the file and replace all default values generated by the following:

The first line loads the railsless-deploy module which ist required, because we’re about to deploy WordPress and not a Ruby application with Capistrano. The Multistage block defines what stages we’re going to have later on. In default_stage one of those stages is registered. Later on we’re going to create equally named cofiguration files for all selected stages containing required server data.

Finally, we have the deploy.rb file from the config directory. Open that file and replace its content with the following:

In the first line we name our application. The next block begins with SCM (Source Control Management). Here we assign :git (more SCM here). In the following lines we define our repository and the branch we want to have on our server. The variable deploy_via we set to :remote_cache. This variation provides a copy of our Git repository on the server, performs only a “fetch” instead of a complete “clone” and thus speeds up the deployment process. Further strategies for deployment can be found here.

In the last block we define the variable :copy_exlude as an array of files we don’t want to keep on our server whereas they do reside in our Git repository. :keep_releases defines how many versions we keep backwards and :use_sudo can be set to false as we don’t want Capistrano to sudo everything it does on the server.

Go to the official documentation for more settings.

Lastly we create a directory named deploy inside the config directory for the three configuration files mentioned above to reside in:

Enter your server access data as follows:

The value of deploy_to refers to the directory on the server where the application resides (see project structure on the server). user contains the SSH user for deployment. The last line sets the host for the :app role. It doesn’t play a big part at this point yet, just keep in mind it’s there. Finally, we process the following command:

This command prepares the required directories on the server. In order to verify everything is ready for the next step, we can do:

to check the local environment on the named server and search for possible conflicts. If everything has been configured correctly, we see this comforting message:

Our first deploy

After successfully having completed all configurations, we’re ready for our first deploy. Let’s navigate via console to our project file where Capfile resides and enter the following:

This command logs into your previously named development server the_host.tld and navigates to /path/to/deployments/. Subsequently it clones the master branch from Git into the releases repository. By now you should see a bunch of output in your console basically saying what is happening and at what state. Once everything completed successfully, you should see this message:

In order to not enter your access data for every new deploy with Capistrano, you might want to generate an RSA key and store it on the target server. Learn more about that method here:

By now we have successfully processed our first cap deploy. Let’s take a look at what has actually happened. To do that we connect to our server via SSH and navigate to our deploy_to path. And behold, there are two new directories:

The current directory is a symlink to the newest subdirectory of releases. After each deploy a new folder with the complete directory will be created in releases. The symlink on current will be updated automatically.


Not that we’re going to need it, but what if anything goes wrong and our site isn’t accessible anymore after deploy? There’s a very simple solution:

This command sets the symlink on our current directory to the previous release. Via

we can switch back to our newest version very quickly.

Clean up releases

Because create a complete new release of our application with every single cap deploy, our release directory might get rather stuffed. In deploy.rb we have already defined “5” with set :keep_releases, so we only keep five releases. Nonetheless we have to tell Capistrano to clean things up at last:

In order not to have to enter that command after each deploy we simply set it at the end of our deploy.rb:

So after each deploy the hook cleanup will be processed and obsolete releases will be deleted.

Capistrano shared files

We know by now how to deploy and rollback. Let’s learn about how to link our released data to the shared directory. Since with every deploy/rollback our wp-content directory is being shifted (to a new subdirectory under releases), we need to automatically update the symlink for uploads. What’s better than defining a small task to be executed with every deploy?

The following three steps are required:

1. Create a file named task.rb within the config directory and enter the new task:

First, we define the namespace under which the call will happen later. It reflects the scheme: cap {namepsace}:{task}. The next block defines the actual task assigning the role :app. That means, our task will be executed only for the defined server with the role :app. In line 4 we define the actual command ln -nfs to be executed and the symlink to be generated. The variables shared_path and release_path are pre-defined by Capistrano.

2. Add the following before load 'config/deploy' in your Capfile:

Thus, we’ll run our previously defined task before each deploy.

3. Open your deploy.rb file and add your new task at the end:

We’re defining the new task to be executed after the deploy has been finished. That task will update the symlink for our latest release

on our shared directory


I hope I’ve been able to provide an insight into the workflow with Capistrano for you. A lot of processes can be optimized easily and quickly nowadays. Like every other tool, Capistrano a bit of getting familiar with and initial configuring, but there’s a lot of time to be saved particularly on larger projects. Also you’re able to resolve a bunch of dependencies by using common interfaces and embed various automatisms into your workflow of deployment.

Finally, here are all the mentioned files for you to download and play with. Have fun!

Post Sharing

Author Avatar

Hi! My name is Chris and I enthusiastically develop the web from back-end to front-end at Inpsyde. When I'm not discussing accessibility, you can find me at Google+. In my spare time I study computer science, do a lot of sports, read one book after the other and blog at

Also Interesting

New Plugin: Slack Connector - Connect WordPress, WooCommerce and Slack

by Michael Firnkes

Initially we merely wanted to optimize our own Slack-processes. With automated notifications from our MarkettPress shop, the blog and our forums. The resul ...

Read more

Role Based Prices for WooCommerce is available again: Different prices for different customer groups

by Michael Firnkes

You want different prices for different customers and users of your online shop? E.g. for subscribers or wholesaler? Or do you need bulk prices? A lot of o ...

Read more

Note to our Customers: MarketPress becoming MarketPress GmbH

by Michael Firnkes

MarketPress - previously a project of Inpsyde GmbH - is about to become its own company. This is a huge step on our journey of building the first marketpla ...

Read more

Inpsyde is the first VIP partner in Germany

by Michael Firnkes

Automattic has given us the title of VIP Service Partner, the first in Germany, Austria and Switzerland. Worldwide, there are only eleven com ...

Read more