So, for the last 6+ months, I’ve had one major elephant on my plate. The eating has been slow, and honestly not very delicious. But something happened yesterday. I realized I had finished.
The proverbial lights came on and I understood Capistrano. I didn’t really like it. But it finally and suddenly made sense after having been a constant irritation for so long.
Capistrano is a deployment system for rails applications. On the tin, it says it can “easily be used to deploy any language” but they’re just kidding themselves. It’s a tool written in ruby meant to deal with the hassles of ruby website deployment. To a non-ruby developer (or more accurately, a non-rails developer), it is so much incomprehensible smoke and mirrors.
I’ve been a programmer for 25 years. I’ve been using Linux for about 20 years, professionally for about 15. I’ve been tinkering with ruby off and on for 5. I’ve recently started teaching my daughter ruby as her first programming language. I should really have been able to figure out this stupid tool much more quickly than this.
I think the bulk of my mental block stems from the way in which I was introduced to Capistrano. Last year, I started at a new job where the head of IT had been using cap to deploy all of our rails apps in ways I did not agree with 100%. There wasn’t anything wrong with what he was doing and it makes plenty of sense. It’s just not the way I’d ever done it myself.
He told me about how cap worked, and explained that we were transitioning between cap 2 and cap 3 – which in the grand tradition of all things ruby is not a backwards compatible change. But before he left the company a few months later, he never explained how to actually bootstrap capistrano on a new system.
One of my first assignments was to make a production environment for an application that one of our rails devs was writing. Staging already worked fine, so I just had to reproduce things with more resources, etc… or so I thought.
There was too much noise.
If I had been a rails developer for a living, I would have been better prepared to sort through the noise. But alas, I was not. I’ve used plenty of ruby over the years for small projects here and there – and for one very large project quite a while ago. But never had a need to use rails itself for anything.
The problem with any web framework is that it is, by necessity, a whole bunch of code sitting in your project written by people who aren’t on your current team. It’s like inheriting a hopefully well documented legacy project along with some outdated contact information from one of the original authors.
Over the years, I have deployed a lot of PHP and Java web pages/applications. I’ve done it by hand and with the assistance of deployment tools. It all makes sense to me.
With PHP, you deploy the source code and assets to a directory accessible by your php interpreter and tell the web server how to reach it. PHP and the web server have config files of their own. The site typically also has its own config files which tend to be clearly labeled as such.
With Java, you deploy a single file that contains all of your compressed assets where your servlet engine of choice (let’s say Tomcat) can see it. The application’s configuration is usually baked into the bundle that you deploy. Tomcat has its own config files separate from the application’s source tree. You run Tomcat, and it serves the website. You then put a real web server in front, similar to how you would with a PHP site.
Ruby… kind of straddles the line between these two, and it hands an additional wrench to the monkey. Rails applications are deployed as source code like PHP. They run a dedicated application server like Java. However, unlike with Java, that application server IS the rails app. You invoke it directly, and it runs itself. This means that app server and application configuration files are kind of mixed together – and it’s hard to tell where one aspect of things ends and another begins.
Ruby also typically makes the general assumption that the application itself will install its own dependencies. Whereas with PHP and Java, you must often install various libraries separately to support their execution – ruby apps ship with dependency lists that you can easily invoke to install everything automatically. So there’s that extra deployment information bundled in with everything else.
So, to recap. To deploy a rails app, you install ruby on a box. You then install one extra utility for ruby that doesn’t ship with it. Then you upload your source code to the server and run that tool. This will go out to the internet and fetch and install all of your dependencies (ala pecl or cpan). Then you can launch the application itself. Then you tell the web server where to find the ruby app just like with anything else.
This is all sane enough, it’s just a different ordering from the other languages. Capistrano gives our monkey a third wrench to hold (in its tail, I guess?). Instead of deploying the application to a self-contained directory, cap starts making symlinks around. It versions subsequent deploys of your app (ostensibly to make rollbacks easier).
There are a lot of symptoms of version paranoia here (yay for abandoning backwards compatibility). When cap runs its bundler install, those libraries aren’t installed system wide, they go into an unprivileged application specific location. This would allow you to run different versions of the same library across multiple applications but makes for a major headache trying to find things if you don’t launch the app just so.
Hang on, one of my programmers is having issues with a Capistrano deploy not making one of the symlinks it was supposed to…
30 minutes later…
The problem was because I originally set things up while referencing information from conflicting versions of various tools. Two config file entries later, he’s back and working and I have more grey hairs because of Capistrano.
Seriously. That just happened while I was trying to rant about versioning and documentation. Things like this would not fly anywhere else.
The only real problem with Capistrano is that it is a Rails tool written by Rails developers for Rails developers. They make a lot of cultural assumptions and subsequent shortcuts. It is not very accessible to those of different cultural backgrounds.
Because cap v2 and v3 are different and the internet is forever and because people are lazy, it’s easy to read incorrect documentation that doesn’t remember to identify which versions of tools it applies to.
Because ruby applications ship with so many different moving pieces all jumbled together in one big fat directory, it is impossible for the uninitiated to identify where config files for one of the myriad components end and where the configs for another begin.
Because I inherited an existing project, the SNR was practically zero.
And don’t even get me started on how Capistrano demands passwordless sudo…
I’m sick and fed up with it all, and it’s one of the best tools that I’ve ever had the misfortune of using.
Now I get to go back and add God to the mix before collecting my thoughts and attempting to write a useful tutorial for general Linux admins to get up and running with Capistrano.