Vagrant Introduction

Vagrant is a command line utility for managing the lifecycle of virtual machines.

Installation

Vagrant can run on top of VirtualBox. You need to install VirtualBox first. go to https://www.virtualbox.org/wiki/Linux_Downloads and Install VirtualBox first.

Download Vagrant package to Install in Ubuntu

1
$ curl -O https://releases.hashicorp.com/vagrant/2.2.14/vagrant_2.2.14_x86_64.deb

Once .dev file is downloaded, install it

1
$ sudo apt install ./vagrant_2.2.14_x86_64.deb

To verify the installation is successful

1
$ vagrant --version

Start a Virtual Machine

Create a directory and cd into the directory

1
$ mkdir vagrant-project && cd vagrant-project

To start a vagrant virtual machine, you need to first set the box we want to use. Boxes are the package format for Vagrant environments. A box can be used by anyone on any platform that Vagrant supports to bring up an identical working environment. There are many boxes available. You can search for the boxes in https://app.vagrantup.com/.

Initialize a new Vagrantfile and specify the box you want to you. In this example, we will use ubuntu/bionic64 box.

1
$ vagrant init ubuntu/bionic64

The generated Vagrantfile contains a lot of comments to help you configure the Vagrant file. Without the comments, the Vagrantfile looks like this

1
2
3
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/bionic64"
end

Run vagrant up to create the virtual machine

1
vagrant up

Output

1
2
3
4
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'ubuntu/bionic64'...
==> default: Matching MAC address for NAT networking...
==> default: Checking if box 'ubuntu/bionic64' version '20210305.0.0' is up to date...

To ssh into the newly created machine

1
$ vagrant ssh

To stop the vagrant machine

1
$ vagrant halt

To stop and delete all traces of the vagrant machine

1
$ vagrant destroy

Synced Folders

You can sync a folder on the host machine to the guest machine. By default, Vagrant share the project directory to /vagrant on the guest machine. You can add more share directory using synced_folder method.

1
2
3
4
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/bionic64"
config.vm.synced_folder "../data", "/vagrant_data"
end

Networking

Vagrant allows various networking options to access the guest machine from host machine.

Port Forwarding

In the example below. Access to host machine’s port 8080 will forward to port 80 of the guest machine. Note that this allows public access.

1
config.vm.network "forwarded_port", guest: 80, host: 8080

Here is another example of port forwarding but only allow access from host machine.

1
config.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.0.0.1"

Private Network

Create a private network. Only host can access the guest machine using this specific IP.

1
config.vm.network "private_network", ip: "192.168.33.10"

Public Network

Create a public network to allow public access. You can ssh into the guest machine and then use ifconfig to get the public IP address of the guest machine.

1
config.vm.network "public_network"

Provisioning

Provisioners in Vagrant allow you to automatically install software, alter configurations, and more. Provisioning automates the tedious process of software installation so you can quickly start working once the virtual machine is up and running.

Provisioning happends when

  • vagrant up command is executed to create the environment.
  • vagrant provision is used on a running environment.
  • vagran reload --provision is called to reload the environment.

You can provision using shell script. Here is the example to do apt update and install apache2 packages.

1
2
3
4
5
6
7
8
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/bionic64"

config.vm.provision "shell", inline: <<-SHELL
apt-get update
apt-get install -y apache2
SHELL
end

Each provisioner has a type. the above configuration use "shell" as the provider. You can also use ansible, Chef, Puppet.

Example: Vagrantfile with Ansible provisioner

1
2
3
4
5
6
7
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/bionic64"

config.vm.provision "ansible" do |ansible|
ansible.playbook = "playbook.yml"
end
end

playbook.yml - A simple playbook that installs zip and nginx package

1
2
3
4
5
6
7
8
9
10
11
12
13
---
- hosts: all
become: yes
become_method: sudo
tasks:
- name: Update OS
package:
name: '*'
state: latest

- name: Install Basic packages
package:
name: [zip, nginx]

Vagrant box Commands

vagrant downloads boxes to spin up vagrant environment. If you have too many boxes, it will occupy a lot of disk space. You may need to remove the boxes you don’t need.

You use vagrant box command to manage boxes.

Add a box, use –insecure flag if you get certificate error

1
vagrant box add ubuntu/focal64 --insecure

To list vagrant boxes

1
vagrant box list

Remove a vagrant box

1
vagrant box remove <name>