Three years of Tiller


Note : This page may contain outdated information and/or broken links; some of the formatting may be mangled due to the many different code-bases this site has been through in over 20 years; my opinions may have changed etc. etc.

On July 18th, 2014 - 3 years to the day of writing this post - I pushed the first public code of Tiller to Github. Back then, it was just a simple little tool that I wrote (mostly as a learning exercise), found useful and thought others may like to use.

Since then, there have been:

  • Nearly 60,000 downloads from
  • 575 commits
  • 244 stars on Github
  • 54 releases
  • 52 issues closed
  • 16 new plugins created
  • 11 pull requests from other developers
  • Over 2,000 lines of documentation written

And countless emails, comments and discussions on the chatroom.

I’d be the first to admit that it’s certainly not the best code you’ll ever see, and in terms of project size it’s tiny compared to some of the other things you’ll see hosted on Github. But something that was once solely mine has clearly resonated with others (The 1.1.0 release actually contained more of other people’s code than my own changes!), spawned a community and has found a place as a building block in projects I’d never have imagined, from people I’ve never even met.

It’s a feeling I didn’t expect to experience outside of my musical endeavours. As when I’ve slaved over a mixing desk for days or spent hours trying to perfect a bass riff, it’s been a labour of love. For me, it’s the same nerve-racking sensation publishing a mastered musical track, or pushing a new code release to I find myself second-guessing my decisions every time, and - despite working on these things because it’s like an itch I have to scratch - I can’t help but wonder whether anyone will like what I’ve just created.

Just like making music, I strongly believe that code can be an art form. It’s something that ends up reflecting a little of yourself - and whatever your endeavours, you’ll only ever get better at as you continue, receive helpful criticism and words of encouragement.

So here we are, 3 years later from that first tentative code push. It’s immensely satisfying to see a community spring up around this little tool, and I want to take a moment to thank everyone who has ever emailed me, submitted a bug report, come up with suggestions, submitted code or otherwise joined in helping this project fill a niche. You’re my encouragement to keep up with this project, learn more, grow as a developer and above all - keep having fun!

Recent updates

Anyway, enough of my meandering musings.. It’s been quite a while since I last posted about Tiller, but that doesn’t mean things have been quiet! On the contrary, development is busier than ever and there have been a lot of new features and improvements added over the last year. There is of course the Changelog where you can see all these updates, but I thought I’d take the opportunity to provide a quick round-up of some of the highlights.


Tiller 0.9.0 was released on the 10th of August 2016, and the 0.9 series included a lot of new features and some nice improvements:

Precedence changes

In previous versions of Tiller, global values were merged together in the order that plugins were loaded. Then, the same was done for template values. Finally, template values were merged over the top of global values. As had been discussed in the Gitter chatroom many times, this led to some counter-intuitive behaviour! Starting with Tiller 0.9.0, the behaviour has now been greatly simplified.

We now go through the plugins in order, and for each one we merge template values over global values, then proceed onto the next plugin. To put it simply: A template value will take priority over a global value, and any value from a plugin loaded later will take priority over any previously loaded plugins.


The 0.9.x series also saw two “Vault” plugins. The first supports Hashicorp’s Vault product and was provided in an awesome Pull Request including test cases and documentation from the fantastic liquid-sky.

The second plugin adds support for Ansible Vault - a simple way of encrypting a YAML file and passing it into a Docker container. I’m particularly fond of this plugin as it means it’s trivial to ship a safely encrypted set of YAML values or credentials inside your container, and unlock it at run-time. Even if you’re not using Ansible for orchestration or configuration management (and you should!), Ansible vault is simple to use:

$ ansible-vault create my_secret_vars.yaml
Vault password: <enter password here>

And that’s it! You can then edit the file with ansible-vault edit and bundle it into your container. See the plugin documentation for more examples.


Tiller 0.9.5 added support for merging configuration in a config.d directory structure (and 0.9.6 improved it). This was another simple change suggested by a user (thanks, rafik777!) but means it’s easier now to create layered containers and split configuration out over multiple files.


The big 1.0.0 release! This marked the start of using semantic versioning, and as always, a big priority is never to break existing installs. I now strongly recommend a modern Ruby installation (see the requirements page for more details) but will continue to test on older installations.

Apart from some nice new features such as exec on write and dynamic values, the big highlight for me of this series so far is the 1.1.0 release. As I mentioned above, for the first time since I started this little project, I made a release with more of other people’s changes in it than my own code!

The future

There’s several new features coming in future releases, and I’ve already started to lay the foundations for plugin versioning. This means I (and other plugin authors) can experiment with new features or radically alter the internal workings of Tiller without breaking compatibility with existing installations. The first thing that will use this will be a new feature to specify multiple “targets” per template. So you’ll be able to do something like this:

      - target: /etc/httpd/sites_available/my_site.conf
        user: root
        group: httpd
        perms: 0644
          site_name: "My site"
      - target: /etc/httpd/sites_available/other_site.conf
        user: root
        group: httpd
        perms: 0644
          site_name: "My other site"

… and so on. As always, feel free to submit an issue, join the chatroom or send me an email with any suggestions or improvements you’d like to see. And keep having fun!