Vagrant on Windows: VirtualBox Network Configuration & Provisioning
This article explores Vagrant automation and VirtualBox networking (NAT/Bridging) configuration fundamentals on a Microsoft Windows operating system host.
Prerequisites
There is a Microsoft Windows installer available for Vagrant–you can download Vagrant here. In addition, Oracle VirtualBox should already be installed.
Note: The Vagrant Microsoft Windows installer will add ‘vagrant’ to your environment’s system path.
Initialization
Using PowerShell, create a new directory and, using Vagrant, initialize a new project:
As the return output indicates, a Vagrantfile has been generated inside the directory. The primary function of the Vagrantfile is to describe the type of virtual machine required, and more importantly, how to configure and provision the virtual machine.
If you open the Vagrantfile in a text editor, most of the file is simply comments and noise–therefore, let’s generate a minimal Vagrantfile and expand on it–first, delete the existing Vagrantfile:
This instructs Vagrant to reference HashiCorp’s Atlas box catalog and grab the chef/centos-6.6 box image.
In addition, this instructs Vagrant to apply a hostname as well as apply a “label” which VirtualBox can use to identify the virtual machine–in this case, both have a value of “vagrant-centos01”.
In NAT mode, the guest network interface is assigned to the IPv4 range 10.0.x.0/24 by default, where x corresponds to the instance of the NAT interface +2. Therefore, x is 2 when there is only one NAT instance active.
With this configuration, the virtual machine receives its network address and configuration on the private network from a DHCP server integrated into VirtualBox. Typically, the first virtual network interface is connected to the private network 10.0.2.0/24, the second virtual network interface to the private network 10.0.3.0/24, and so on.
Which private network has the virtual machine been connected to?
The VirtualBox utility ‘VBoxManage’ is useful for this:
The above example virtual machine is connected to the private network “10.0.2.0/24” (CIDR, netmask 255.255.255.0), as expected. This private network is internal to VirtualBox and therefore invisible to the underyling Windows host.
Therefore, any and all network services on the guest are not accessible to the host (or to other computers on the same network).
Fortunately, much like a physical router, VirtualBox can make selected services available to the world outside the guest virtual machine through port forwarding.
Vagrant’s automation has performed the forwarding on our CentOS virtual machine, for us: “Host” port 2222 has been forwarded to “Guest” port 22.
Naturally, rather than using the VBoxManage utility to glean the virtual machine’s network configuration, we could have used a SSH client (Putty), and connected to 127.0.0.1 on port 2222:
1234567
# username: vagrant / password: vagrant[[email protected] ~]$ ip a | grep inet | grep eth0
inet 10.0.2.15/24 brd 10.0.2.255 scope global eth0
[[email protected] ~]$ ip route show dev eth0
10.0.2.0/24 proto kernel scope link src 10.0.2.15
default via 10.0.2.2
Obviously, we can’t SSH to 10.0.2.15. Enter bridged networking.
Bridged Networking
Rather than provision virtual machines within private virtual networks, we can use a bridged networking configuration–our guests will be assigned an IP address from the same subnet as the Windows host.
With bridged networking, VirtualBox uses a device driver on your host system that filters data from your physical network adapter.
The second (bridged) virtual network interface was assigned 192.168.1.16/24 via DHCP.
From the perspective of the virtual machine:
12345678910
[[email protected] ~]$ ip a | grep inet | grep eth
inet 10.0.2.15/24 brd 10.0.2.255 scope global eth0
inet 192.168.1.16/24 brd 192.168.1.255 scope global eth1
[[email protected] ~]$ ip route show dev eth0
10.0.2.0/24 proto kernel scope link src 10.0.2.15
[[email protected] ~]$ ip route show dev eth1
192.168.1.0/24 proto kernel scope link src 192.168.1.16
default via 192.168.1.1
It’s tedious to query the VirtualBox provider for virtual network configuration information (or the edge firewall), so let’s instruct Vagrant to provide the bridged IPv4 address as returned Vagrant output within PowerShell, once the virtual machine has been provisioned.
Update the Vagrantfile:
123456789101112131415161718
Vagrant.configure(2)do|config|config.vm.box="chef/centos-6.6"config.vm.hostname="vagrant-centos01"config.vm.network"public_network",bridge:"Realtek PCIe GBE Family Controller"config.vm.provider"virtualbox"do|v|v.name="vagrant-centos01"endconfig.ssh.shell="bash -c 'BASH_ENV=/etc/profile exec bash'"config.vm.provision"shell"do|s|s.inline="echo $(ip -family inet a | grep 192 | awk '{print $2}')"endend
As you can see, Vagrant ran our custom script as a part of its automation and returned the IPv4 address 192.168.1.13/24 as part of the Vagrant output within PowerShell.
Virtual Disk Size Information
Once you’re comfortable with Vagrant, you’ll want to be aware of your disk utilization.
To determine the initial disk usage of the vagrant-centos01 virtual machine, perform the following in PowerShell:
Based on the above, the “Size on disk” is 728 megabytes–this value will vary depending on the base box image specified in your Vagrantfile.
In addition, the “Format variant” is dynamic. In dynamic mode, storage will be allocated on-demand, as it is needed. You will likely incur a disk I/O penalty as the VMDK expands, as long as the disk image file is using the dynamic allocation format.
Note: VirtualBox supports two types of image file formats: dynamic and fixed.
Vagrantfile Example Template (Reference)
The following is a rudimentary Vagrantfile, using the public Ubuntu image, allocating 2 GB of RAM, 2 vCPU(s) with a 90% execution cap, and utilizing a bridged network configuration.
Both the NAT and Bridged virtual interfaces have been set to use the adapter type virtio-net for improved performance.
Vagrant.configure(2)do|config|# https://atlas.hashicorp.com/ubuntu/boxes/trusty64config.vm.box="ubuntu/trusty64"config.vm.hostname="vagrant-ubuntu01"config.vm.network"public_network",bridge:"Realtek PCIe GBE Family Controller"config.vm.provider"virtualbox"do|v|v.name="vagrant-ubuntu01"v.customize["modifyvm",:id,"--cpuexecutioncap","90"]v.memory=2048v.cpus=2# set bridged adapter to use (KVM) para-virtualized virtio-netv.customize["modifyvm",:id,"--nictype1","virtio"]v.customize["modifyvm",:id,"--nictype2","virtio"]# default is "headless"; to debug, set to truev.gui=falseendconfig.ssh.shell="bash -c 'BASH_ENV=/etc/profile exec bash'"config.vm.provision"shell"do|s|s.inline="echo $(ip -family inet a | grep 192 | awk '{print $2}')"endend
If you come across any interesting tips or tricks, please feel free to comment.