Moving a VM Dev Environment to VirtualBox Headless

Submitted by nigel on Monday 15th January 2018

I've been using a VM image on my Macbook for a while now, and using it as my Drupal development environment. It has been handcrafted with MariaDB, NGINX, Jenkins and other utilities that have built up over time such as Mailcatcher and npm. It's become increasingly inconvenient having the VM on the laptop I use for client work, so I decided to move it to my Intel NUC machine. This will provide a centralised location in my apartment to access the VM from any of my other laptops and devices. 

However since my Intel NUC doesn't have an installed GUI since it is a server, a headless solution is required. To manage this I will need VirtualBox Headless - here is the tutorial on how to achieve this. My NUC machine was installed with Ubuntu 17.04 (Zesty Zapus) but other flavours of Debian based Linux will be similar.  

Installing VirtualBox
To install VirtualBox, login to the host box over the local network (in my case my Intel NUC) and sudo su. Then add the repository and the public key with
root@devbox:/# wget -q https://www.virtualbox.org/download/oracle_vbox.asc -O- | apt-key add -
OK
root@devbox:/# 
Update and install. Note - there's every chance you will be presented with a list of numerous dependencies that will have to be installed at the same time. For brevity I haven't included the output below.
root@devbox:/# apt-get update
root@devbox:/# apt-get install virtualbox
In addition it's a good idea to install the dkms package to ensure that the VirtualBox host kernel modules (vboxdrv, vboxnetflt and vboxnetadp) are properly updated if the linux kernel version changes during the next apt-get upgrade. I did this but no updates were required.
root@devbox:/# apt-get install dkms
Reading package lists... Done
Building dependency tree       
Reading state information... Done
dkms is already the newest version (2.3-3ubuntu1.2).
dkms set to manually installed.
0 to upgrade, 0 to newly install, 0 to remove and 7 not to upgrade.
root@devbox:/#
Now we can check the installed version of VirtualBox to make sure it is installed ok.
root@devbox:/# vboxmanage --version
5.1.22_Ubuntur115126
root@devbox:/# 
Export the Existing VM from VirtualBox
Select Export
Rename the export
Appliance Settings Page
Progress

Now I exported the existing VM from my MacBook. This is achieved through the VirtualBox GUI. Go to File->Export Appliance... and select the VM from the list (first image above). Then change the name of the output file if you desire. I opted to do this by adding the date on to the end (image two). The third image shows the appliance's settings - if you are ok with this click Export. The final image shows the progress screen - budget on a few minutes. 

Create a directory for the VM on the remote host machine.
nigel@devbox:~$ cd ~
nigel@devbox:~$ mkdir VM
nigel@devbox:~$
And scp it over to that machine from the MacBook. This could take half an hour or so.
$ scp badzilla-d8-2018-01-15.ova nigel@192.168.0.202:/home/nigel/VM/.
Import VM Image
Now let's import our VM image so VirtualBox knows about it. Note I am now logged in as myself, not as superuser.
nigel@devbox:~/VM$ VBoxManage import badzilla-d8-2018-01-15.ova 
0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
Interpreting /home/nigel/VM/badzilla-d8-2018-01-15.ova...
OK.
Disks:
  vmdisk2	16106127360	-1	http://www.vmware.com/interfaces/specifications/vmdk.html#streamOptimized	badzilla-d8-2018-01-15-disk001.vmdk	-1	-1	
 
Virtual system 0:
 0: Suggested OS type: "Ubuntu_64"
    (change with "--vsys 0 --ostype <type>"; use "list ostypes" to list all possible values)
 1: Suggested VM name "badzilla-d8"
    (change with "--vsys 0 --vmname <name>")
 2: Number of CPUs: 1
    (change with "--vsys 0 --cpus <n>")
 3: Guest memory: 1024 MB
    (change with "--vsys 0 --memory <MB>")
 4: Sound card (appliance expects "", can change on import)
    (disable with "--vsys 0 --unit 4 --ignore")
 5: USB controller
    (disable with "--vsys 0 --unit 5 --ignore")
 6: Network adapter: orig Bridged, config 3, extra slot=0;type=Bridged
 7: CD-ROM
    (disable with "--vsys 0 --unit 7 --ignore")
 8: IDE controller, type PIIX4
    (disable with "--vsys 0 --unit 8 --ignore")
 9: IDE controller, type PIIX4
    (disable with "--vsys 0 --unit 9 --ignore")
10: SATA controller, type AHCI
    (disable with "--vsys 0 --unit 10 --ignore")
11: Hard disk image: source image=badzilla-d8-2018-01-15-disk001.vmdk, target path=/home/nigel/VirtualBox VMs/badzilla-d8/badzilla-d8-2018-01-15-disk001.vmdk, controller=10;channel=0
    (change target path with "--vsys 0 --unit 11 --disk path";
    disable with "--vsys 0 --unit 11 --ignore")
0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
Successfully imported the appliance.
nigel@devbox:~/VM$
Modify Existing Network Configuration
An attempt to start the VM will result in an error - see below diagnostic.
nigel@devbox:~/VM$ VBoxHeadless --startvm badzilla-d8 
Oracle VM VirtualBox Headless Interface 5.1.22_Ubuntu
(C) 2008-2017 Oracle Corporation
All rights reserved.
 
Error: failed to start machine. Error message: Failed to open/create the internal network 'HostInterfaceNetworking-en0: Wi-Fi (AirPort)' (you might need to modprobe vboxnetflt to make it accessible) (VERR_INTNET_FLT_IF_NOT_FOUND).
Failed to attach the network LUN (VERR_INTNET_FLT_IF_NOT_FOUND)
nigel@devbox:~/VM$
This is due to the network configuration which is currently set to use the MacBook's WiFi Airport device as a bridge. No good in an Intel NUC machine! So let's see how the configuration currently looks:
nigel@devbox:~/VM$ VBoxManage showvminfo badzilla-d8 | grep NIC
NIC 1:           MAC: 080027D2CF47, Attachment: Bridged Interface 'en0: Wi-Fi (AirPort)', Cable connected: on, Trace: off (file: none), Type: 82540EM, Reported speed: 0 Mbps, Boot priority: 0, Promisc Policy: deny, Bandwidth group: none
NIC 2:           disabled
NIC 3:           disabled
NIC 4:           disabled
NIC 5:           disabled
NIC 6:           disabled
NIC 7:           disabled
NIC 8:           disabled
nigel@devbox:~/VM$ 
Let's see what we've got in this machine...
nigel@devbox:~/VM$ VBoxManage list bridgedifs
Name:            enp3s0
GUID:            33706e65-3073-4000-8000-94c69114b597
DHCP:            Disabled
IPAddress:       192.168.0.202
NetworkMask:     255.255.255.0
IPV6Address:     fe80:0000:0000:0000:96c6:91ff:fe14:b597
IPV6NetworkMaskPrefixLength: 64
HardwareAddress: 94:c6:91:14:b5:97
MediumType:      Ethernet
Status:          Up
VBoxNetworkName: HostInterfaceNetworking-enp3s0
 
Name:            wlp2s0
GUID:            32706c77-3073-4000-8000-cc2f7140538a
DHCP:            Disabled
IPAddress:       0.0.0.0
NetworkMask:     0.0.0.0
IPV6Address:     
IPV6NetworkMaskPrefixLength: 0
HardwareAddress: cc:2f:71:40:53:8a
MediumType:      Ethernet
Status:          Down
VBoxNetworkName: HostInterfaceNetworking-wlp2s0
 
nigel@devbox:~/VM$
Ok - our eth0 port is actually called enp3s0. That's useful :) So let's set that to be our network adapter.
nigel@devbox:~/VM$ VBoxManage modifyvm badzilla-d8 --nic1 bridged --bridgeadapter1 enp3s0
Now lets see what happens when we try to start the VM
nigel@devbox:~/VM$ Oracle VM VirtualBox Headless Interface 5.1.22_Ubuntu
(C) 2008-2017 Oracle Corporation
All rights reserved.
 
ALSA lib confmisc.c:767:(parse_card) cannot find card '0'
ALSA lib conf.c:4528:(_snd_config_evaluate) function snd_func_card_driver returned error: No such file or directory
ALSA lib confmisc.c:392:(snd_func_concat) error evaluating strings
ALSA lib conf.c:4528:(_snd_config_evaluate) function snd_func_concat returned error: No such file or directory
ALSA lib confmisc.c:1246:(snd_func_refer) error evaluating name
ALSA lib conf.c:4528:(_snd_config_evaluate) function snd_func_ref
Ok - this looks more promising. The ALSA messages probably relate to a missing sound card. Let's check
Remove Soundcard
Connected Devices
We are now clearly very close to having a configuration that works. By checking the connected devices on my router I can see that my machine badzilla-d8 has connected to the network successfully. Further more I can ping it and ssh into it! All we need to do is sort out the sound card diagnostics.
$ ping 192.168.0.17
PING 192.168.0.17 (192.168.0.17): 56 data bytes
64 bytes from 192.168.0.17: icmp_seq=0 ttl=64 time=4.286 ms
64 bytes from 192.168.0.17: icmp_seq=1 ttl=64 time=1.941 ms
64 bytes from 192.168.0.17: icmp_seq=2 ttl=64 time=2.101 ms
^C
--- 192.168.0.17 ping statistics ---
3 packets transmitted, 3 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 1.941/2.776/4.286/1.070 ms
$ ssh nigel@192.168.0.17
nigel@192.168.0.17's password: 
Welcome to Ubuntu 14.04.5 LTS (GNU/Linux 4.4.0-31-generic x86_64)
 
 * Documentation:  https://help.ubuntu.com/
 
  System information as of Mon Jan 15 16:19:31 GMT 2018
 
  System load:  0.08               Processes:           117
  Usage of /:   52.0% of 14.10GB   Users logged in:     0
  Memory usage: 5%                 IP address for eth0: 192.168.0.17
  Swap usage:   0%
 
  Graph this data and manage this system at:
    https://landscape.canonical.com/
 
