Vagrant is a personal tool to automatically provision virtual machine environments. It comes for free along with VirtualBox plugin, although there are commercial plugins for other virtualization engines such as VMWare. It is a very handy tool, especially for developers: it enables them to quickly mock-up or destroy even complex virtual machine environments by executing just one command. Within this post we'll see how easily it can be installed, and how easy it is operating with it.

A tool for quickly mock-up environments

Vagrant is "a tool for building and managing virtual machine environments in a single workflow": this means that you can define a whole environment made of several virtual machines within a single manifest file called vagrantfile - the syntax of the manifest follows Ruby coding.
Vagrant processes this manifest file and executes the directives stated into the file by connecting to hypervisors using a component called provider: Virtualbox and KVM are free providers, but there are also commercial ones like VMWare provider.

Vagrant can be exploited by:

  • system engineers to mock-up virtual environments to test installation of new software or to perform proof of concepts
  • developers to easily create virtual environments with all the components necessary to perform the integration tests of the software they are developing, without interfering with anybody since the environment is isolated and local to his/hers workstation

If necessary, the vagrantfile can be shared and versioned using the company SCM and even integrated in the toolchain.

Installing VirtualBox and Vagrant

To keep on the free of charge side, and to have an easy to setup solution suitable to every platform, we install Vagrant with the Oracle Virtualbox provider:

Installing both of them is straightforward, so I think that it does not make sense to explain anything that is as difficult as hitting the "next"or  the"I agree" buttons several times.

The only thing that you must really take care of manually doing is to add VirtualBox's path to the PATH system wide environment variable.

For example, on Windows it must be set as shown by the box on the right: by doing so you are able to issue commands such as VBoxManage without having to specify the full path of the folder containing it.

Vagrant requires access to the Internet to download Virtual Machine images – these are called Vagrant boxes in Vagrant's terms. In addition to that, the operating system installed into the Virtual Machines requires Internet access to download software packages to be installed (such as RPM from online yum/dnf repositories).
If you are working without a direct connection to the Internet you should ask the administration team of your corporate proxy to grant requests to https://vagrantcloud.com/ and to the online repositories of the operating system of the Virtual Machines you want to install.
After that you should also have to install the Vagrant proxy configuration plugin – issue the following command - in this example the corporate proxy URL is http://proxy.carcano.local:8080

export http_proxy=http://proxy.carcano.local:8080
export https_proxy=http://proxy.carcano.local:8080
vagrant plugin install vagrant-proxyconf

Once installed, each time you want to run vagrant, you should export the following variables right after opening the command prompt (the shell) before running vagrant up:

  • VAGRANT_HTTP_PROXY – for example http://proxy.carcano.local:8080
  • VAGRANT_HTTPS_PROXY – for example https://proxy.carcano.local:8080
  • VAGRANT_FTP_PROXY – for example http://proxy.carcano.local:8080
  • VAGRANT_NO_PROXY - localhost,127.0.0.1,.carcano.local

Upgrading Vagrant

Upgrading Vagrant requires only downloading the new version and installing it, overwriting the old installation. If you have installed any plugin, right after upgrading Vagrant you should also upgrade them as well. You can upgrade them as a whole as follows:

vagrant plugin update

Vagrant Boxes

Downloading Vagrant Boxes

Once both VirtualBox and Vagrant are installed, and proxy has been configured if necessary, you can test your installation by downloading a vagrant box.

You can get a list of public available VagrantBoxes on Hashicorps's VagrantCloud at https://app.vagrantup.com/boxes/search?provider=virtualbox

For example, we can easily install the official centos/8 VagrantBox to our local repository as follows:

vagrant box add --provider virtualbox centos/8

This downloads the CentOS 8 official VagrantBox: it will take some time (of course it mostly depends on the speed of your connection to the Internet), so this can be the right moment to relax with a coffee or a cup of tea.

Updates of the boxes are periodically released. Updating a box is really easy: for example, to update the centos/8 box simply issue

vagrant box update --box centos/8

Although this should be straightforward, it is worth to say that the upgrade is focused only to the box itself: the VMs you already provisioned using that box do not get updated - You should use the updating commands of the guest itself to keep things up to date.

You can of course copy Vagrant boxes from another workstation (for example if you do not have a fast Internet connection, or you are paying for the amount of data you download): boxes are stored beneath the following path:

  • C:\Users\%USERNAME%\.vagrant.d\boxes on Windows
  • ~/.vagrant.d/boxes on Mac and Linux

Creating Vagrant Boxes

We can of course create our own Vagrant Boxes: despite there exist two different ways of creating Vagrant boxes, the procedure is quite simple.

Extending An Existing Vagrant Box

This is of course the most straightforward way: just light-up the existing Vagrant Box you prefer. You just need to run the "vagrant init" statement followed by the Vagrant box you want to use as by the following example:

vagrant init centos/8

the output is as follows:

A `Vagrantfile` has been placed in this directory. You are now
ready to `vagrant up` your first virtual environment! Please read
the comments in the Vagrantfile as well as documentation on
`vagrantup.com` for more information on using Vagrant.

