Vagrant is not a new tool in the utility belt of dev-ops engineers but for the uninitiated the vagrant website briefly describes vagrant as a means to:

Create and configure lightweight, reproducible, and portable development environments.

To explain this, imagine a development team in which developers use Windows PC's, Macbooks or a Linux distribution. Now imagine the server - which is where the code they are all working on would run - is completely different from anything any of the developers is running. Chances are that after the push to the live server, everything goes well and all the bells and whistles work when and how they are supposed to. There is however a possibility that something goes wrong, not because the code is necessarily incorrect but because a difference in live server configuration and that on the local machines introduced a bug which would never have come up in any of the tests. Vagrant provides a solution to this problem by letting you configure your expected server environment and package it in a redistributable form for all members of your dev team. That way each developer is able to code - despite using different operating systems - in a setup that matches what you'll be running in production. This solves the all too common 'but it worked on my computer' problem.

The Vagrant website has a nice getting started tutorial but this article focuses on building your own vagrant box. A vagrant box is the product of the packaging and configuration which vagrant promises. There are alot of pre-configured boxes available here but sometimes what is available either does not meet your needs or perhaps contains packages that you do not need (which makes the size of the box even larger and less portable). We'll build a vagrant Debian box which has the all the components of a LAMP stack installed, which should be useful for many PHP applications.

Choose your Provider

Providers alongside boxes are a major backbone of the vagrant process. Providers server as a sort of bridge between vagrant and your own computer (if you're running the box on your locally). Vagrant ships with support for Docker, Virtual Box and Hyper-V. But with additional plugins you can enable providers for VMWare, AWS, etc. We'll be using Virtual Box in this tutorial. Apart from being supported out of the box, it is free and easy to setup. If you don't have virtualbox installed already, pick it up here and comeback after the installation.

Pick your Operating System

Picking the operating system of your box depends strongly on your requirements. As mentioned earlier we'll be using a Debian operating system, specifically version 8.3. In choosing yours, if you already have a live environment then you should choose an operating system that matches it as closely as possible. You can pick up the iso for Debian 8.3 here.

Install Vagrant

Erm yeah, this was a no brainer =D. Download the appropriate version for your operating system here and install it. That's all. End of step 3

Setup your OS on Virtual Box

Now the fun part begins. We'll need to install the operating system on virtual box to begin with. Go ahead and create a new virtual machine. if you've been following this tutorial:

  1. When asked for the version of the OS, choose Linux and Debian 64 bit.
  2. Next select a memory size of 512 MB (you can go higher or lower depending on what you're running). If you've used Digital Ocean before then you'll see that we are using similar specs as the $5 droplet they have on offer.
  3. Create a dynamically allocated virtual hard disk with a Virtual Disk Image (VDI) file type and 20GB in size. Making it dynamically allocated means it takes up only as much space on as it requires up to 20GB.
  4. Since we would be running this machine in a headless mode, we'll disable some settings which are not needed. Go into the settings section for the machine and disable the audio and usb controllers.
  5. Now attach the iso previously downloaded to the Controller IDE in the storage settings section.
  6. We can now run the virtual machine. Follow the instructions on the screen to install. In this example the following settings were used:
  • hostname: mobnia-base
  • domain: mobnia.com
  • username: mobnia
  • partitioning method: use entire disk,
  • partitioning scheme: all files in single partition
  • You should also create some swap space while partitioning the hard disk. A swap size of 1GB should be okay
  • When asked to use a network mirror, select no, this would prevent the installation of packages which might be unnecessary

With that done we have a Debian virtual machine we can boot into. Let's move on!

Configure your OS

Even though we have our machine running, it's not quite helpful if we don't have the needed software running on it. So we'll start by setting up the sources for the Debian machine.

P.S: You'll need to login as root

sudo echo "deb http://http.debian.net/debian jessie main
deb-src http://http.debian.net/debian jessie main
deb http://security.debian.org/ jessie/updates main
deb-src http://security.debian.org/ jessie/updates main
deb http://http.debian.net/debian jessie-updates main
deb-src http://http.debian.net/debian jessie-updates main" > /etc/apt/sources.list

Next you run an update

apt-get update

As stated earlier, the plan is to get our vagrant box ready with the missing components of the LAMP stack. So let's go grab those

apt-get install --force-yes -y apache2 php mysql-server mysql-client

While that is running, you might be asked to enter a password for the mysql root user. Once it's done you've got yourself a debian machine running mysql, apache and php.

The next step would be prepping our machine for packaging as a vagrant box, but before that we need to configure a user who has sudo access and can get sudo access without using a password. Vagrant expects this user to be called vagrant by default but it is possible to change this. Typically when setting up the debian machine, you should have been asked to set up a user but for the sake of completeness we would create a vagrant user which is what would be used by vagrant.

adduser vagrant

Fill in the required information (password, name, etc). Now add the user to the sudo group:

usermod -aG sudo vagrant

Now we need to make sure that this user is able to become sudo without using a password. To do this run:

visudo

and append this line to the file: vagrant ALL=(ALL) NOPASSWD: ALL

You can check that you don't need a password to switch to sudo by running these commands:

# swtch to the vagrant user
su - vagrant

# become root (this should not require a password)
sudo -s

# return back to root
exit && exit

Finally we'll want to install the virtual box additions for our machine.

apt-get install linux-headers-$(uname -r)

Using the virtual box GUI, click the insert the guest additions menu and mount the CD like so:

mount /dev/cdrom /media/cdrom
sh /media/cdrom/VBoxLinuxAdditions.run

Prep Box for Packaging

Now that we have our vagrant user and our desired packages, we can now begin the more vagrant specific parts of our mission.

Typically while using a vagrant box, the machine itself runs in a headless mode which means that communication to the box is via ssh. So we'll first have to setup an ssh access to the box. Vagrant has a default (but insecure - since everyone uses it) public key which lets vagrant ssh automatically into any vagrant box. This is what we would be using, If you are configuring this for your team then you'd best want to use a more secure option.

mkdir /home/vagrant/.ssh
chmod 700 /home/vagrant/.ssh
cd /home/vagrant/.ssh
wget --no-check-certificate 'https://raw.github.com/mitchellh/vagrant/master/
keys/vagrant.pub' -O authorized_keys
chmod 600 /home/vagrant/.ssh/authorized_keys
chown -R vagrant:vagrant /home/vagrant/.ssh

The guide provided by Mitchell Hashimoto on building your own box suggests that to avoid possible errors it is best to clear the udev persistent-net rules.

rm /etc/udev/rules.d/70-persistent-net.rules
mkdir /etc/udev/rules.d/70-persistent-net.rules
rm -rf /dev/.udev/
rm /lib/udev/rules.d/75-persistent-net-generator.rules

The final prep we'll need to make is one which minimises the size of the box. Remember that this whole process was inspired by a need to create a light weight box with the minimal software included hence having a large sized box would not help our cause. In this finall step, we'll use the linux utility dd to reduce fragmentation in the box. Note that this should be the last step before packaging.

dd if=/dev/zero of=/EMPTY bs=1M
rm -f /EMPTY

This command basically fills your virtual machine's hard disk with zeros and then deletes the file containing the zeros thereby reducing any fragmentation.

We are now set to package!

Packaging the Box

With our virtual machine installed with the required software, we can package it. In vagrant speak, packaging converts a virtual machine into a vagrant box.

vagrant package --base debian-8.3

Where debian-8.3 is the name of the virtual machine we created at the beginning (do change this to the name of your virtual machine).

Once this is finished, you'll have a vagrant box ready to be imported into your next project or if you just want to spin up a quick virtual machine for a test.