Mac VirtualBox Linked Clones
I’ve been a VMWare Fusion user for quite some time, and I’ve been more than happy with the experience, but the most recent version has dumped an unsupported feature that is essential to my personal workflow: Headless Mode.
One of the VMWare developers responded to requests for information on the missing headless feature in the “Fusion 3 Headless?” VMWare communities thread. Needless to say, the feature may or may not reappear in a newer version of Fusion, but certainly doesn’t in the current version.
With that in mind, I decided it was about time I took a look at VirtualBox, the Open Source virtualisation product from Sun (now Oracle). I’d already heard mostly good things about VirtualBox—except some complaints of slow Windows VMs—and it definitely includes a Headless Mode of its own. What’s more, after a bit of investigation on t’internet, I discovered that linked cloning also appeared to be supported, and linked clones are essential to my workflow.
Create the master
Before we can create clones, we’re going to need a master. In my examples I’ll be creating and cloning an Ubuntu VM, but there’s really no reason why you couldn’t do the same with Windows—in fact, it would be of benefit for cross-browser testing in the various versions of IE, since you can have an instance of Windows for each.
Before we begin creating the master VM, it’s worth updating the VirtualBox preferences so that it puts your files in a predictable place. The default is ~/Library/VirtualBox/ but I have a specific ~/vms/ directory that I like to use. When doing this, be aware that new virtual disk files are created before new VM directories in the “Create New VM” process. This means it’s worthwhile having two directories; one for virtual disk files, and one for the virtual machine directories. This is a pain in the proverbials for portability, but don’t worry too much about it since VirtualBox creates the snapshot difference disks (which will be used by our clones) in the virtual machine directory.
Let’s begin:
Create new VM (cmd+N) and name it whatever you want. It's probably best to make some reference to it being your master, but that's entirely up to you. I used "atum" (first of the Egyptian Gods), and specified my OS as Linux / Ubuntu, unsurprisingly.
When asked to specify, I went with the recommended RAM.
The next step in the wizard is to specify a new or existing virtual disk. Since this is our master, select "Create New Disk".
A second wizard will pop up, specifically for defining the new virtual disk. Use the following options: dynamically expanding, 10Gb (although, VirtualBox recommends 8Gb for Ubuntu, which would also be fine), located in your new default virtual disks folder.
Click finish to end the Create New Virtual Disk Wizard. VirtualBox may pause for a second whilst creating the new .vdi and updating the various XML files that reference it.
After a second or two, you should be presented with the original wizard again. Click "Finish" to complete the creation process.
Make sure new VM is selected in the list of VMs in your VirtualBox window.
We need to make sure we can connect to the our new VM locally. To do that, you'll need to add a host-only network adaptor in addition to the standard NAT one. Click the "Network" heading on the right side of the VirtualBox window, and the settings dialog should pop up. Make sure "Adaptor 1" is enabled and using "NAT", then select "Adaptor 2" and click "Enable". Change "Attached to" to "Host-only Adaptor" and just use the suggested name.
Next we need to tell our VM to boot and install Ubuntu the first time we run our VM. Click "Storage" either in the right hand side of the VirtualBox window, or in the tab bar of the settings dialog that should still be open from the previous step. Choose the CD/DVD device and point it at your Ubuntu ISO, ready for your install.
Click "Ok" to close the settings dialog.
Start your new VM and it should boot into the Ubuntu Installation.
At the installation introduction screen, push F4 and select "Install Minimal Virtual Machine", then start the install as normal. This will install Ubuntu as JeOS, which is specifically configured for virtual machine use.
Install Ubuntu however you like.
Once your install is complete, make sure to remove the Ubuntu ISO from the CD/DVD device. This won't come back to bite you straight away since the first few reboots appeared to ignore it during my install. However, I did end up spending a good 10 minutes wondering why I could no longer SSH to a VM that had previously been working fine before reboot during my install.
Top tip: Depending on the keyboard set-up you opted for during the installation of Ubuntu, you may want to change the AltGr key to be the left alt (option) on your Mac keyboard. You can do this with the following bash command in Ubuntu:
$ sudo dpkg-reconfigure console-setup
If you don't do this, you may have trouble trying to enter # characters later.
</li>Next, let's make sure apt is all up to date. Do that by running the following commands:
$ sudo apt-get update $ sudo apt-get upgrade
If you're using an older than current version of Ubuntu, you may want to do the following (note: the second command reboots the VM):
$ sudo apt-get dist-upgrade $ sudo shutdown -r now
Next I installed vim as my editor of choice.
$ sudo apt-get install vim
Since the basic Ubuntu terminal is a little sparse, you'll probably want to be able to SSH into the VM and use your terminal of choice. To do that, we need to activate the secondary interface for the adaptor we added earlier.
First, edit the following file:
$ sudo vim /etc/network/interfaces
Add the following lines at the bottom:
# The secondary network interface auto eth1 iface eth1 inet static address 192.168.56.2 netmask 255.255.255.0
It's important to use that IP address, since the vboxnet0 is configured on 192.168.56.1 by default.
Activate the eth1 interface:
$ sudo ifup eth1
Now make sure ssh is installed:
$ sudo apt-get install ssh
Following all that, you should now be able to SSH to your new VM from your host:
$ ssh 192.168.56.2
You should now install all the software you want shared across your clones. In my case, that was the usual scripting languages, web servers, database servers etc. used for web development.
Once you're happy with your build, move on.
Let's clear the persistent net rules on our master disk, just so they don't come back to bite us later. In my VMWare tutorial, I did this on the clones, but it makes far more sense to do it on the master before cloning:
$ sudo cp /dev/null /etc/udev/rules.d/70-persistent-net.rules
Now that we're done with SSH, we should bring down the secondary interface so that it's easier to configure on our clones later. Bring the interface down like so:
$ sudo ifdown eth1
Next, go back into the interface configuration file, and comment out the second interface you added:
$ sudo vim /etc/network/interfaces # The secondary network interface # auto eth1 # iface eth1 inet static # address 192.168.56.2 # netmask 255.255.255.0
Now, when you create your clones, you'll be able to uncomment and make sure the IP doesn't clash with other cloned VMs.
Finally, shutdown your VM so we can break it down to the parts we need:
$ sudo shutdown -P now
</ol>
First, you'll need to "release" the virtual disk from the virtual machine using the Virtual Media Manager in VirtualBox.
To do this, just open VirtualBox and choose the Virtual Media Manager from the File menu (alternatively, push cmd+D). Select your master virtual disk in the "Hard Disks" tab, and click the "Release" button in the toolbar.
Next it's worthwhile telling VirtualBox that your master virtual disk is immutable. Run the following command in a terminal on your host machine:
$ vboxmanage modifyhd --type immutable atum.vdi
Where atum.vdi is the name of your master virtual disk. Don't worry about using the full path, VirtualBox should already know where your virtual disks all are (thanks to the Virtual Media Manager).
Lastly, you may like to make the .vdi file read-only:
$ chmod a-w /path/to/atum.vdi
</ol> And we're done. The master virtual disk is now ready to be cloned.Create a clone
So let's go ahead and make a clone of our master:Create a new VM (cmd+N) and name it whatever you like (I used "ra", to follow that Egyptian deity theme). Obviously, make sure to use the same OS as your master when you define your new VM.
Once again use the recommended RAM.
Choose "Use existing hard disk" and select your master, which should already appear in the drop-down since it's already in the Virtual Media Manager.
Once you do this, VirtualBox will automatically create a snapshot difference disk in the "Snapshots" child directory of your virtual machine directory. So in my case, that was here:
/path/to/vms/ra/Snapshots/
Be aware that the difference disks are named with a UUID, and that they reset automatically when the cloned virtual machine is rebooted.
To stop the virtual disk from auto-resetting every time you reboot, you'll need to run the following command once the snapshot has been created:
$ vboxmanage modifyhd --autoreset=off /path/to/vms/ra/Snapshots/{long-uuid}.vdi
Click "Finish" in the "Create New VM" dialog.
Once again, we need to set up the second network interface, so go ahead and do the same as we did for the master: Click "Network" and make sure "Adaptor 1" is enabled and using "NAT". Select "Adaptor 2" and click "Enable". Change "Attached to" to "Host-only Adaptor" and use the suggested name.
Start your new VM and log in with the same user you used on the master. Note your clone is still using the hostname of your master. We'll update that in a second.
It's time to reactivate the secondary interface within Ubuntu:
$ sudo vim /etc/network/interfaces
Uncomment the secondary interface and update the last number of the IP address so that it is unique on the vboxnet.
Now activate the interface again:
$ sudo ifup eth1
You can now ssh to the clone on the address you specified in the secondary interface configuration.
Finally, let's update the hostname of our clone in two places, so that it's unique. First, the hostname file itself, and secondly in the /etc/hosts file so the loopback doesn't get confused:
$ sudo vim /etc/hostname ra $ sudo vim /etc/hosts 127.0.0.1 ra
Finally restart the hostname service:
$ sudo /etc/init.d/hostname.sh start
Headless Mode
Now that we have an army of working linked clone virtual machines, it's probably worthwhile making use of Headless Mode so that they are all running in the background without you needing the VirtualBox GUI invading your desktop and draining resources. First, shutdown your VM by logging in and running this:$ sudo shutdown -P now
Now you can start it back up by running the following command on your host:$ (VBoxHeadless -v=off -s ra &)
Be aware that this runs the VBoxHeadless script in the background, as it doesn't normally auto-exit. I'm running it in a sub-shell because someone far more knowledgeable than myself suggested that this was safer. Cheers Norm.Summary
Firstly, I'd like to thank a few people for their help with this: Bradley Wright for being the usual tech. sounding board, Stuart Colville for clearing up the mystery of VirtualBox network adaptors, and Mark Norman Francis for being considerably better at server administration and bash than me. You should be able to get a good virtualised development environment up in VirtualBox now. Feel free to post any questions in the comments, and if I can't answer personally, I'll pester someone that might be able to. In the future I'm going to look at automating this process, but the VBoxManage command is considerably different to VMWare's vmrun and it's going to take me a little while to figure out stuff like creating new VMs, and releasing virtual disks without removing the entire IDE controller from the master (yeah; I already tried).