This post appeared originally in our sysadvent series and has been moved here following the discontinuation of the sysadvent microsite
Personally, I consider the script parameter in a Vagrantfile
to be a
feature that is not abused enough. It’s got a lot of potential - every
script can have a parameter (or several). Modifying your Vagrant use
to include this gives you a more flexible and reliable way of quickly
deploying some test nodes.
That automation thing
While juggling around with Vagrant and provisioning boxes for the local test environment - which certainly is a lot of fun - I found myself deploying the same scripts on new hosts all the time. Even worse: when being lazy I just quickly installed the necessary tools manually.
When I repeat a certain task often enough, it crosses a border where it gets annoying. Annoying enough to be dealt with (that border is quite low actually). And I’d like to spend that time rather doing something else.
The idea is that a few small scripts could customize and
generalize the installation of components on vagrant nodes very
quickly - in the same way every time. Vagrant provides support for
this through the script parameter in the Vagrantfile
. By running
scripts like this on a newly provisioned host, we can do pretty much
anything we want with only a basic knowledge of bash.
These scripts are just quickly whipped together to deal with the repeating steps involved in repeatedly creating hosts with similar configurations. It is way below the level of complexity or capability of what you get with larger Configuration Management tools like Ansible, Chef and Puppet. At a certain level of complexity and with certain requirements, it might make more sense to integrate these tools instead of using custom scripts. But the simplicity of this solution might make it easier for beginners to reach at least some level of automation without diving into the deep waters of the full-blown configuration tools.
All of the code is available at GitHub, with examples.
The scripts
In the Vagrantfile
, the following lines should look familiar:
client.vm.provision :shell,
path: "some_script.sh",
:args => [ "arg1", "arg2" ]
They basically pass a script including parameters to Vagrant and run the script on the host.
And this can be abused.
The structure
For this example the local Vagrant installation is combined with a VirtualBox. The basic principles are easy to understand and can be used in other setups.
- boot.sh
- The core of the setup is the file
boot.sh
. It handles all parameters and includes all the necessary files. (You’ll find this file and all of the other files included in the in the Git repository mentioned in the beginning and at the end of the article). The script parses parameters and controls the order in which optional updates, host files and other installations take place. It is also responsible for including theid_distro.sh
. - id.distro.sh
- Then there’s Santa’s little helper:
id.distro.sh
. It provides some basic id-ing of the distro and allows other scripts to use the right distro-specific commands. If you need to support another distro, add specifics in this file. - host_update.sh
- The
host_update.sh
, does what you’d guess from the name - it updates the installed packages on the system. - bs.<fqdn>.sh:
- host
specific installation files can run any kind of custom command on the
host-level. They need to be named following the pattern
bs.<fqdn>.sh
. - install_tags.sh
- The install_tags.sh file handles the tags structure. These are basically directories with init-files. These init-files install a component on a host, they are not System V init-files. I usually use this like you would use Puppet Modules or Chef Cookbooks and either install and configure a single component or multiple (E.g. syslog, nfs-server, dhcp, etc.). By just including the tags as parameters, we include these automatically in the bootstrap process.
The name of the directory must be identical to the tag to use, e.g. the
tag webserver will trigger the file ./webserver/init.sh
. In the
example code you’ll find a setup for a (very basic) web-server
installation. Also in the example: the directory tools
and the
required
init.sh
,
which installs some generic basic tools.
./hosts/bs.u1404.example.com # Hostfile for host u1404.example.com
./tools/boot.sh # The Main process
./tools/host_update.sh # Update script
./tools/id_distro.sh # Santa's helper
./tools/init.sh # Tools-init script (install-tag)
./webserver/init.sh # webserver-init script (install-tag)
- boot.sh pulling it all together
- The initial script called from
Vagrantfile
is theboot.sh
script. It starts by parsing parameters and gathering general information and then sets some environment variables.
-
If the hostname parameter has been set as well, the specific host-file is included and included commands are executed.
-
Then the rest of the installation tags are run, installing specific tools or more general applications.
An example
Depending on the parameters given in the Vagrantfile
, the hosts will
be setup differently using the method described above.
Node 1
The following Vagrant configuration will
- Upgrade all packages on the host
- do nothing else (because the example setup does not provide a
bs.plain.example.com.sh
bootstrap file)
host.vm.provision :shell,
path: "bootstrap/tools/boot.sh",
:args => [
"-h plain.example.com",
"-u"
Node 2
The following Vagrant configuration will
- Upgrade all packages on the host.
- Install a web-server.
- Install custom tools
- Run the commands in
bs.u1404.example.com.sh
.
host.vm.provision :shell,
path: "bootstrap/tools/boot.sh",
:args => [
"-h u1404.example.com",
"-u",
"-i webserver",
"-i tools"
Future improvements
As always, there’s still some space for improvements:
-
Support more distributions, and make the scripts as distro agnostic as possible.
-
The code structure could probably require some restructuring.
The code is available at GitHub, and I would love it if you play around with it and send me pull-requests if you improve or extend ‘vagrant-lazy’.
The irony of insecure security software
It can probably be understood from my previous blog post that if it was up to me, I’d avoid products like CrowdStrike - but every now and then I still have to install something like that. It’s not the idea of “security software” per se that I’m against, it’s the actual implementation of many of those products. This post lists up some properties that should be fulfilled for me to happy to install such a product.