
Vagrant is a useful and free software product that automates the provisioning of new virtual machines. Its primary purpose is to bring up VMs on your local machine quickly, so you don't have to worry about setting up the infrastructure just to test something. Its goal, which it attains, is to allow you to type "vagrant up" and immediately have one or more VMs automatically come up and be available.
Vagrant isn’t incredibly complicated and doesn’t break any new ground. After all, it’s just automating what we could do ourselves by installing Hyper-V, VirtualBox, or some other virtualization software on our local machine and setting up the VMs. What sets it apart is the huge timesaving effort it affords you. Once a single text file is set up, with just a single command, VMs magically appear on your machine, ready to be connected. In this article, I’ll give you a peek behind the scenes of this magic, so you can enjoy this benefit as well.
To start, you’ll need to install a couple things. First, you’ll need to download Vagrant itself, and second, you’ll need a “provider” for Vagrant—the hypervisor that will bring up your VMs. Vagrant supports VirtualBox, Hyper-V, and Docker out of the box but also can plug into others. For this demonstration, I’ll be using VirtualBox on a Windows machine.
Once you have both products installed, fire up PowerShell and create a directory, if Vagrant didn’t create one for you. You’ll learn that Vagrant is picky about file locations. I’ll create one called C:\Vagrant and change into it.
cd C:\Vagrant
To start, you’ll need to install a couple things. First, you’ll need to download Vagrant itself, and second, you’ll need a “provider” for Vagrant—the hypervisor that will bring up your VMs. Vagrant supports VirtualBox, Hyper-V, and Docker out of the box but also can plug into others. For this demonstration, I’ll be using VirtualBox on a Windows machine.
Once you have both products installed, fire up PowerShell and create a directory, if Vagrant didn’t create one for you. You’ll learn that Vagrant is picky about file locations. I’ll create one called C:\Vagrant and change into it.
cd C:\Vagrant
At this point, I need to tell Vagrant a few basic things about what kind of VMs I’d like it to provision for me. In this case, I’m going to bring up a Windows Server 2012 R2 VM. Vagrant calls these VMs “boxes.” You can download boxes automatically from the public box catalog. You’ll find that hundreds of different images exist already set up for use with Vagrant.
If provisioning Windows Server boxes, I recommend looking for boxes created by Matt Wrock (mwrock). He takes a lot of time to streamline his images, making them as lightweight as possible. For this demonstration, I’ll use his Windows2012R2 box.
Now that I know what box I want to use, I’ll create a configuration file where I can specify the box name I want and a few other details. To do this, I’ll create a Ruby script called VagrantFile (no extension) in my C:\Vagrant directory.
Add-Content –Path C:\Vagrant\VagrantFile –Value ''
At a minimum, for a Windows box, your VagrantFile should include:
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure(2) do |config|
config.vm.define "S1" do |web01|
web01.vm.box = "mwrock/Windows2012R2"
web01.vm.hostname = "S1"
web01.vm.communicator = "winrm"
web01.winrm.username = "vagrant"
web01.winrm.password = "vagrant"
web01.vm.network "private_network",ip: "192.168.2.6"
web01.vm.provider "virtualbox" do |vb|
vb.memory = 2048
vb.cpus = 1
end
end
end
There are many different ways to define this, but you’ll find that if you need to provision multiple VMs, this is the easiest way.
Now that I’ve got my configuration file set up, I’ll simply run “vagrant up” and it will begin to download the box and set it up for me. You can see below that it’s importing the base box. This is because I’ve downloaded this box before and it caches it. If this is a new install, it will download it from the public box catalog. You’ll also see that it literally automates all the common things that have to happen to get a functioning VM working, installing the VirtualBox additions, setting up all the networking, configuring WinRM, setting the hostname, and more.
Now that it’s up, Vagrant knows how to connect to it. I can then use PowerShell remoting to connect using the vagrant/vagrant credential, although I could simply RDP into the server if I wish.
icm –computername 192.168.2.6 –ScriptBlock {hostname} –Credential (Get-Credential)
Once I’m done with the box, I can destroy it just as easily with “vagrant destroy.”

