articles in 2014

Hyperlapse'd cycling commute (work to home)

no comments yet, post one now

My commute home from work last Tuesday. From Tottenham Court Road, heading west towards Notting Hill, via Mayfair, MarbleArch, Bayswater Road, Holland Park Road and then south towards Brook Green. Recorded with Hyperlapse at 6x regular speed for some added drama.

September 04, 2014 15:21 by

Configuration management tools, explained with a Hubot

1 comment

TLDR; I setup Hubot from scratch with a bunch of different CM tools, Ansible, Babushka, Chef, Puppet, Salt, and finally plain old Bash

Show (without the tell)

A few weeks ago I began evaluating various tools for server configuration management. Before I start, I would like to point out that this exercise was inspired by the very excellent Taste Test by Matt Jaynes.

I do not want this post to detract in anyway from the hard work he has put into his guide. If you want an in depth look at the pro’s and con’s of each tool, including insight into their different approaches, I highly recommend you grab a copy. Please consider this post more of a “show” (without the “tell”). I’ll basically be pointing to the code and letting it do the talking.

Why explain this with Hubot?

To date, I’ve dabbled a little with Puppet and I’m no stranger to what we now call ‘the devops’. In the not so distant past I’ve rolled my own one-time scripts with Bash or Ruby. Trawling past repo’s on GitHub, you might even have seen my attempt to create a CM tool from scratch, Catapult (a mash-up of Capistrano, Ruby, Bash and some best practice docs from Slicehost).

More recently I’ve had a need to evaluate the best CM tools currently available, and I’ve been waiting for any excuse to play with Hubot (GitHub’s open source extensible chat-bot). So why not combine the two?

Of course, Hubot has been carefully crafted to be easily installed on Heroku, but from scratch, it has just the right combination of setup steps to exercise the more common tasks you’d want to know for any CM tool. In summary they are;

  • Installing dependencies with a package manager
  • Installing other (not so common) packages
  • Cloning your code/project to the machine (e.g. with Git)
  • Setting up your code/project with a user/group
  • Adding configuration variables for your code/project
  • Setting up log rotation (using a templated logrotate file)
  • Service management for your code/project (e.g. with upstart)
  • Starting your code/project service running

Show me the tools!

We basically want each CM tool to install and configure Hubot (including dependencies) and start the chat-bot service running. You can find my Hubot (named Henshall), here. If you are following along at home, I’d suggest creating your own bot to work with and pushing it to GitHub.

The best place to start is with a working shell script that spells out exactly what steps are needed. Using that as a guide I can then figure out how to express each step in the many dialects and dsl’s each tool provides. I should mention that Digital Ocean, Linode or a local Vagrant setup are great playgrounds for this sort of thing.

Without further ado, I’ve placed the nessecary files and README’s right here. Each README explains the “golden path” to setting up Hubot. I should mention that a fresh Ubuntu Server (12.10 x64) was used for all machines, and at the time of writing, these setup steps were correct with the latest versions of each tool. Ymmv with other distributions and as time marches on.


A bare bones shell script. Configuration via environment variables, logrotate and upstart templates are included inline. Of course this script is not designed to be ran more than once, it is a fire and forget approach to setting up Hubot on a fresh machine.


Ansible (along with Babushka) was one of the easiest tools to use. All that is needed is a simple SSH connection to the remote Hubot machine. Simple yml files define ‘playbooks’ that configure your servers. A collection of built-in modules provide the playbook commands and templates are written with Jinja2 (a simple Python templating language).


Babushka is another simple Ruby based CM tool. It takes a test driven approach to server management, and forces you to think about the setup tasks in a nested dependency tree of ‘deps’ that each do one thing well. It a fresh opinionated approach to CM that was a joy to use.


Chef is a powerful, fully featured CM tool. Unfortunately using Chef to setup one machine, requires using 3, a chef-master, chef knife and the Hubot machine itself. It is possible to use a chef-solo machine to avoid this (but that requires learning yet another way to set things up). A Ruby DSL is used to define cookbooks and recipes. Templating is available with Ruby and Erb. Certificate signing is required before machines can talk to each other.


Puppet uses manifests and Erb templates to configure machines with a Ruby based DSL. A library of puppet modules provide the nessecary commands for manifest files. Puppet manifests are deployed via a puppet master server and again, certificate signing is required before machines can talk to each other.


Salt (like Ansible) uses a simple yml syntax to define ‘sls’ files. Again templates are written with Jinja2 (a simple Python templating language). Salt applies configuration to ‘minions’ via SSH and a salt master server.


All these tools have their own strengths, weaknesses and hurdles to overcome. I found both Ansible and Babushka the simplest to get started with, followed by Salt, Puppet and finally Chef. Setting up Hubot gave a great insight into each tool and I’ve chosen to move forward with both Puppet and Babushka in future projects. Babushka’s approach felt like a breath of fresh air and was in tune with a test-driven approach that has real added value. Puppet has a more established community and module library. It is a tremendously powerful tool and I feel like I’ve only scratched the surface.

Please throw any questions in the comments below (or via GitHub issues). Wow, I think I managed to get all the way through that without mentioning the word “Cloud”!

ActsAsTextcaptcha v4.0 released!

no comments yet, post one now

With some downtime over Christmas, I decided to give ActsAsTextcaptcha some love and release v4.0. For those not familiar with the gem;

ActsAsTextcaptcha provides spam protection for your Rails models using logic questions from the excellent TextCAPTCHA web service.

This was a much needed update and necessary to provide a fix for an urgent issue – kindly identified and reported by Jeffrey Lin (thanks again!)

A bot (using something like Mechanize) could by-pass spam protection using a fake question and answer. This was down to the gem exposing the possible answers in a hidden form field. Encryption of the answers only really helped prevent against attacks from the dumbest of spam bots. With a valid question and possible answer combo, POST requests could be constructed to appear valid and submit spam.

Using the built-in Rails session to hold possible answers between requests was a no-go too. Let’s say your app used the default ActionDispatch::Session::CookieStore. An attacker could grab a valid cookie that contained some possible answers to a known question and send that same cookie data (repeatedly) with POST requests containing spam. CSRF won’t help here either (with Mechanize) a valid token can be requested before each POST request.

So it was obvious the possible answers needed to be stored server side, and any reference to associate form requests with the answers needed to be random and dynamic (much like Rails own form_authenticity_token). I settled on using the Rails.cache, it’s available by default and easy to configure. The cache key mutates with each request and cache values only live for 10 minutes.

With this new release I took some time to refactor things a little, update the README and improve test coverage. As a nice side effect code-climate rates the gem with a 4.0 GPA.

Finally, I released v4.1 removing various hooks for Rails 2. It is 2014 now (over 4 years since Rails 3 was released) I think its time to move on.

← (k) prev | next (j) →