Bashtard v2.0.0

Bash Bashtard FreeBSD GNU+Linux — Published on .

A little over a year ago I started on a project to create my own configuration management system. I’ve been disappointed with existing alternatives, such as Ansible, on the grounds that they don’t work all that well if you have a mix of different distros with different package managers, and sometimes even different paths to store data in.

I’ve been having a lot of fun working on it, since the limitations I’ve put on it result in having to solve some problems in different ways than I would in a full-fledged programming language. These limitations also keep things pretty simple, and ensure that most of the features I have worked on need little to no additional effort to run on all the different systems I use for my computing needs.

And now, a year later, I feel confident enough about a new release. There’s some small backwards incompatible changes, so a new major release version is the way to go. Bashtard v2.0.0 is now available. There are a few big things that I want to go into a little bit, but you can also find a full list of changes in the changelog included on the release page.


After using the templating features I wrote about last month, I’ve decided to not include it into Bashtard. I am not convinced after using it in practice that it adds enough value to warrant the size of the added code, and hassling with two licenses instead of one. I am still very much open to the idea of a good base templating engine, but for now you can always install jinja2 or something on the target machine, and call that manually. The new playbook_path() function should make it easy to generate the path to your playbook’s files.

Additional $BASHTARD_* vars

Apart from having a new key in $BASHTARD_PLATFORM called init, there’s a completely new variable in this version: $BASHTARD_PLAYBOOK_VARS. Currently, it’s only used to set a given variable as required, but can be extended in the future with other kinds of checks. This allows playbooks to define some data to be required for it to run, and have it refuse to run if those are not supplied, rather than having to manually check them when the playbook runs. This is mainly intended for use with playbooks you intend to share, so that other people can get reasonable feedback as to what they need to configure, vs what they can configure.

Re-usable playbooks

So let’s talk about one of the more important updates to Bashtard. At least, in my opinion. How playbooks are being used has been altered slightly, in order to allow a little easier re-use of them. I consider this a very important feature of any configuration management system, the ability to share your playbooks with others easily, and being able to use other people’s playbooks with minimal effort. This greatly reduces the barrier to get started, and encourages people to show off what they’ve made.

The current implementation is built upon git submodules, and the bashtard pull command will take them into account. Perhaps I’ll add an import subcommand in the future to abstract the git submodule effort away, as I know that many people find it difficult to work with. However, since git is already ingrained in Bashtard, this addition keeps dependencies low, and allows me to keep the complexity out of the Bash code.


Having re-usable playbooks introduced the need to have a place for data that is important to my setup, but completely useless to someone else’s setup. For this, the data.d directory was added. You can store information that should be preserved across sync runs on your machines, but are not a good fit to keep in the actual playbook itself. I personally use it for my vpn-tinc playbook to keep the host files in.

Another use-case for this directory is without a playbook at all. You can put a regular directory in it, and symlink to it from a host system to keep a given directory in sync across all your machines. In my case, I have an etc-nixos directory in my data.d directory. On my NixOS system I have a symlink from /etc/nixos to /etc/bashtard/data.d/nixos. If I ever continue with NixOS, I can have this on all systems, and share any .nix files across all machines.

Binary packages!

Lastly, I’ve written about Laminar before. I’m still using it, and I’m still very happy with its simplicity. Since setting it up I’ve added jobs to verify my Bashtard code with shellcheck, and if it passes, it’ll queue up additional jobs to create a .tar.gz distribution and a .deb distribution. I hope to expand this to also generate binaries for use with Alpine, FreeBSD, and Archlinux. I’ve recently set up an S3-compatible object storage,

Additionally, I’ve recently set up an S3-compatible object store, which Laminar should push such artifacts to immediately. This will simplify new releases of any software, and offload this kind of storage to an actual remote server, rather than hosting directly from my desktop.

Wrapping up

All in all, I’ve been very happy with Bashtard so far, and I’ve been having a lot of fun working on it. I hope to be able to continue working on it and making it even better that it is in this release.

Thanks for reading, and perhaps even using Bashtard!