This was Vagrant 101. If you dive deeper, you’ll see that Vagrant can automate many more aspects of VM provisioning through multi-VM test labs, spinning up VMs on Azure, AWS, and more. If you routinely need to bring up VMs quickly to develop on or just want to poke around with a new product, I encourage you to check out Vagrant.
Let’s now attempt to run “vagrant up” and see what happens!
Notice that even if I don’t have the boxes locally, Vagrant will automatically download them from the Internet, perform the necessary configuration, and bring them online. Once I’ve got my VagrantFile set up correctly, I can simply add a few more lines to this text file to bring up another box immediately.
Now that the machines are up, let’s ensure that Vagrant sees them all.
Great! This shows that the three boxes I just provisioned are all online. I’ll now try to SSH into the Linux server and use PowerShell remoting to connect to one of the Windows servers.
The box name has been specified
Notice that I had to specify the name of the box. If this were a single machine, I’d simply need to type “vagrant ssh” or “vagrant powershell” instead.
At this point, you’re free to test away or do whatever you need to do on these local boxes. When you’re done, you can either remove the box, which removes it from your box list, or destroy the box, which also removes the box and all the attached disks as well.
Credit: Adam Bertram
If provisioning Windows Server boxes, I recommend looking for boxes created by Matt Wrock (mwrock). He takes a lot of time to streamline his images, making them as lightweight as possible. For this demonstration, I’ll use his Windows2012R2 box.
Now that I know what box I want to use, I’ll create a configuration file where I can specify the box name I want and a few other details. To do this, I’ll create a Ruby script called VagrantFile (no extension) in my C:\Vagrant directory.
Add-Content –Path C:\Vagrant\VagrantFile –Value ''
At a minimum, for a Windows box, your VagrantFile should include:
- Box name
- Hostname
- Communicator reference (winrm)
- Username
- Password
- Private IP address
- Memory
- CPU
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure(2) do |config|
config.vm.define "S1" do |web01|
web01.vm.box = "mwrock/Windows2012R2"
web01.vm.hostname = "S1"
web01.vm.communicator = "winrm"
web01.winrm.username = "vagrant"
web01.winrm.password = "vagrant"
web01.vm.network "private_network",ip: "192.168.2.6"
web01.vm.provider "virtualbox" do |vb|
vb.memory = 2048
vb.cpus = 1
end
end
end
There are many different ways to define this, but you’ll find that if you need to provision multiple VMs, this is the easiest way.
Now that I’ve got my configuration file set up, I’ll simply run “vagrant up” and it will begin to download the box and set it up for me. You can see below that it’s importing the base box. This is because I’ve downloaded this box before and it caches it. If this is a new install, it will download it from the public box catalog. You’ll also see that it literally automates all the common things that have to happen to get a functioning VM working, installing the VirtualBox additions, setting up all the networking, configuring WinRM, setting the hostname, and more.

Automates all the common things that have to happen to get a functioning VM
icm –computername 192.168.2.6 –ScriptBlock {hostname} –Credential (Get-Credential)

Use PowerShell remoting to connect using the vagrantvagrant credential
Once I’m done with the box, I can destroy it just as easily with “vagrant destroy.”

