Ubuntu Server in VirtualBox on Mac OS X
Introduction
All the web apps I build get deployed on Linux, yet I develop these apps on OS X. I find Macs a brilliant development platform, but building all the server software (nginx, mysql, django, python, apache, php, etc) a real ball-ache. I've tried macports and fink, and frankly neither comes close to apt or yum.
Even if you build the server software on OS X, the quirkiness of OS X makes managing it all so much more difficult compared with Linux (e.g. no /etc/init.d, group permissions are a mess, etc). So what could be better than using a Linux distro virtualized inside OS X itself under Sun's fantastic, free, fast VirtualBox?
Install VirtualBox
Download VirtualBox 2.0.2 and install it. I'm using Ubuntu Server Edition 8.04, but whichever Linux distribution you're using have the ISO ready to install.
Install Linux
In VirtualBox create a New virtual machine and install Linux from the ISO you have - just follow the instructions through. Once installed the Linux machine won't boot unless the PAE/NX setting is checked in the VB settings.
Networking
In the Settings for the Linux VM, set "Attached To:" to NAT. "Host" networking for OS X was part of the 2.0.0 release (which makes the VM and the Host able to connect directly over the network) but I couldn't get it to work. So, select NAT and make sure you've got our active OS X network interface (en0/1 for Airport, eth0/1 for ethernet) highlighted in that same window.
Your Linux machine should boot up now, so we can start setting up the network - we are setting up a webserver after all! There are however a couple of gotchas:
- Pinging doesn't work when using NAT because ICMP isn't implemented by VB's NAT driver.
- Your VM will have an IP address of 10.0.x.x or something, which like 192.x.x.x is a private network so if your router assigns IPs in the 192 range, you won't be able to connect directly to your VM. Fun huh?
With Host networking not working, and NAT not allowing the VM and OS X to talk to each other we have to do a bit more config to tunnel network traffic between them. Fire up Terminal.app, and do the following:
cd /Applications/VirtualBox.app/Contents/MacOS/ ./VBoxManage setextradata "ubuntu" "VBoxInternal/Devices/pcnet/0/LUN#0/Config/sshtunnel/Protocol" TCP ./VBoxManage setextradata "ubuntu" "VBoxInternal/Devices/pcnet/0/LUN#0/Config/sshtunnel/GuestPort" 22 ./VBoxManage setextradata "ubuntu" "VBoxInternal/Devices/pcnet/0/LUN#0/Config/sshtunnel/HostPort" 2222 ./VBoxManage setextradata "ubuntu" "VBoxInternal/Devices/pcnet/0/LUN#0/Config/httptunnel/Protocol" TCP ./VBoxManage setextradata "ubuntu" "VBoxInternal/Devices/pcnet/0/LUN#0/Config/httptunnel/GuestPort" 80 ./VBoxManage setextradata "ubuntu" "VBoxInternal/Devices/pcnet/0/LUN#0/Config/httptunnel/HostPort" 8080
Don't just copy and paste that blindly - there's one thing you must change. You must replace "ubuntu" with the name of your VM. To find out the name open VirtualBox and click on your VM in the left hand panel - the VM name is shown in the list on the right under "General > Name". The identifiers "sshtunnel" and "httptunnel" can also be anything you want.
So what the hell does that do? Well, it instructs VirtualBox to forward any requests on Port 2222 on your OS X will get forwarded to Port 22 on your Guest VM (in my case, Ubuntu). It does the same for HTTP - forwarding 8080 on OS X to port 80 on the VM. Restart your Linux VM if it's started, then do this on Terminal.app in OS X to SSH into your Linux VM:
ssh -p2222 localhost
Remember, although that looks like you're just connecting to your OS X host machine the SSH will actually get tunneled through to your Linux VM. It's a bit clunky though having to type all that, so you could create an alias entry in ~/.ssh/config like so:
Host ubuntu
User
HostName localhost
Port 2222
Once you've done this, you'll be able to ssh into your Linux box like this:
ssh ubuntu
Now that ssh is working, you can do all this fun stuff:
- Install all the software you need using apt (or your other favourite package manager)
- Set up ssh keys between OS X and the VM for passwordless SSH login
- Use scp to copy your .bash_profile, or .vimrc over to the VM to make it feel cosy and comfortable
Finishing Up
Using the VBoxManage tool setting tunnels other than SSH (port 22) and HTTP (port 80) tunnels is easy:
cd /Applications/VirtualBox.app/Contents/MacOS/ ./VBoxManage setextradata "ubuntu" "VBoxInternal/Devices/pcnet/0/LUN#0/Config/ftptunnel/Protocol" TCP ./VBoxManage setextradata "ubuntu" "VBoxInternal/Devices/pcnet/0/LUN#0/Config/ftptunnel/GuestPort" 21 ./VBoxManage setextradata "ubuntu" "VBoxInternal/Devices/pcnet/0/LUN#0/Config/ftptunnel/HostPort" 721
Would for example forward localhost:721 on OS X to and FTP server listening on port 21 on the Linux VM.
Hopefully Sun will fix up Host Networking on OS X in future versions so that this tunneling stuff won't be necessary. It's a minor grumble at the moment, and considering what a wildly brilliant tool VirtualBox is compared with Parallels being heaps faster and open source.
No more painful OS X source builds!