as you see, the outcome is a Vagrantfile generated on the fly that can be used to start a CentOS 8 VM.

Let's provision and start the VM as follows:

vagrant up

and eventually login to the VM using the following command:

vagrant ssh

we are now connected to the CentOS 8 VM: skip to the "Preparing The Vagrant Box" paragraph.

The CentOS 8 image is not delivered with VirtualBox Guest additions already included. We'll see how to  attach the ISO image of the DVD, compile and install them.

Creating A Vagrant Box From Scratch

You may prefer to start from scratch, creating a Virtual Machine as you wish: simply create a VM using your favorite Hypervisor - the only mandatory condition is that a Vagrant provider for the Hypervisor you want to use. 

The most popular Hypervisor used with Vagrant is certainly VirtualBox, so I will show you how to deal with it, but since (at least at the time of writing this post) it does not support AARM architecture, I show you also how to deal with Parallels.

Create a Virtual Machine and set up it as you wish - for example using a STIG compliant partition layout.

It is mandatory to create the "vagrant" user with administrative rights, since Vagrant uses it to SSH connect to the Virtual Machines you spin up from the Vagrant Box. In addition to that, do not configure any network settings, besides one network interface with DHCP enabled at boot.

Once the Virtual Machine is up and running, log in to it and go on as described in the "Preparing The Vagrant Box" paragraph.

Preparing The Vagrant Box

The very first thing to do is update the RPM packages installed into the VM - if it is a dnf based Red Hat derived distro type:

sudo dnf update -y

otherwise, if it is an old yum based Red Hat derived distro, simply replace with "yum" the word "dnf" in the previous and in every next statement.

As soon as the update process completes, shutdown the Virtual Machine:

sudo shutdown -h now

We need now to attach the ISO file of the DVD containing the source files to build the VirtualBox Guest Additions: attaching it using the GUI is very simple, so I will show you how to do the same using the command line.

First we need to get the list of the configured VMs, so to guess the name or UUID of the VM Vagrant has just deployed:

VBoxManage.exe list vms

on my computer the output is as follows:

"centos8_default_1623083202261_27402" {c385608d-76f3-402b-ac11-cf57c49c8ec2}

if you are instead using Parallels, just type:

prlctl list -a

on my computer the output is as follows:

{d0515d56-c34f-4829-a6e8-3fa3c5411f23}  stopped      -               rocky9

we can now attach the ISO containing the guest additions DVD - the example command below is for VirtualBox running on Windows - please adjust the path to the ISO image to reflect the actual path using the syntax specific to your virtualization host.

VBoxManage.exe storageattach "centos8_default_1623083202261_27402" --storagectl IDE --port 0 --device 1 --type dvddrive --medium "C:\Program Files\Oracle\VirtualBox\VBoxGuestAdditions.iso"

of course, also Parallels have a tools DVD - the statement to attach it is as follows:

prlctl set rocky9 --device-set cdrom0 --image /Applications/Parallels Desktop.app/Contents/Resources/Tools/prl-tools-lin-arm.iso
With Parallels, in this example we are installing an AARM Virtual Machine. If you are installing an x86 Virtual Machine please attach the "prl-tools-lin.iso" ISO file instead.

we are eventually ready to launch the VM again: if you are extending an existing Vagrant box, just run "vagrant up" and then "vagrant ssh", otherwise launch the Virtual Machine in VirtualBox:

VBoxManage.exe startvm "centos8_default_1623083202261_27402" --type gui

if using Parallels, just type:

prlctl start rocky9

wait until the startup completes and then login as the "vagrant" user, then install the EPEL repository as follows:

sudo dnf install epel-release

we must now install all of the packages required to compile the VirtualBox Guest additions (or the Parallels tools) Kernel modules:

sudo dnf install -y gcc make perl kernel-devel kernel-headers bzip2 dkms
It is mandatory that the kernel-devel RPM package matches the kernel version: you can verify this by issuing "rpm -q kernel-devel; uname -r" and ensure that the version in the output of both of them matches.

Now we must mount the CD-ROM onto the "/mnt" directory as follows:

sudo mount /dev/cdrom /mnt; cd /mnt

We are now ready to compile and install the kernel module - if you are using VirtualBox just type:

sudo ./VBoxLinuxAdditions.run

if instead you are using Parallels,  type the following command:

sudo ./install

the output with VirtualBox is as follows:

Verifying archive integrity... All good.
Uncompressing VirtualBox 6.1.22 Guest Additions for Linux........
VirtualBox Guest Additions installer
Copying additional installer modules ...
Installing additional modules ...
VirtualBox Guest Additions: Starting.
VirtualBox Guest Additions: Building the VirtualBox Guest Additions kernel
modules.  This may take a while.
VirtualBox Guest Additions: To build modules for other installed kernels, run
VirtualBox Guest Additions:   /sbin/rcvboxadd quicksetup 
VirtualBox Guest Additions: or
VirtualBox Guest Additions:   /sbin/rcvboxadd quicksetup all
VirtualBox Guest Additions: Building the modules for kernel
4.18.0-305.3.1.el8.x86_64.

