The local setup (to rule them all)

At work I have to jump between different web (PHP) projects all the time. So having an environment that allows me to easily add something new, switch to another site and do all of that fast and with as little steps as possible is crucial for my job (and my sanity).

Before today I used a “native” setup for this: install Apache, PHP and MySQL on OS X, add a new vhost with VirtualHostX and add the new site to the /etc/hosts file. That setup ran smoothly for many months and many projects, and hardly gave me any trouble.

With Mac OS 10.10 Yosemite getting released last week, I decided to give my work machine (which is a 15″ retina MacBook Pro) a fresh start. I ran an (extra) back-up, made bootable disk and was off to the races. A formatted disk and 30 minutes later, I had a fresh Yosemite install, ready to be configured.

I decided to use Vagrant this time, because I want to separate my development environment from my operating system as much as possible. That makes it portable and share-able (but that’s a topic for a whole other post). I’ll quote vagrantup.com here:

If you’re a developer, Vagrant will isolate dependencies and their configuration within a single disposable, consistent environment, without sacrificing any of the tools you’re used to working with (editors, browsers, debuggers, etc.).

That sounds pretty good right? Here we go:

  1. Download & install VirtualBox
  2. Download & install Vagrant
  3. Using puPHPet.com I configure a VM running Ubuntu with the usual: Apache, PHP 5.6, MySQL, Mailcatcher.
  4. Make a “Sites” folder in your user profile (/Users/$username/Sites) and add the puphpet file to it
  5. Open a terminal window, go to the Sites folder and run vagrant up to download the vm and run through the install scripts

So now that we have our virtual machine up and running, we have to figure out 2 things: 1) how to direct local traffic to the VM, 2) a fast and easy way to add new virtual hosts.

Having to edit your hosts file for every new project I need to set up is a bit inconvenient (even though apps like GasMask make it super easy). Ideally I’d be able to set a wildcard for a subdomain and all that traffic would just go to the VM, where Apache figures out where to send it. This is where I introduce you to Dnsmasq. Dnsmasq provides network infrastructure for small networks – but what does that mean for this setup? I’m going to use the DNS server in Dnsmasq to route all traffic for a certain subdomain to my VM. Here’s how that’s done:

  1. I’m going asume you have HomeBrew installed
  2. run brew up to make sure everything is up to date.
  3. run brew install dnsmasq
  4. follow the instructions brew gives you at end of the installation (copying the default config files and adding dnsmasq to LaunchDaemons)
  5. find the /usr/local/etc/dnsmasq.conf file and add the follwing:
    address=/dev/127.0.0.1
    In this example we’re pointing all traffic from domains with top level .dev to 127.0.0.1

For my work setup I added the following:
address=/.local.company.tld/192.168.56.101
Note the extra dot in from of the url: that is the wildcard, which is crucial to our setup. The IP address is address of our Vagrant VM.
Lastly, we stop and start Dnsmaq:
sudo launchctl stop homebrew.mxcl.dnsmasq
sudo launchctl start homebrew.mxcl.dnsmasq

  1. Next up, we have to get OS X use Dnsmasq for any requests going to .local.company.tld. Most UNIX-like systems use the file /etc/resolve.conf to control where DNS querries go. OS X allows us to configure extra resolvers in the /etc/resolver/ directory.
    We’ll start by creating that folder: sudo mkdir -p /etc/resolver.
    Then we create run sudo vim local.company.tld to create that file (with same name as the domain we want to “redirect”) in that folder. In that file, we simply add “nameserver 127.0.0.1” to indicate that DNS querries for local. company.tld should be routed to the DNS server at 127.0.0.1 (which is where Dnsmasq runs).

  2. Lastly, we’re going to test our DNS. We’ll use a simple ping command to check if our domain names are still resolving correctly.

ping google.com
ping test.local.company.tld
ping mlkjmlkj.local.company.tld

Now we have wildcard domain pointing to our Vagrant machine, so project1.local.company.ltd, project2.local.company.tld, etc all automatically go to our VM. As a last step, we’ll look at a script to automate the creation of a new VirtualHost for Apache.

I started from this and forked it to fit my needs:

  • By default we run our sites with public/ as DocumentRoot
  • In older projects there might be /www or /html as DocumentRoot
  • Or the site can run completely in the DocumentRoot

 

You can find my version of the script here (I’ll try to keep it updated with the changes I make as I use it more). The script also imports a template it uses for the vhost file, that can be found (and forked) here.

Here are some example of what the script can do for you:

  • vhost.sh facebook will give you a vhost called facebook.local.company.tld, which /var/www/facebook/public for its webroot and a facebook folder in /var/www (which maps to ~/Sites/facebook on your mac)
  • vhost.sh -www facebook will do the same thing, expect the webroot will be www instead of public
  • vhost.sh -root facebook will make a vhost called facebook with /var/www/facebook as its webroot.
  • vhost.sh -l will list all vhosts available on the system
  • vhost.sh -rm facebook will remove the vhost called facebook from your Apache config.

I’ve been running this configuration for about a week now and I’m quite happy with it. It’s stable, fast and easy to add new projects.

If you have your own setup for PHP development or have suggestions for how I can improve this configuration further, feel free to leave them in the comments section.

Happy coding 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *