baylorrae.com: $ echo $BAYLORS_THOUGHTS > index.php

PHP+Capistrano+Shared Host = Easy Deployments

I wrote a Rails app that was deployed with Capistrano and I loved it. Every time I made a change, one file or a dozen, I could get all the files up in a single command. In addition, if anything was broken I could revert to the previous deploy with cap deploy:rollback.

While using Capistrano is considered a "standard" with Rails, it's something that I think should be used more with PHP as well. When I built my last website with PHP I reverted back to my FTP client deploys, and it was a nightmare. I worried about the order in which I uploaded each file and making sure I uploaded all of my changes.

I'm aware of the services like Beanstalk that let you do a git push and will move the modified files for you. But, I'm not a big fan of sharing my entire repository or giving access to my server. Plus, I'm a little cheap, especially when I know I can write my own system for free. It may not be as fancy and it may require a little more work, but I like having complete control.

The Requirement

I don't want to explain how to make deployments with Capistrano. There are a lot of tutorials on the web that do a much better job than I can. So, if you're not familiar with Capistrano, you will need to follow a tutorial. The Capistrano Wiki has quite a few resources that you may find helpful.

However, there is one modification that is far different than most Capistrano tutorials. On my shared host, I wasn't allowed to change the DocumentRoot for my primary domain. As a result, I had to create a symlink from ~/public_html to the latest release on every deploy. While it sounds difficult, it's actually very easy.

The Deployment Strategy

This is where all the magic of Capistrano takes place. It's where you get to decide what takes place and when. You can define your entire deploy strategy here and Capistrano will make sure it happens, every time.

The most important change to the default deployment is on line 38. It deletes the default ~/public_html directory and replaces it with a symlink to the latest release. A very simple command that makes the whole thing work.

The result is when I want to push the changes I made I can run cap deploy and my entire application is uploaded. I don't have to worry about individual files, and if something breaks I can always return to the previous release with cap deploy:rollback.

  • Eric Mathison

    Thank you so much for writing this up! I was trying to do exactly the same thing and this helped a ton.

    I have one suggestion though. I would replace line 44 with:
    run “chmod -R g-w #{release_path}”

    That way you will only be removing (or subtracting) group (that’s the g) write permissions (that’s the w). There is no need to set the execute bit for non directories (which is what you are currently doing).

    I only wish I had understood the purpose of your permissions modification before I spent a bunch of time trying to figure out why my server was giving me a 500 error. I eventually found the problem in my logs but I spent a lot of time before realizing that allowing group write permission would actually cause things not to work.

    • BaylorRae

      I’m glad you found it helpful, and thanks for the suggestion.

      I ran into a very similar issue on my server with the group permissions being set incorrectly. Setting the permissions to 755 fixed it with HostGator. It makes me wonder if various hosting providers require the permissions to be set differently.

  • Pingback: Wordpress Deployment with WP-Stack | My Webdev Log

%d bloggers like this: