Saturday, 5 July 2008

Using capistrano to deploy a python application

At weListen we have a small python web application that we use as a time tracker and status keeper. Something akin to twitter, but with less social and more tracking. It lives in a Linux server together with a couple of our other services, and tends to be something I work on from time to time to improve small details or to fix small bugs.

Now, most of the time the development of this app is rather iterative. I think up of something new to try or a small improvement, code it on my local workstation, test it with live data taken from the production environment and if I'm happy with the results, I commit the change and deploy it on the production server. It's a small app, with a couple of services running, so the upgrade protocol is direct. It is still a couple of steps, and sometimes I tend to forget one of them (usually the one where I refresh the source code from subversion).

So, that looks like a good excuse to try out capistrano, of which I've heard many things, mostly coming from the ruby on rails community.

In a nutshell, what I wanted was for a library to take care of the connection and execution of commands on remote servers with minimal fuss. And that's what I got.

The Good

After installing the one click version, ruby was setup and ready to go. The gems library was already included, and installing capistrano was a matter of invoking the stanza featured on the project's home page.

Creating a script to perform the same steps I previously did manually was straightforward enough, and rather "obvious", apart from the trick to get sudo not to complain:

task :update, :hosts => "<server>" do
  default_run_options[:pty] = true # required so that sudo doesn't complain
  run "svn update ~/<directory>"
  sudo "/etc/init.d/<service 1> restart"
  sudo "/etc/init.d/<service 2> restart"
end

The server can use the standard username@host:post format, and the ssh framework plays nice with pageant, making passwordless logins updates real easy.

The Bad

No documentation, apart from a getting started tutorial, which is completely geared to deploying ruby on rails applications according to their methodology. Both seem to be a known problem, as a quick Google search for "capistrano documentation" gives us some pages with a call for help, and a mailing list post for it, and the getting started page warns us about it being devoted to ruby on rails.

Still, It leaves the rest of the world in the dark about how to use cap to deploy other kind of applications. Also, there isn't much in the way of explaining what is their methodology, and how can a user skip or customize some of the steps.  I ended up just running the commands with no automatic error checking. Which works for now, but leaves me a bit unsure as to how solid it is.

The Ugly

Since I use a private/public key combo to login to the server with a non-root user (standard Linux sysadmin practice), and sudo requires a password by default, the script didn't work out as well as I wanted it to be on the first try. I could either type the password each time I wanted to deploy the app, get ssh to pass through my private key from pageant to sudo, or tell sudo that the services don't require a password.

I ended up compromising and going with the last choice. It means that an attacker which gains access to the server via the normal user can restart the services and do a bit of damage, but if he's already inside, then a couple of services going down is the least of my worries.

Conclusion

If I already had ruby installed, adding capistrano to the list of dependencies is not a big deal. The library is small and easy to install using gems. The problem was simple, and with the right tools the solution was equally direct. The lack of documentation wasn't that big a deal, but mostly because the problem was small.

Sadly, capistrano is the only reason for me to have ruby installed, so far, making the dependency a large and difficult one to explain. I might have a look in the future for python based alternatives.

Also, I'm starting to wonder if I could use the idea behind capistrano to deploy windows based applications. The biggest problem would be the remote connection, but I believe that Windows Server 2008 already has some support for console based remote connections. If this were possible, deployments could be more easily automated, which would most likely reduce the overhead of getting a new version of a web based application live.

No comments: