Vagrant – A complete beginner’s guide

Introduction

This article is a complete beginner’s guide to Vagrant. Vagrant is an open-source free tool for building and managing virtual machine environments in a single workflow. Once you install Vagrant, it provides a command line client tool “vagrant” to quickly set up virtual machines using virtual machine providers like Oracle VM Virtual Box, Hyper-V, Docker and any other providers including cloud providers like AWS.

While Vagrant itself is not a provider, it works on top of providers and helps quickly set up environments.

Vagrant ships out of the box with support for Oracle VM Virtual Box, Hyper-V, Docker. You can make it work with any other provider by using custom providers. For example, you can make it work with AWS using vagrant-aws plugin.

Why use Vagrant?

If you are an Software Developer or Operations engineer or DevOps engineer or Security engineer, Vagrant is a tool that helps you set up a fully automated disposable environment for developing and testing application code or infrastructure management scripts or security scripts or performing various Proof Of Concepts. 

Vagrant helps you create repeatable environments with simple commands. With vagrantfile, which helps you define configuration of virtual machines, you create and maintain your infrastructure as code.

Lets Get Started

This tutorial will walk you through your first Vagrant project, highlighting major features of Vagrant.

To get started with Vagrant, you will need to install Vagrant and a Virtual Machine Provider. We will use Oracle Virtual Box as provider which is free to download.

Prerequisites

The installations of prerequisites are pretty straightforward:

  1. Install Vagrant
    Installing Vagrant is extremely easy. Head over to the Vagrant downloads page and get the appropriate installer or package for your platform. Install the package using standard procedures for your operating system.
    The installer will automatically add vagrant to your system path so that it is available in terminals. If it is not found, please try logging out and logging back in to your system (this is particularly necessary sometimes for Windows).
  2. Install Oracle Virtual Machine
    Download the installer from https://www.virtualbox.org/ and follow the installers default instructions to install the Virtual Box.

Quick VM set up

In order to feel the power of Vagrant, we will first quickly spin up a VM on Virtual Box.

After you run the following two commands, you will have a fully running virtual machine in VirtualBox running Ubuntu 18.04 LTS 64-bit. Yes! It’s that easy.

First initialise Vagrant using init command

$ vagrant init hashicorp/bionic64                                       

Start the virtual machine using up command

$ vagrant up

That’s it! You have just created your first virtual environment with Vagrant.

Now you can SSH into this machine with below command and explore your environment

$ $ vagrant ssh
Welcome to Ubuntu 18.04.3 LTS (GNU/Linux 4.15.0-58-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Tue Jun 16 21:57:57 UTC 2020

  System load:  0.44              Processes:           91
  Usage of /:   2.5% of 61.80GB   Users logged in:     0
  Memory usage: 11%               IP address for eth0: 10.0.2.15
  Swap usage:   0%

 * MicroK8s gets a native Windows installer and command-line integration.

     https://ubuntu.com/blog/microk8s-installers-windows-and-macos

0 packages can be updated.
0 updates are security updates.


vagrant@vagrant:~$

Terminate the SSH session with CTRL+D, or by logging out.

vagrant@vagrant:~$ logout
Connection to 127.0.0.1 closed.

When you are done exploring terminate the virtual machine with destroy command as follows and confirm when the CLI prompts you by typing yes.

$ vagrant destroy

Now imagine every project you’ve ever worked on being this easy to set up! With Vagrant, vagrant up is all you need to work on any project, to install every dependency that project needs, and to set up any networking or synced folders, so you can continue working from the comfort of your own machine.

The rest of these tutorials will walk you through setting up a more complete project.

Getting started with Vagrant project

Now let’s start with a complete project in which we will use Vagrant to spin up a VM using Ubuntu 18.04 LTS 64-bit and also install apache web server using shell provisioner.

The first step to create a project with Vagrant is to create a Vagrantfile. A Vagrantfile is generated on running vagrant init command with boilerplate code.

The Vagrantfile allows you to:

  • Mark the root directory of your project. Many of the configuration options in Vagrant are relative to this root directory.
  • Describe the kind of machine and resources you need to run your project, as well as what software to install and how you want to access it i.e. define the configuration of your machine as code.

Now let’s start setting up Vagrant project Step by Step.

Create Vagrant root directory

If you are using Linux/Unix or Mac then open terminal or if using Windows open cmd prompt and create directory as follows:

$ mkdir vagrant_first_project

Move into new directory

$ cd vagrant_first_project

Initialise the directory

Now we will initialise our directory using init command. This will generate a pre-populated Vagrantfile with some examples and documentation to understand the code.

The init command will take box name as argument like hashicorp/bionic64. Boxes are the package format for Vagrant environments. The easiest way to use a box is to add a box from the publicly available catalog of Vagrant boxes.

Now we will initialise the directory and specify the hashicorp/bionic64 box

$ vagrant init hashicorp/bionic64

Now we have a Vagrantfile in current directory which we will modify in our tutorial.

The Vagrantfile is meant to be committed to version control with your project, if you use version control. This way, every person working with that project can benefit from Vagrant without any upfront work.

You have now initialised your first project directory. To set up Vagrant for an existing project you would run vagrant init in a pre-existing directory for example, root directory of a code repository. This will generate Vagrantfile which you can modify according to your project.

Now we can bring up the virtual machine to test if it works.

$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
## ... Output truncated ...

Now we can ssh into the machine.

$ vagrant ssh
Welcome to Ubuntu 18.04.3 LTS (GNU/Linux 4.15.0-58-generic x86_64)
## ... Output truncated ...

Local and Guest Files Synchronization

Before moving on to learning shell provisioner, we will learn about sharing files between hosts and guests machines.

Vagrant automatically syncs files to and from the guest machine. This way you can edit files locally and run them in your virtual development environment.

By default, Vagrant shares your project directory (the one containing the Vagrantfile) to the /vagrant directory in your guest machine.

If not already logged in, SSH into your virtual machine to see the synched file.

$ vagrant ssh
Welcome to Ubuntu 18.04.3 LTS (GNU/Linux 4.15.0-58-generic x86_64)
## ... Output truncated ...

On the virtual machine, list the files in the vagrant directory.

vagrant@vagrant:~$ ls /vagrant
Vagrantfile

This Vagrantfile that you see inside the virtual machine is actually the same Vagrantfile that is on your actual host machine.

To see the files sync between the guest machine and yours add a new folder in your virtual machine’s vagrant directory.

vagrant@vagrant:~$ touch /vagrant/test

End your SSH session.

vagrant@vagrant:~$ exit
logout
Connection to 127.0.0.1 closed.

Now list the contents of your local vagrant directory, and notice that the new directory you created on your virtual machine is reflected there.

$ ls
Vagrantfile test

The folder “test” is now on your host machine; Vagrant kept the folders in sync.

Provision a Virtual Machine using shell provisioner

Now we will edit the same Vagrantfile that we used above and learn to use shell provisioner to install and run an apache web server.

If we opt to just install apache by ssh into VM then we have to do this every time if we destroy the virtual machine. Hence we automate provisioning using shell provisioner.

Create an HTML file

Before doing that we will create a directory html inside project directory vagrant_first_project and create a simple html file index.html inside new directory.

The content of html file index.html would look like this.

<html>
  <body>
    <h1>Getting started with Vagrant!</h1>
  </body>
</html>

Create provisioning script

Now is the time to install Apache using shell provisioner. For that we need to create a script and call it lets just say bootstrap.sh and save it in the same directory as Vagrantfile.

#!/usr/bin/env bash

apt-get update
apt-get install -y apache2
if ! [ -L /var/www ]; then
  rm -rf /var/www
  ln -fs /vagrant /var/www
fi

This script will download and start Apache, and crate a symlink between your synced files directory and the location where Apache will look for content to serve.

Modify Vagrantfile

Edit the Vagrantfile as follows

Vagrant.configure("2") do |config|
  config.vm.box = "hashicorp/bionic64"
  config.vm.provision :shell, path: "bootstrap.sh"
end

The provision line tells Vagrant to use the shell provisioner to setup the machine, with the bootstrap.sh file. The file path is relative to the location of the project root (where the Vagrantfile is).

Provision the webserver

If you never ran vagrant up before, then running it now will create machine and install Apache for us.

If machine is already created, we can run reload to reload configuration from Vagrantfile.

$ vagrant reload --provision
==> default: Attempting graceful shutdown of VM...
==> default: Checking if box 'hashicorp/bionic64' version '1.0.282' is up to date...
==> default: Clearing any previously set forwarded ports...
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
## ... Output truncated ...

After Vagrant completes running, the web server will be up and running. You cannot see the website from your own browser (yet), but you can verify that the provisioning works by loading a file from within the machine.

$ vagrant ssh

Now get the HTML file that was created during provisioning.

vagrant@vagrant:~$ wget -qO- 127.0.0.1
<html>
  <body>
    <h1>Getting started with Vagrant!</h1>
  </body>
</html>

This works because in the shell script above you installed Apache and setup the default DocumentRoot of Apache to point to your /vagrant directory, which is the default synced folder setup by Vagrant.

Network Configuration

We will use Vagrant’s networking features to provide access to the guest machine from our host machine.

Port forwarding

Port forwarding allows you to specify ports on the guest machine to share via a port on the host machine. This allows you to access a port on your own machine, but actually have all the network traffic forwarded to a specific port on the guest machine.

Set up a forwarded port so you can access Apache in your guest, by adding it to the Vagrantfile under the line you added to run your bootstrap script.

Vagrant.configure("2") do |config|
  config.vm.box = "hashicorp/bionic64"
  config.vm.provision :shell, path: "bootstrap.sh"
  config.vm.network :forwarded_port, guest: 80, host: 4567
end

Reload so that these changes can take effect.

$ vagrant reload

Access Apache from local browser

Once the machine is running again, load http://127.0.0.1:4567 in your browser, where you will find a web page that is being served from the guest virtual machine.

We have successfully configured networking for your virtual machine using Vagrant. 

Share a Vagrant Environment

Vagrant Share is a plugin that lets you share your Vagrant environment to anyone around the world with an Internet connection. It will give you a URL that will route directly to your Vagrant environment from any device in the world that is connected to the Internet.

The person you are sharing the URL do not need to have vagrant installed.

Prerequisite

For vagrant share to work, we need to install ngrok. Ngrok exposes local servers behind NATs and firewalls to the public internet over secure tunnels.

It can be downloaded and installed from https://ngrok.com/download

Install the plugin

Install the vagrant-share plugin as follows:

$ vagrant plugin install vagrant-share
Installing the 'vagrant-share' plugin. This can take a few minutes...
Fetching vagrant-share-1.1.10.gem
Installed the plugin 'vagrant-share (1.1.10)'!

Share the environment

Now run vagrant share to share the environment

$ vagrant share
##... output truncated ...
==> default: Creating Vagrant Share session...
==> default: HTTP URL: http://a2fc4f8e.ngrok.io
##... output truncated ...

Open a web browser and visit the URL from your output. It should load the Apache page we setup earlier.

If you modify the files in your shared folder and refresh the URL, you will see your update. The URL is routing directly into your Vagrant environment, and works from any device in the world that is connected to the internet.

End the sharing session.

$ ^C
==> default: Halting Vagrant share!

Suspend,Halt,Destroy or Rebuild Vagrant machines

Vagrant provides various options on how you want to stop or restart your work on Vagrant machines. We will explore these options now

Suspend the machine

Suspending the virtual machine will stop it and save its current running state.

$ vagrant suspend
==> default: Saving VM state and suspending execution...

When you begin working again bring the machine back up and its state resumes from where you left off. 

$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Checking if box 'hashicorp/bionic64' version '1.0.282' is up to date...
==> default: Resuming suspended VM...
##... output truncated ...

Suspending your machine is intended for stopping and starting work quickly.

The downside is that the virtual machine will still use disk space while suspended, and requires additional disk space to store the state of the virtual machine RAM.

Halt the machine

Halting the virtual machine will gracefully shut down the guest operating system and power down the guest machine.

$ vagrant halt
==> default: Attempting graceful shutdown of VM...

Halting your machine will cleanly shut it down, preserving the contents of disk and allowing you to cleanly start it again. 

$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Checking if box 'hashicorp/bionic64' version '1.0.282' is up to date...
==> default: Clearing any previously set forwarded ports...
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
##... output truncated ...

A halted guest machine will take more time to start from a cold boot and will still consume disk space.

Destroy the machine

Destroying the virtual machine will remove all traces of the guest machine from your system. It’ll stop the guest machine, power it down, and reclaim its disk space and RAM. Destroy the machine now, and confirm with a yes when prompted.

$ vagrant destroy
    default: Are you sure you want to destroy the 'default' VM? [y/N] y
==> default: Forcing shutdown of VM...
==> default: Destroying VM and associated drives...

Again, when you are ready to work again, just issue a vagrant up.

Rebuild the machine

Even if you have destroyed your machine. You still have files stored in shared file local. You can opt to checkin the project folder along with all the shared files and Vagrantfile. Now whenever you are ready to work on your project anytime which could be days or weeks or months or whenever you want to, all you need to do is run vagrant up command.

$ vagrant up

And now you have rebuilt the environment with same configuration as before with just one command. Once Vagrantfile is completely configured, project can be shared with team members and they can set up environments with same configuration as you.

Conclusion

I am pretty sure by now you have realized how Vagrant can make your life much easier. It is a must have tool in your toolkit. Other provisioners which can be used with Vagrant are ansible , docker, chef, CFEngine and Salt.

Now go ahead and try to set up your project using Vagrant. You can refer Vagrant documentation at https://www.vagrantup.com/docs/index

Similar Posts