Professional developers know they must test their code before releasing it. It is really kind of obvious nowadays! But then why not also testing your deployment scripts before using them in production?
Ideally, you would test the deployment on a controlled environment. If you’re working on an enterprise project, chances are the company provided you with such an environment. But if you are developing a pet project at home, you may not have that luxury.
We still can make this work, though. Thanks to virtualization technologies such as VirtualBox we can create such an environment in the comfort of your development machine.
We need the instances to be able to talk to each other, so we’ll probably have to assign static IP addresses to them. We also need them to be accessible from the host if we want our Ansible playbooks to work, for example. And we’ll probably need to ensure they can access the Internet, to install packages as request by the scripts.
So let’s see how you can setup and configure a network of VirtualBox instances, with static IP addresses and Internet access.
For this example we’re going to create two VirtualBox instances with Ubuntu Server 16.04 on them. OSBoxes.org conveniently provides VDI image files ready to be imported by VirtualBox, but you’re free to install Ubuntu Server from scratch if you feel inclined to.
Start by creating a new instance:
Before we proceed to configuring each virtual machine, we must create a host-only network. The machines will use this network to communicate with each other. Simply access the Host Network Manager from VirtualBox’s main window (File… Host Network Manager) and click on that “Create” button. You should now see an entry, probably named “vboxnet0“. Since we will assign static IP addresses to those instances, you can disable the DHCP server for that network.
Now let’s move to configuring each of the virtual machines we created.
In the instance’s Settings… Network, make sure the Adapter 1 is attached to NAT. This will provide the Internet access to the virtual machine.
Also enable the Adapter 2 and attach it to a Host-only Adapter. Normally VirtualBox will automatically fill the adapter’s name with the “vboxnet0” network we created here above.
Click on “OK” to save your settings and repeat the process for the second machine, using the same settings.
Port-forwarding easily enables you to access a virtual instance through a specific port.
Say for example that your Ansible script needs to access port 22 of your machine in order to work on that Ubuntu Server. We can simply tell VirtualBox to map a local port, such as 4001, to port 22 on the virtual instance. So when we type
ssh firstname.lastname@example.org -p 4001 we will in fact tunnel to the machine’s port 22!
To configure that, simply go back to the instance’s network settings, access the Advanced options of the NAT adapter and click on “Port-Forwarding“. Then create a new rule which you can name “ssh”, set the Host Port to 4001 and the Guest Port to 22. That’s it!
Repeat the process for the second machine.
Static IP addresses
Let’s start both machines right now and login (for OSBoxes’ images, username is usually “osboxes” and password is “osboxes.org”).
You can easily verify that the virtual instances can access the outside world, for example by typing
ping codesandnotes.be. And you should normally be able to reach the machines from your host by opening a terminal and using SSH as explained above.
However, you may have trouble making both instances ping/talk to each other. This is because only one interface is configured in Ubuntu Server: the one from Adapter 1, which is the NAT adapter. We still need to configure the second network interface to point at our”vboxnet0″ host-only network adapter.
To do that, in your Ubuntu Server, type
sudo nano /etc/network/interfaces and edit the file to make it look like this:
source /etc/network/interfaces.d/* # The loopback network interface auto lo iface lo inet loopback # The primary network interface (that's the NAT) auto enp0s3 iface enp0s3 inet dhcp # The secondary network interface (that's the host-only network) auto enp0s8 iface enp0s8 inet static address 192.168.56.101 netmask 255.255.255.0
With this configuration we enabled the secondary network interface, named “enp0s8” in Ubuntu, which is attached to our configured host-only network. We also assigned it a static IP: 192.168.56.101
The address stems from the IPv4 address configured for our “vboxnet0” adapter, which is 192.168.56.1 with a mask of 255.255.255.0. This means we can assign addresses from 192.168.56.2 upwards to our VirtualBox instances.
Okay time’s out: where did those enp0s3 and enp0s8 bits come from? As pointed out by “winter” in the comment below, those are the network interface names known to the OS. You can run
ifconfigto display a list of those. If you do that before editing that “interfaces” configuration, you should see that one of the interfaces has an IP: that’s the one matching the NAT adapter we have set up in the Virtual Box’s Network options. The other interface will be the one we need to set up the host-only network.
Another useful trick is to ping a website by specifying the interface we want to use:
ping -I enp0s3 codesandnotes.be. This way you can figure out which network interface provides Internet access.
Do the same for the second machine you set up: give it 192.168.56.201 as the static address, for example.
Now restart both virtual instances to take those network changes into account, and do an ifconfig to make sure the static addresses have been correctly assigned.
I like it when a plan comes together
If all went according to plans, should now be able to:
- Access your VirtualBoxes from the host with ssh, using the ports configured to forward to the instances’ port 22
- Attain the web from inside the virtual instances
- Reach one virtual machine from the other one, using the configured static IP addresses
Not bad, right?