Last login: Mon Jan 15 16:16:02 2018 from 192.168.0.12
$
Ok so let's see what the configuration says about our audio card:
nigel@devbox:~/VM$ VBoxManage showvminfo badzilla-d8 | grep ALSA
Audio:           enabled (Driver: ALSA, Controller: AC97, Codec: AD1980)
nigel@devbox:~/VM$ 
Power off the machine before we do anything to the configuration
nigel@devbox:~/VM$ VBoxManage controlvm badzilla-d8 poweroff
0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
nigel@devbox:~/VM$ 
Now we can remove the audio, check it's definitely gone, and start the VM
nigel@devbox:~/VM$ VBoxManage modifyvm badzilla-d8 --audio none
nigel@devbox:~/VM$ VBoxManage showvminfo badzilla-d8 | grep audio
nigel@devbox:~/VM$ VBoxHeadless --startvm badzilla-d8 &
[1] 29795
nigel@devbox:~/VM$ Oracle VM VirtualBox Headless Interface 5.1.22_Ubuntu
(C) 2008-2017 Oracle Corporation
All rights reserved.
 
 
nigel@devbox:~/VM$
Ok we are up and running! Now so long as we can connect via NFS on my MAC and my Kubuntu laptop, then we should be in good shape.
NFS Connect to VM from Mac OS
NFS url
NFS Connected

Open Finder and press cmd-K to bring up the Connect to Server modal. The NFS url format must be like shown in the first image - and obviously you must have a corresponding /etc/hosts entry for the url. In my case this will 192.168.0.17.

Once connected, you will see whatever files you've got on your server. In my case I map to /var/www/html so the list of folders are effectively my projects for each website I am working on. 

NFS Connect to VM from Kubuntu Linux
The NFS connection from Kubuntu is best achieved on the command line or by adding an entry to the /etc/fstab file. Once that's achieved, the directory structure can be listed. Success!
nigel@devbox:~$ sudo mount -t nfs -o vers=3 192.168.0.17:/var/www/html /mnt/projects                       
nigel@devbox:~$ ls -las /mnt/projects/
total 84                                                                                               
 4 drwxrwxr-x 13 www-data www-data  4096 Jan 15 18:13 .                                                     
 4 drwxr-xr-x  3 root     root      4096 Jan 15 19:15 ..
 4 drwxrwxr-x  3 nigel    www-data  4096 Aug 11 22:43 badzilla_d6
 4 drwxrwxr-x  7 www-data www-data  4096 Feb 19  2017 badzilla_d8
 4 -rw-rw-r--  1 www-data www-data  4096 Feb  9  2017 ._blog_theme_d8
 4 drwxrwxr-x 13 www-data www-data  4096 Feb 12  2017 blog_theme_d8
 4 -rw-rw-r--  1 www-data www-data  4096 Jan 15 18:13 ._index.html
12 -rw-rw-r--  1 www-data www-data 11510 Feb  6  2017 index.html
 4 drwxrwxr-x  7 nigel    www-data  4096 Oct 19 21:07 kitboot
12 drwxr-xr-x  4 nigel    users    12288 Dec 27 16:41 lakeland
 4 drwxrwxr-x  8 nigel    www-data  4096 Oct 22 10:49 meedjum
 4 drwxrwxr-x  4 nigel    www-data  4096 Apr 23  2017 multisite
 4 drwxrwxr-x 11 www-data www-data  4096 Feb 12  2017 personal-blog
 4 -rw-rw-r--  1 www-data www-data  1301 Aug  6  2015 README.txt
 4 drwxrwxr-x  9 nigel    www-data  4096 May  7  2017 saasidate
 4 drwxrwxr-x  9 nigel    www-data  4096 Dec 23 16:19 serverless-vote
nigel@devbox:~$