Create a folder testsite.dev in your ~/Sites folder and immediately access it with your browser by using http://testsite.dev, without changing your apache config or adding sitenames to your DNS or /etc/hosts file. That's what you can do after following the instructions in this post!

Background

Most of the time I've been using specific vhost files per webdevelopment project in a vhost folder of which all vhost files will be included. All development sites are added to the /etc/hosts file, so I could access them by a friendly-name lie http://dlmax.dev.

An article by Blain Smith on his local development setup made me rethink my own setup: "Can't I just configure it to add the domainnames to the local DNS resolution too, so I only have to create a folder and immediately be able to access the site?"

Apache configuration

Current setup

I'm using the included Apache included in OSX Mountain Lion (10.8) and modified it, so it's using 1 conf file per vhost in the /etc/apache2/vhosts folder. These get included at the end of the file /etc/apache2/httpd.config with the line:

Include /private/etc/apache2/vhosts/*.conf

in the vhosts folder I've created a file 1_default.conf that contains the following:

NameVirtualHost *

<VirtualHost *>
    ServerAdmin mwesten@localhost
    DocumentRoot "/Users/mwesten/Sites"
    ServerName max.local
    ServerAlias localhost
</VirtualHost>

An example of the other files, in this case dlmax.conf then contains:

<VirtualHost *>
    ServerAdmin mwesten@localhost
    ServerName dlmax.dev
    DocumentRoot "/Users/mwesten/Sites/dlmax"
    Options -Indexes +FollowSymLinks
</VirtualHost>

Changes to this setup:

In /etc/apache2/httpd.config change the line that calls all *.conf files in the vhosts folder, to only call the virtual.conf

Include /private/etc/apache2/vhosts/virtual.conf

now create the etc/apache2/vhosts/virtual.conf to use some wildcards:

NameVirtualHost *
UseCanonicalName Off

<VirtualHost *>
  VirtualDocumentRoot "/Users/mwesten/Sites/%0"

  <Directory "/Users/mwesten/Sites">
      Options Indexes FollowSymLinks MultiViews
      AllowOverride All
      Order allow,deny
      Allow from all
  </Directory>
 # If you are experiencing problems with the PHP DOCUMENT_ROOT setting, create a
 # PHP file containing the following lines:
 #   <?php
 #    $_SERVER['DOCUMENT_ROOT'] = str_replace($_SERVER['SCRIPT_NAME'], '', $_SERVER['SCRIPT_FILENAME']);
 # and uncomment the following line, pointing to the just created PHP file:
 #   php_admin_value auto_prepend_file /Users/mwesten/Sites/setdocroot.php

</VirtualHost>

DOCUMENT_ROOT problems with PHP

If you are experiencing problems with your DOCUMENT_ROOT server variable, uncomment the php_admin_value line in the virtual.conf file. Add the file setdocroot.php to the path specified above and put the following in, to fix the DOCUMENT_ROOT problem described in this apache bugreport

<?php
$_SERVER['DOCUMENT_ROOT'] = str_replace($_SERVER['SCRIPT_NAME'], '', $_SERVER['SCRIPT_FILENAME']);

Get the local DNS names working

Because the /etc/hosts file doesn't parse wildcards, we cannot add something like: 127.0.0.1 *.dev.

The only option is to install a local DNS server like bind or a DNS proxy like DNSMasq.

I'm using DNSMasq, because it's the easiest to configure and less prone to configuration errors.

Install and configure DNSMasq

I'm using Homebrew as my package manager, so if you don't use one, or use another one, you should install brew(to keep it easy) or try to follow the next steps based on your package manager.

brew install dnsmasq

Then create a textfile /usr/local/etc/dnsmasq.conf and add the following line, to redirect all *.dev sites to the local ip 127.0.0.1:

address=/.dev/127.0.0.1

Now make dnsmasq start on system-startup and start it now:

sudo cp /usr/local/Cellar/dnsmasq/2.63/homebrew.mxcl.dnsmasq.plist /Library/LaunchDaemons
sudo launchctl load -w /Library/LaunchDaemons/homebrew.mxcl.dnsmasq.plist

Configure OSX to use your local system as first DNS server

Enter your network preferences and note the DNS servers named there. In my case I'm using my router, so 192.168.10.1. Now add your loopback IP (127.0.0.1) first and then your previous addres.

Now if you try to ping some address ending in .dev it should give a reply like this:

$ ping thisisatestdomain.dev
PING thisisatestdomain.dev (127.0.0.1): 56 data bytes
64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.056 ms
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.079 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.101 ms
64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.075 ms
64 bytes from 127.0.0.1: icmp_seq=4 ttl=64 time=0.094 ms

--- thisisatestdomain.dev ping statistics     5 packets transmitted, 5 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 0.056/0.081/0.101/0.016 ms

Pinging to www.google.com should also work, so we know external name resolutions works well too.

Adding a new local site

Adding a site is now as easy as creating a new folder in the ~/Sites folder with the name of the local sitename, so for http://dlmax.dev you would create the dlmax.dev folder.

Previous Article Next Article