Vagrant destroy
This was Vagrant 101. If you dive deeper, you’ll see that Vagrant can automate many more aspects of VM provisioning through multi-VM test labs, spinning up VMs on Azure, AWS, and more. If you routinely need to bring up VMs quickly to develop on or just want to poke around with a new product, I encourage you to check out Vagrant.
Set Up a Vagrant Test Eenvironment
I've already gone over how to install Vagrant and get a single virtual machine setup. The steps below will be about taking your skills up a notch if you’d like to set up an entire environment. You’ll learn how to test a high-availability situation, such as setting up load balancers, clusters, and the like. I’ve also personally used this to test Ansible managing Windows, which required a Linux and a Windows host.
Let’s get into the logistics of how to use Vagrant to set up three VMs on your local machine. Vagrant is not limited to three VMs, but my machine is! For this demonstration, I’m going to create an Ubuntu Linux server, a Windows Server 2012 R2, and a Windows Server 2016 VM. I’ll be bringing up these VMs on Oracle’s Virtualbox. VirtualBox is free, has full support with Vagrant, and there’s already a lot of Vagrant boxes already created for VirtualBox.
I’ll head on over to the public Vagrant box catalog and pick the three boxes I’d like to use. I’ll pick the latest Ubuntu box, a box from Matt Wrock with Windows Server 2012 R2 and a Windows Server 2016 TP5 box. Now that I’ve selected each of the boxes I’ll be bringing up, I’ll need to add references to each of the boxes in my VagrantFile.
Assuming you’ve already got Vagrant and VirtualBox installed, next we need to get into your VagrantFile configuration file. At this point, you’ve probably already got a VagrantFile created with, perhaps, a single VM that looks something like this:
config.vm.provider "VirtualBox" do |vb|
# Display the VirtualBox GUI when booting the machine
vb.gui = true
# Customize the amount of memory on the VM:
vb.memory = "1024"
end
Assuming you’ve already got Vagrant and VirtualBox installed, next we need to get into your VagrantFile configuration file. At this point, you’ve probably already got a VagrantFile created with, perhaps, a single VM that looks something like this:
config.vm.provider "VirtualBox" do |vb|
# Display the VirtualBox GUI when booting the machine
vb.gui = true
# Customize the amount of memory on the VM:
vb.memory = "1024"
end
If so, we’ll have to modify that a little bit to add support for multiple VMs. To do that, we’ll have to nest this Ruby do loop inside another to get support for multiple Vagrant boxes. To save you some time, here’s the complete VagrantFile I’m working with.
# -*- mode: ruby -*-
# vi: set ft=ruby :
# All Vagrant configuration is done below. The "2" in Vagrant.configure
# configures the configuration version (we support older styles for
# backward compatibility). Please don't change it unless you know what
# you're doing.
Vagrant.configure(2) do |config|
config.vm.define "linux" do |ctl|
ctl.vm.box = "ubuntu/trusty64"
ctl.vm.hostname = "linux"
ctl.vm.network "private_network",ip: "192.168.2.5"
ctl.vm.provider "virtualbox" do |vb|
vb.memory = 2048
end
end
config.vm.define "WinSrv1" do |winsrv1|
winsrv1.vm.box = "mwrock/Windows2012R2"
winsrv1.vm.hostname = "S1"
winsrv1.vm.communicator = "winrm"
winsrv1.winrm.username = "vagrant"
winsrv1.winrm.password = "vagrant"
winsrv1.vm.network "private_network",ip: "192.168.2.6"
winsrv1.vm.provider "virtualbox" do |vb|
vb.memory = 2048
vb.cpus = 1
end
end
config.vm.define "WinSrv2" do |winsrv2|
winsrv2.vm.box = "mwrock/windows2016"
winsrv2.vm.hostname = "S2"
winsrv2.vm.communicator = "winrm"
winsrv2.winrm.username = "vagrant"
winsrv2.winrm.password = "vagrant"
winsrv2.vm.network "private_network",ip: "192.168.2.7"
winsrv2.vm.provider "virtualbox" do |vb|
vb.memory = 2048
vb.cpus = 1
end
end
end
You can see the file that I’ve arbitrarily chosen is a private IP network of 192.168.2.0, and I have each box set with a different IP address. I’ve also made sure to configure the Windows boxes to use WinRM with the standard vagrant/vagrant username/password.# -*- mode: ruby -*-
# vi: set ft=ruby :
# All Vagrant configuration is done below. The "2" in Vagrant.configure
# configures the configuration version (we support older styles for
# backward compatibility). Please don't change it unless you know what
# you're doing.
Vagrant.configure(2) do |config|
config.vm.define "linux" do |ctl|
ctl.vm.box = "ubuntu/trusty64"
ctl.vm.hostname = "linux"
ctl.vm.network "private_network",ip: "192.168.2.5"
ctl.vm.provider "virtualbox" do |vb|
vb.memory = 2048
end
end
config.vm.define "WinSrv1" do |winsrv1|
winsrv1.vm.box = "mwrock/Windows2012R2"
winsrv1.vm.hostname = "S1"
winsrv1.vm.communicator = "winrm"
winsrv1.winrm.username = "vagrant"
winsrv1.winrm.password = "vagrant"
winsrv1.vm.network "private_network",ip: "192.168.2.6"
winsrv1.vm.provider "virtualbox" do |vb|
vb.memory = 2048
vb.cpus = 1
end
end
config.vm.define "WinSrv2" do |winsrv2|
winsrv2.vm.box = "mwrock/windows2016"
winsrv2.vm.hostname = "S2"
winsrv2.vm.communicator = "winrm"
winsrv2.winrm.username = "vagrant"
winsrv2.winrm.password = "vagrant"
winsrv2.vm.network "private_network",ip: "192.168.2.7"
winsrv2.vm.provider "virtualbox" do |vb|
vb.memory = 2048
vb.cpus = 1
end
end
end
Let’s now attempt to run “vagrant up” and see what happens!

![]() |
Vagrant will automatically download the boxes from the Internet and perform the configuration needed
|
Now that the machines are up, let’s ensure that Vagrant sees them all.

Great! This shows that the three boxes I just provisioned are all online. I’ll now try to SSH into the Linux server and use PowerShell remoting to connect to one of the Windows servers.

The box name has been specified
Notice that I had to specify the name of the box. If this were a single machine, I’d simply need to type “vagrant ssh” or “vagrant powershell” instead.
At this point, you’re free to test away or do whatever you need to do on these local boxes. When you’re done, you can either remove the box, which removes it from your box list, or destroy the box, which also removes the box and all the attached disks as well.

Credit: Adam Bertram
No comments: