Deploy apps to the Media Temple Grid Service with Capistrano

Last time I upgraded WordPress, I decided it was time to create a deploy process on this blog. Lots can go wrong with upgrades and updates, and I really don’t have a good reason to avoid version control and automated deployments when I can basically do it all for free.

I use Media Temple’s Grid Service, which means the Capistrano deploy recipe for pulling this off has a few customizations needed to work properly, which is why I thought I’d document it here.

For the impatient: the recipe for my Railsless WordPress deploy on Media Temple’s Grid Service. Please note the original version of my recipe, from which my version is forked. The original did almost everything I needed; yay, Github.

Technically Grid Service users do not have full root access, however, users can enable shell access and even create files above the public docroot which was enough for me to get deployments working! I am not going to document it here, but you need to set up ssh access on your Media Temple Grid account.


You need to have SSH enabled on your Media Temple GS account and be able to successfully SSH into the grid service. Obviously you need to have ruby installed on your local machine, and I recommend using Bundler to manage your gems.

The Developer Setup

My goal was to use my private Git repository to run automated deployments straight from the source code. This means that my capistrano recipe and supporting files are within the project’s version control. That lead to the following project structure to keep my files out of the public folder:

-- bin/     (Contains gem executables)
-- config/  (Capistrano deployment code)
-- htdocs/  (The webroot of the project)

Generate the barebones Gemfile to manage your gem dependencies, including Capistrano:

$ bundle init

Now add the following to your newly created Gemfile

source ""
gem "capistrano", "~> 2.15"
gem "capistrano-deploytags", "~> 0.7"
gem "railsless-deploy", :require => nil

Note: I may provide a future writeup once I upgrade to Capistrano 3
Update: For Capistrano 3 support (mentioned in the comments) check out capistrano-gridserver.

Next is installing your gems and “capifying” your project:

$ bundle install --binstubs
$ bundle exec capify .

You should have the skeleton needed to flesh out a deployment recipe. The next step is to add/update all files listed in my recipe so you can set up the deployment directories in the next step. Note the environment files (which allow you to deploy to multiple environments) that will reside in config/deploy/dev.rb.

Change the following values to match your account/project:

# config/deploy.rb
set :site, "1234"
set :application, ""
# ...
set :repository, "[email protected]:myname/myproject.git"

Environments also require you to create separate config files for each environment. Based on the environment you are deploying, the respective config file will be used in that environment. In this WordPress recipe, I have:

  • wp-config-dev.php
  • wp-config-prd.php

Once you have your environment-specific configs and deploy.rb recipe saved, it’s time to run your first deployment!

# deploy:setup will install cap folders (note the dev env).
bin/cap dev deploy:setup
# Make sure it went well
bin/cap dev deploy:check
# You should see a message like "You appear to have all necessary dependencies installed"

If all went well, you are ready to rock and roll!

The Server Setup

The nice thing about doing this last for me is that I had a live site running. I was able to perfect deploying code first before finally symlinking the Media Temple defined webroot folder. Once you are ready to let capistrano take over you need to symlink the html/ folder to the symlink that capistrano created called current/.

$ ssh mt
$ cd ~/domains/
# Move static code to a backup folder in case things go wrong.
$ mv ./html ./html-backup
$ ln -s ./current/ ./html

If you plan on keeping the multi-stage stuff (which I highly suggest) then you will need to set up multiple domains (ie. a subdomain) for each environment in your Media Temple GS account. Then each environment would have a unique :application value configured for each environment:

# config/deploy/dev.rb
set :application, ''
set :branch, 'develop'

The Recipe

I am not going to go over every line of the deployment recipe featured in this article, but I will cover some unique things that needed tweaked to work with Media Temple’s Grid Service.

To get symlinks working properly relative symlinks are required. This requires overriding the deploy:create_symlink task to use a defined relative_path method to symlink paths properly. The create_symlink task points to my /htdocs folder to keep configuration and deployment code out of the webroot.

Secondly, I created a custom task redmonster:symlinks to symlink uploaded images to a shared folder so that all the releases will use the same shared folder for generated media.

Deploying the Thing

After you have verified that releases are being deployed to your Grid Server account, here is the normal workflow using the multistage configuration.

# do some work
git push origin develop
cap dev deploy
# ready for production?
git checkout master && git merge develop
cap prd deploy

Pay attention to the environment-specific Ruby files. They usually tweak things like the domain name you might deploy to and the branch that will be used in deployments. Be sure and check out the documentation for all the things you can do with capistrano.

Capistrano Plugins

As demonstrated, my recipe is using the railsless-deploy gem and the capistrano-deploytags gem for creating tags for each deploy. The capistrano-deploytags gem is completely optional, but I find it provides a nice deployment history built right into my version control system.

WordPress Stuff

To ease configuration of WordPress options in multiple environments, I define the WP_SITEURL and WP_HOME constants. This allows database syncronization later on without having to manually update these options in the database.

Here is how I do it in wp-config.php:

// ...
if (getenv('SERVER_NAME')) {
    $server_name = getenv('SERVER_NAME');
    $site_url = sprintf("http://%s", $server_name);
    define('WP_SITEURL', $site_url);
    define('WP_HOME', $site_url);

I hope this writeup was helpful, I was really excited to have working deployments. It has already been helpful. Hope you enjoyed!

Update: For Capistrano 3 support (mentioned in the comments) check out capistrano-gridserver.

11 thoughts on “Deploy apps to the Media Temple Grid Service with Capistrano

  1. Thank you for taking the time to create a recipe and write all of this. My deployment to GS would’ve been a lost cause otherwise.

    Question: everything works beautifully up until the point of where the deployed files are situated. There’s a symlink created by the cap deploy recipe that points to the releases folder -> release # -> htdocs but when I view that particular folder, only the contents of my Git repo are in there and not necessarily an htdocs folder.

    Any ideas?

    Thank you!

  2. Actually, scratch the last question: I finally realized htdocs isn’t where the git repo is (the entire folder structure listed above).

    When I deploy it seems to work just fine in terms of deployment but currently, I’m unable to view these files as if I were looking at them under /html in my browser. The symlinks seem to point in the right directions.

  3. @Raoul – thanks for trying it out. The symlinks were a little tricky, as they have to be relative to work right, but the recipe should take care of that. It might take a little digging from the command line to find out how your paths are symlinked to troubleshoot it.

  4. This is exactly what I’ve been trying to figure out how to do. Thanks for writing this up and sharing. I almost have it working, so close!

    I’m getting an error in the middle of deployment that says this (i’m blanking out my personal site info):
    [out ::] rm: cannot remove `/home/XXXXXX/users/.home/domains/'
    I really am on the edge of what I know how to do at the moment, I have next to no Ruby experience, so I’m not sure where to start to troubleshoot this. I’ll keep poking around. Any ideas?

  5. @alan thanks for sharing. I think you should start by running “cap dev deploy:check” and if you have not already “cap dev deploy:setup”. The check task should give you some feedback on what is up hopefully. You might also try removing the “current” folder from the command line and trying to run the setup task again.

  6. Success! It was all because the ‘current’ folder was already there. I deleted it and everything works great. Incredible. Thanks!

  7. Hey Paul, thanks for the article!

    I am having a bit of trouble. Everything is deploying as it should without problems but MT is throwing up a 503 error when I navigate to the actual domain. My server error log is giving me this problem:

    [Sun Feb 09 16:36:50 2014] [crit] [client] (13)Permission denied: /home/156312/domains/ pcfg_openfile: unable to check htaccess file, ensure it is readable

    The only real thing I have different from this set up is that I have my files and folders in the root (not htdocs). Any ideas?

  8. I’m using Capistrano on my (gs), but I’m using it with a Roots/Bedrock project.

    I can’t get the relative paths bit of your deploy.rb to work, I think because Bedrock uses Capistrano 3. (I’ve already posted a similar question on their Discourse.)

    You wouldn’t happen to have updated yours for v3 at any point, would you?

  9. @josh – That looks like a permissions issue. I’ve not seen that yet, you should ssh into your account and try and see what the folder/file permissions are.

    @vincent – I was planning on updating my recipe to use Capistrano 3. Capistrano 3 abstracts the Rails-ness from the default, making the railsless-deploy unnecessary. I haven’t had time to work on updating it and I don’t even know when I’ll have time right now. Let me know if you are able to convert the recipe to Capistrano 3!

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>