Running a Linux dev environment on a Mac

Tags: 

I use a Macbook Air as my main Drupal development machine these days. Although this laptop is perfectly capable of running MySQL, Apache and PHP on OSX, I keep all that inside an Ubuntu Linux virtual machine, and use some tricks to maintain the dev server's filesystem directly with OSX applications like Text Wrangler and Finder. It can be surprisingly time-consuming to set up, if you have no idea what you are doing.

First off, I should justify why I am doing this. There are a few reasons:

  1. Keeping the Macbook 'clean'. Holding all the web development stuff I do inside a VM sandbox of some sort means all my configuration management is tidy, and stays off the bare metal OSX. If I break something in Apache, the damage is limited to the VM and not the entire Macbook, which I use for other things.
  2. To develop in an environment more closely resembling production infrastructure. I have always run Drupal on Linux hosts because they behave so well there. Also, thinking from Day 1 in terms of ownership, permissions, etc. outside my local environment keeps the surprises and disasters to a minimum.
  3. All the normal reasons people use VMs. I can snapshot, pause, roll back, migrate, duplicate and backup the entire system. It's easy to control how it exists within various networks, and to tweak disk and CPU allocations.

Summary of the rest of this post

  • Ubuntu server through VirtualBox on a Mac host.
  • Mac OSX kernel extended with OSXFUSE.
  • MacFusion app installed for quick GUI mounting of server filesystem on the Mac.

My configuration at a glance

The host machine is a 2010 Macbook Air with a 2.13GHz Intel C2D, 4GB RAM and 256GB disk inside, running OSX 10.7.x (Lion).

The Virtual Machine hypervisor is VirtualBox, v4.1.8 at the time of writing.

The guest VM is an Ubuntu 10.04 TurnKey Linux LAMP appliance. Turnkey Linux is great - you should check it out.

The basic idea is that my development server lives inside Ubuntu, and that the relevant parts of that filesystem are exposed to the Mac host so I can work using its native tools. I spent a lot of time trying to get this working the other way around - with the Drupal files living natively in OSX and being shared with Ubuntu through VirtualBox Guest Additions.  This almost worked - but I could never get permissions to behave properly, and sometimes the mounts would behave unpredictably.

The secret sauce: sshfs

While Googling for solutions to some of the Virtualbox filesystem sharing problems I had been having, I found a blog post by Greg "Greggles" Knaddison with this heartening line:

I spent a bunch of time messing with shared folders and couldn't get it to work.

Greg went on to describe an alternative method using sshfs.

The idea of sshfs is to allow a mount over SSH.  With this, as long as I can SSH between guest and host, I can mount the guest filesystem on the host. Any activity is transferred over SSH immediately -- a nagging problem if I use it to edit large files over a regular internet connection, pure cream if I'm editing small web files against a VM running locally. Hooray!

Installing the Virtual Machine server with VirtualBox

I won't explain everything about installing a VM because the rest of the Internet has it covered.  I chose Ubuntu and VirtualBox because they work, are well documented and I have a comfort factor based on some experience.

Download your preferred Linux installer and create a new Virtual Machine. When configuring the network adapters I have Adapter 1 running as a host-only adapter so I can always reach the VM from the host, and Adapter 2 as NAT so the VM can take advantage of whichever LAN or WAN the host is using - whether that is my home wired network, wifi, or tethered 3G from my phone.  In the occasional circumstance where I want to connect to the VM from a Windows box at home (e.g. Internet Explorer testing), I can enable Adapter 3 as a bridged adapter and the VM will obtain its own IP address from the home router.

Changes to the Mac

Once things are running smoothly you should be able to ssh from the Mac Terminal to the VM.  Once you have Apache set up and serving files, you'll probably want to edit your hosts file on the Mac so you can call the VM's web server. From the Mac terminal, type:

sudo nano /etc/hosts

Add a line similar to this for each website you are serving. Assuming you have a host-only adapter running on Adapter 1, ensure your VM's eth0 IPv4 address is reflected.

192.168.56.101     your-dev-site-name-here

Now you should be able to browse to http://your-dev-site-name-here/ in a browser and your server will hand you back the page you've always wanted.

OSXFUSE - successor to MacFUSE

Greg's post was written in 2009 and described an OSX kernel extension and toolset called MacFUSE. This project has since been discontinued; its closest successor/fork is OSXFUSE which has maintained a compatibility layer with MacFUSE. Installing OSXFUSE is simple, and described elsewhere so I won't go into that here.

There is also a convenient GUI app which takes advantage of MacFUSE/OSXFUSE.  In an example of namespace-grabbing genius, it is called Macfusion. The Macfusion.app lets you set up as many distinct connections as you might need to various places. You nominate the host, username, optional password if you don't have key pairs set up, and a point on the remote filesystem to serve as the base of the mount. You can nominate a mount point on your OSX filesystem but by default it will drop it in /Volumes alongside your main hard disk partition, and will throw an icon on your desktop if your Finder preferences allow the desktop to show connected servers.

I followed the hints on a great blog post by Chandima Cumaranatunge to select the right options in Macfusion to prevent nasty Mac hidden files being generated back on the server, etc. That post has all the nice screenshots you're wishing I'd included here.

I did run into a couple of minor bugs with Macfusion - namely it would get stuck when deleting presets, leaving a messy list of trial-and-error connections listed.  These can be deleted manually if you know where to look