wait until it completes.

Now we must cleanup the VM as follows:

sudo rm -rf /var/cache/dnf /etc/sshd/*key*
sudo truncate -s0 ~/.bash_history /var/log/messages /var/log/secure /var/log/cron /var/log/dnf.*
truncate -s0 ~/.bash_history

we have completed the procedure. Let's shutdown the VM:

sudo shutdown -h now

Now we must package the VM into a VagrantBox: with VirtualBox is really easy - in this example we package it within the "centos8.box" file:

vagrant package --output centos8.box

With Parallels is a little bit more cumbersome, since you cannot get the Vagrant Box automatically created.

First shrink the size of the disk as much as possible:

prl_disk_tool compact --hdd rocky9.pvm/harddisk1.hdd/harddisk1.hdd

In this example the name of the VM is "CENTOS8".

Then create the metadata.json  file with the following contents:

{ "provider": "parallels" }

And create the default Vagrantfile that will be run generated when typing "vagrant init": the contents must be something as follows:

# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.require_version ">= 1.6.2"

Vagrant.configure("2") do |config|
    config.vm.define "vagrant-rocky9"
    config.vm.box = "grimoire/rocky9"
    config.vm.communicator = "ssh"
    config.ssh.username = "vagrant"
    config.vm.guest = :redhat
  end
EOF

We can now package everything into a VagrantBox for the Parallels provider:

tar cvzf rocky9.box ./rocky9.pvm ./Vagrantfile ./metadata.json

This completes the procedure to create the Vagrant Box for the Parallels provider.

We can now add this box to the list of installed boxes as follows:

vagrant box add grimoire/centos8 C:\Users\vagrant\Desktop\vagrantlab\CENTOS8.box
Please note that on Windows it is mandatory to specify the full path to the Vagrant Box.

Operating Vagrant

Vagrant let you provision Virtual Machines in a very convenient and easy way: these are the very basic Vagrant commands you need to know to operate it:

vagrant plugin list
list installed vagrant plugins
vagrant plugin install

install a given vagrant plugin. For example

vagrant plugin install vagrant-scp
vagrant plugin update

update an already installed vagrant plugin. For example:

vagrant plugin update vagrant-scp
vagrant plugin uninstall

removes an already installed vagrant plugin. For example:

vagrant plugin uninstall vagrant-scp
vagrant box list
list the available boxes
vagrant box add

download a box – remember that boxes are specific for a given provider, so you should specify it too. For example:

vagrant box add --provider virtualbox centos/8
vagrant box remove

delete a box – For example:

vagrant box remove centos/6 
vagrant box update

update an already downloaded box. For example:

vagrant box update --box centos/8
vagrant up
start-up an already setup VM or create it as new if it does not exist yet.
If no VM name is specified as argument the action is performed for every VM defined in the vagrantfile. For example, to limit the command to jump-ci-upa002 VM only:

vagrant up jump-ci-upa002
vagrant halt

shut down VM. If no VM name is specified as argument the action is performed for every VM defined in the vagrantfile. For example to limit the shut down to jump-ci-upa002 VM only:

vagrant halt jump-ci-upa002
vagrant suspend

Suspend VM. If no VM name is specified as argument the action is performed for every VM defined in the vagrantfile. For example to limit the suspend to jump-ci-upa002 VM only:

vagrant suspend jump-ci-upa002
vagrant resume

resume VM. If no VM name is specified as argument the action is performed for every VM defined in the vagrantfile. For example to limit the resume to jump-ci-upa002 VM only:

vagrant resume jump-ci-upa002
vagrant destroy

Destroy (delete) VM. If no VM name is specified as argument the action is performed for every VM defined in the vagrantfile. For example to limit the destroy to jump-ci-upa002 VM only:

vagrant destroy jump-ci-upa002
vagrant snapshot list

list available snapshots for a given VM. For example

vagrant snapshot list jump-ci-up3a001
vagrant snapshot push

create a snapshot for a given VM. For example

vagrant snapshot push jump-ci-up3a001
vagrant snapshot restore

Revert a VM to the specified snapshot. For example:

vagrant snapshot restore jump-ci-up3a001 push_1607852325_7783
vagrant snapshot delete

Delete the specified snapshot for the given VM:

snapshot delete jump-ci-up3a001 push_1607852325_7783

Footnotes

Vagrant is certainly a great tool that every professional should be skilled on, since it is dramatically useful to quickly mock-up things. This post is just an operating cheat-sheet: to really exploit the power of Vagrant you should be able to develop vagrantfiles, but this will be the topic of another post.

Writing posts for this blog takes hours. I'm doing it for the only pleasure of sharing knowledge and thoughts, but all of this does not come for free: it is a time consuming volunteering task. This blog is not affiliated to anybody, does not show advertisements nor sells data of visitors. The only goal of this blog is to make ideas flow. So please, if you liked this post, spend a little of your time to share it on Linkedin or Twitter using the buttons below: seeing that posts are actually read is the only way I have to understand if I'm really sharing thought or if I'm just wasting time and I'd better give up.

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>