I spent quite a bit of my day yesterday trying to work out a painless, scripted, idiot-proof deployment process with Capistrano for my photo-a-day website. I’ve been doing a lot of work on the site lately, which means a lot of deployments, and I’ve been very unhappy with myself for implementing what amounts to “deployment worst practices” when it comes to my personal projects.
The last time I worked with Capistrano was about two years ago, and a lot has changed since then. Capistrano v3 was released in June of 2013 and brought with it a lot of great changes, but for a guy who doesn’t know ruby and relies on tutorials and Stack Overflow questions for help, the version bump brought a lot of pain as well.
Challenges
Every Tutorial is Wrong
Just know going into this that (almost) every tutorial you find is going to be a Capistrano v2 tutorial. Enough has changed between v2 and v3 to make those tutorials just misleading enough to cause a good amount of pain.
Stack Overflow is a Capistrano v3 Desert
As of this writing, there are ten questions tagged capistrano3 on Stack Overflow. Seriously. Ten. And only four of those include accepted answers.
Capistrano v3 Documentation is Lacking
The documentation available for v3 is seriously lacking, although the problem is more one of quantity than quality. What’s available is good, there’s just nowhere near enough of it.
Caveat Emptor
These are indeed “Notes to Self”. I hope they help you out, but if they don’t, I’m giving you fair warning. Please feel free to add what’s missing to the comments.
Reading the Capistrano docs is highly recommended. These notes are supplemental.
PHP + Capistrano v3
NOTE: You can find the application source, which now includes Capistrano v3, on GitHub.
Ruby
First, I had to reinstall rvm, a ruby version manager. What I don’t know about installing a ruby dev environment could fill books, so I let rvm take care of that for me.
1
|
|
(Capistrano requires Ruby 1.9 or newer, so the current stable Ruby from rvm will work fine.)
Installation
Install Capistrano.
There are a few options, but I used gem install
.
1
|
|
NOTE: All of the PHP tutorials I found instruct you to install the
railsless-deploy
gem. As Capistrano v3 “doesn’t ship with any Railsisms”,
this is no longer necessary and the railsless-deploy project is obsolete.
I’ll probably go back and add a Gemfile
since I’ll be adding the composer gem and want everything I need in one place.
Preparing Your App
The capify
command is no longer, it’s now cap install
.
1 2 |
|
The documentation on this portion, “Preparing Your Application”, is one of the places the documentation shines, IMHO.
Capistrano Files
Capfile
: Kind of like a bootstrap. Takes care of necessary required configs and globs for custom tasks.config/deploy.rb
: Common items across all deployments go hereconfig/deploy/{staging, production}.rb
: Environment specific deployment settings
Roles
I’m still not 100% clear on this, but roles don’t seem to be roles in the ACL
sense, but rather roles in the “division of server responsibility” sense, hence the
roles :web
, :app
, and :db
.
The docs say that you can dump the :app
and :db
roles if you like, but if
you’re going to use the :linked_files
and :linked_dirs
feature (which are
pretty cool) you’ll need to leave the :app
role in place. I’m obviously doing
something wrong or missing something here, but that’s what I had to do.
I found it extremely helpful to refer to the deploy.rb.erb
template.
I removed most of the example text before realizing I needed to use some of it,
and referencing the template was nice.
SSH Forwarding
SSH Agent Forwarding is the way to go here, IMHO. I already had a key agent running so the forwarding was dead simple, almost like magic. If you don’t already have an agent running, here’s some good info from GitHub Help.
Server Config
The section on how to set up the proper Capistrano directories on your server is
way down deep in the Authorisation portion of the docs.
Short version: you need two dirs in the root of your project (on the server):
releases
and shared
, and they must be readable and writeable by both the
webserver and deploy user.
Getting permissions right is easy for some, but I always return to the Setting Up Permissions section of the Symfony2 docs to get them set up properly.
Making Composer Work
Once I got my deploy.rb
and deploy/production.rb
right and tested (by deploying, natch),
I needed to create a task to run composer install
.
Getting that right turned out to be pretty difficult because of a design decision
in SSHKit.
Short story: No spaces in command line commands.
I finally got my composer command running by doing this:
1 2 3 4 5 6 7 8 9 10 |
|
- The
within release
bit in the command tells the task tocd
into therelease
directory before running composer. - There are
before
andafter
hooks you can apply to the deploy flow. The final line above is a hook that runs afterdeploy:updated
.
Composer Gem for Capistrano v3
Of course, as soon as I got it working, Peter Mitchell sent me this tweet:
I haven’t yet replaced my hacked version with the gem, but I’ll use it as soon as I do any refactoring.
Deployment Annoyances
cap production deploy --dry-run
never worked for me, although cap production deploy
worked fine. No idea why, who cares at this point. Maybe I’ll dig in later.
Also, cap production deploy
really wants to run deploy:restart
, even
though it doesn’t show up anywhere in the deploy flow.
I replaced the :restart
task that’s in the default deploy.rb
template, made
sure it was empty, and deploy finally worked.
Linked Files and Directories
The :linked_files
and :linked_directories
feature is really nice. I’ve used
it for logs, a local.php
config, Twig caching, my SQLite database, and my
generated rss file. The linked items are for files and dirs that should be
shared between deploys.
Also, those files and dirs need to be present in the shared dir before deploying. Deploy will puke if they’re not present.
Capistrano Variables
I couldn’t find a listing of these anywhere, but release_path
is one of them,
and it points to the latest release path.
That’s All For Now
I hope the notes help when you get ready to write your own Capistrano v3 scripts for use with PHP. I’ll update this as I learn more, and I’ll make sure to point out any excellent point made in the comments.