Vagrant and Ansible

This week I worked through Daniel Higginbotham’s book “Deploying your first Clojure App - from the Shadows”. In this book he explains how to set up a comprehensive deployment chain with reproducible results via a use of Vagrant in combination with Ansible.

Of course he also explains how to install these tools. Strangely on my machine (Linux Mint 18.1 Cinnamon 64-bit) these commands were not enough to get my system up and running. So here the quick summary what was necessary to set me up:

What confuses me is that these tools are all registered in the package index. So supposedly sudo apt-get install virtualbox vagrant should have done the trick. But after I installed the virtualbox version my package manager suggested, even though successful, I didn’t have any executable that I could run. Consequently Vagrant failed to set up because it couldn’t find a suitable provider. Luckily VirtualBox comes with a good download guide for Linux.

What Daniel describes in his book is the following setup: Using Vagrant to manage one or more virtual machines and then using Ansible to set up the machines and perform the necessary steps to bring the application online. He does this via three shell scripts: build, provision and deploy. These scripts use the same playbook and alter behaviour via tag inclusion and exclusion.

I don’t have a lot to complain about that, because it is good pratice to use tools like Docker or Vagrant to ensure a defined state to work with and other tools to take care of deploying your application. I just found a small optimisation: Vagrant combines nicely with Ansible, so instead of maintaining an install tag and manage provisioning manually it is possible to give Vagrant an Ansible playbook to use for provisioning the virtual machine. After that calling vagrant up for the first time will run the Ansible playbook to set up the machine, but subsequent calls will not call the script again. This is probably not ideal for every (complex) setup, but for small hobby projects that is totally acceptable.

So my Vagrantfile looks like this

Additionally if you use Vagrant with Ansible in this way, Vagrant will automatically generate an inventory file, which can be reused by other Ansible playbooks. The default location is .vagrant/provisioners/ansible/inventory/vagrant_ansible_inventory. Since I specified in the Vagrantfile to be verbose when running Ansible, Vagrant is also printing the full command it uses when running Ansible, which can be easily copied to a shell script and used for a deploy script. Here is mine:

And this is the very basic directory structure for my DevOps needs:

Thus, assuming I have these files in the folder devops, all I have to do is the following: