Posted on January 29, 2011 at 7:58pm EST. More.

How to make a VirtualBox guest boot from an external drive on a Mac host

I have been using Macintosh since before it was cool. A lot has changed since then: now Apple is cool, Macs use Intel processors, and software can emulate a virtual computer inside your actual computer. Although Microsoft becomes less relevant each day, there are still valid reasons besides masochism that a person might want access to Windows.

This is the story of how I used VirtualBox to set up a Windows 7 guest on a Mac OS X host. Lots of people have done this. The reason I feel my story is compelling enough to tell is that, rather than using a single file to act as a virtual hard disk, I am using an actual hard disk, connected to my Mac via FireWire.

Why do this?

Now that I have convinced you this is worth the hassle, I will describe the details of the hassle.

Warning: the procedure below is not for the faint of heart. If you are uncomfortable at a command line, you may want to wait for software to support this in a more graceful manner.

Install VirtualBox

On Mac OS X you have three options (that I am aware of): Parallels DesktopVMware Fusion, and VirtualBox. I used VirtualBox because it is free and I am a cheapskate. Parallels and VMware are very reasonably priced, and supposedly offer better performance, but my needs are modest and VirtualBox is pretty good.

Download VirtualBox and follow the installation instructions, etc. Don’t create your virtual machine just yet. Note to people of the future: 4.0.2 was the latest available version at the time of writing.

Create Virtual Disk File

Although your virtual machine will be using an actual hard disk, you still need to make a file that tells VirtualBox how to access the device. You can’t do this through the graphical interface, so you must drop down to the command line. Connect your disk and open a Terminal window. Then type:
diskutil list
You should see some output that looks like this:
/dev/disk0
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:      GUID_partition_scheme                        *250.1 GB   disk0
   1:                        EFI                         209.7 MB   disk0s1
   2:                  Apple_HFS Macintosh HD            215.8 GB   disk0s2
   3:       Microsoft Basic Data BOOTCAMP                33.9 GB    disk0s3
/dev/disk1
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:     Apple_partition_scheme                        *2.2 TB     disk1
   1:        Apple_partition_map                         32.3 KB    disk1s1
   2:                  Apple_HFS Drobo                   2.2 TB     disk1s3
/dev/disk2
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:     Apple_partition_scheme                        *10.8 GB    disk2
   1:        Apple_partition_map                         32.3 KB    disk2s1
   2:                 Apple_HFSX benzado                 10.8 GB    disk2s2
/dev/disk4
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:     FDisk_partition_scheme                        *60.0 GB    disk4
From this list, you need to identify which disk is the one you want to install onto. In my case, it’s the last one, disk4. I wish I could tell you exactly what to look for, but at this point I don’t know what’s on your disk, if it’s been formatted, etc. If you’re unsure, look for a number in the size column that matches the size of the drive.

Now for some harsh reality: Mac OS X assigns these disk numbers on a first-connected, first-served basis. In my case, the internal hard drive is disk0 and my Drobo is disk1. When I log in, Finder mounts my iDisk, so that’s disk2. At some point I downloaded and mounted a disk image to install some software, it was disk3. Then I connected the external drive, disk4. Finally, I ejected the disk image, which is why disk3 does not appear in the list above.

Our problem is that VirtualBox needs a disk identifier, but the identifier depends on when we plugged the drive in. The least painful way to deal with this problem is to create a symbolic link to the device identifier, and tell VirtualBox to use that. If the external disk’s identifier has changed, all we need to do is update the symbolic link. Let’s do that.

Switch to the directory where VirtualBox stores it’s hard disk files:

cd ~/Library/VirtualBox/HardDisks/
Create a link to the device we noted earlier:
ln -s /dev/disk4 ExternalDiskDeviceLink
Create the virtual disk file:
VBoxManage internalcommands createrawvmdk -filename ExternalDisk.vmdk -rawdisk $PWD/ExternalDiskDeviceLink
This creates a virtual disk file named ExternalDisk.vmdk which refers to the link ExternalDiskDeviceLink, which in turn points to the device /dev/disk4.

Whenever you need to point to a new device, update the symbolic link file:

ln -s /dev/disk3 ~/Library/VirtualBox/HardDisks/ExternalDiskDeviceLink
You may be wondering, why not just use VBoxManage to create a bunch of the vmdk files, and switch between those? You could do that, but each time you create a file, it is assigned a UUID which is apparently visible to the guest OS. Microsoft Office, for example, believes it has been copied to a new computer if this UUID changes, forcing you to reactivate your legally obtained copy by telephone.

Also, clicking around in VirtualBox to change the disk file each time would get annoying (to me) fast.

Configure a Virtual Machine

Launch VirtualBox and create a new virtual machine. The prompts are fairly straightforward, I won’t explain them all. When it asks you to select a virtual hard disk, select Use existing hard disk and then click the tiny folder icon to select the ExternalDisk.vmdk file you created earlier.

The guest and the host cannot use the external disk at the same time, so if the disk has been mounted on the host, make sure to eject it before you try to start the virtual machine. If you don’t, VirtualBox will lambast you with a cryptic, angry error message containing the word BUSY.

(If you get a different error message containing the word UNSUPPORTED, try changing the configuration so that the disk is connected to a virtual IDE controller rather than a virtual SATA controller.)

Once the VM is running, you can install Windows 7 (or whatever other OS you like). Allow the installer to partition and format the external drive.

Prevent the Drive from Auto-mounting

Even though I would eject the drives before starting the VM, Mac OS X would mount them again as soon as the VM shut down. This was annoying.

Then at some point I noticed Mac OS X mounted the drives while the virtual machine was running. This caused the VM to lock up and was generally horrible. So even though I was good about unmounting the drives before starting the VM, it is absolutely necessary to prevent Mac OS X from auto-mounting the drives.

If it’s running, shut down the VM. Let the drives mount automatically or use Disk Utility to mount them. Then open a Terminal window and type:

diskutil list
Here is the part of the output we’re interested in:
/dev/disk4
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:     FDisk_partition_scheme                        *60.0 GB    disk4
   1:               Windows_NTFS System Reserved         104.9 MB   disk4s1
   2:               Windows_NTFS Homunculus Brain        59.9 GB    disk4s2
Windows has created two partitions; we need to make sure they don’t mount. We do this by listing them in the system’s fstab file. We can identify disks by label (name) or UUID. It’s better to use the UUID if we can, since it’s easy to change a disk’s label but impossible (well, very difficult) to change it’s UUID. Unfortunately, some partitions don’t appear to have one.

Find out if each partition has a UUID:

diskutil info disk4s1
Look for a line like:
   Volume UUID:              FB4E2CC6-36EF-41E1-9E41-D6E0D932F2EB
Make a note of the UUID; if it doesn’t have one, note the Volume Name instead. Repeat for disk4s2 and so on. Now create a file at /etc/fstab (you need root privileges to do so) and add the following lines. (If the file already exists, you can just add these lines to the end.)
# identifier, mount point, fs type, options
LABEL=System\040Reserved  none  ntfs  ro,noauto
UUID=FB4E2CC6-36EF-41E1-9E41-D6E0D932F2EB  none  ntfs  ro,noauto
In my case, “System Reserved” did not have a UUID, so I identified it by label, using \040 to represent the space. I’m not too worried about it, since its label is unlikely to change. The main partition’s name, other the other hand, can be changed by clicking around within Windows, so I’ve copied the UUID from above. You should copy the UUID from your system and not the one from this web page.

Anyway, that “noauto” keyword on the end of the line is what prevents Mac OS X from mounting the disk when you plug the drive in.

Test it by ejecting the disks, unplugging the drive, then plugging it back in. If nothing happens, you’ve succeeded!

If you ever want to mount the disks manually (perhaps to copy a file without booting up your VM), use Disk Utility.

Congratulate yourself

You have done it: a virtual machine that boots from an actual hard disk.

These instructions are based on my faulty memory of what worked for me on my computer. If you run into problems, leave a comment and let me know, but I can’t guarantee I can help you.

There is definitely room for improvement here. An enterprising sort of person could probably write a script or application that automatically updates the symbolic link before starting the VM.