Extending Vagrant Boxes: Creating your own Vagrant boxes

Posted by Jose Estudillo on September 6, 2017

Extending Vagrant Boxes

It’s a common case in Vagrant wanting to have base boxes that contain certain package or specific software to be able to create different type of clusters with little effort.

The most common case when using Vagrant is to specify a script that will download the software and prepare the box on startup, but this is quite inefficient, specially if we are downloading a lot of information from the internet that could be common for many of the instances.

Defining your own boxed extending from a base image

For the examples I will use CentOS (centos/7) as a base image as it is one of the most common server OS.

Defining a box using Inline script

Using the inline script capabilities is the fastest way to define what our custom box will require:

  • Vagrantfile:
    Vagrant.configure("2") do |config|
    config.vm.box = "centos/7"
    config.ssh.insert_key = false
    config.vm.provision "shell", inline: <<-SHELL
      yum update -y
      yum install -y git
    SHELL  
    end
    

Defining a box Using external script

For the cases where we need to do more complex installation, it is cleaner to create a external script and point to it from the Vagrantfile.

  • Vagrantfile:
Vagrant.configure("2") do |config|
  config.vm.box = "centos/7"
  config.ssh.insert_key = false
  config.vm.provision :shell, path: ".vagrant/scripts/init.sh"  
end

An example of init script could be:

  • .vagrant/scripts/init.sh:
    #!/usr/bin/env bash
    yum update -y
    yum install -y git
    

The location of the script can be anywhere in the directory where the VagrantFile is, but I like to keep the init scripts under .vagrant directory, so they are used the first time the Virtual machine is started, but never copied into it (Vagrant ignored the context of this directory by default).

Installing the extend box

I have noticed that the generated boxes only work correctly when the vguest plugin installed, so I advice to install it before running any of the scripts below. This can be done running vagrant plugin install vagrant-vbguest.

To install the box we will create a vagrant virtual machine that will download and install all the specified software, turn it off and package it into a box to install it in the vagrant boxes repo.

the script below can do all this steps in one go and will clean the generated files after.

BOX_ID="<your box id>"
vagrant destroy -f
set -e
vagrant up # Start the box and run any defined scripts
vagrant package --output ${BOX_ID}.box # Store the virtual machine with all the software installed into a box file.
vagrant box add --force ${BOX_ID} ${BOX_ID}.box # Add the box to the vagrant repo using the given id.
vagrant destroy -f # Stop the vagrant instance
rm ${BOX_ID}.box # Remove the file 

Once the the previous steps are completed, you can use your newly created box as base assigning the id (BOX_ID value) to config.vm.box:

Vagrant.configure("2") do |config|
  config.vm.box = "<box id>"
  ...  
end

In the next article I will show how to configure these boxes to create clusters.