Setting up a zero config webserver on mac OSX

February 23, 2015

If you have lots of projects on your development computer, you know how annoying it is having to configure your apache VirtualHost and changing your hosts file for a dns record. Well there is a solution. I’ll show you how you can configure apache to do this dynamically and afterwards setup a local DNS server so you don’t have to change your hosts file.

Configuring apache

I’ll presume you already have apache2 up and running and have a basic idea how apache works.

First of you need to find a good place to store all you projects. In my case they are under ~/Projects/web/. Then add a new VirtualHost.

<VirtualHost _default_:80>
  RewriteEngine on

  # Remove "www." from domain names by redirecting.
  RewriteCond %{HTTP_HOST} ^www\.
  RewriteRule ^(.*) %{HTTP_HOST}`$1  [C]
  RewriteRule ^www\.([^\_]*)\`(.*)$ http://$1$2 [R=301,L]

  # Use components of the domain to determine the document root.
  # %0 is the whole domain.
  # %1 is the first part (using dotted delimiters).
  # %-2 is the second to last part.
  ServerAlias *.dev

  UseCanonicalName Off
  VirtualDocumentRoot /Users/[username]/Projects/web/%0/htdocs
  <Directory /Users/[username]/Projects/web/>
    AllowOverride All
    Options All
  </Directory>
  ErrorLog /var/log/apache2/dynamic_error.log

Save your file, enable it and reload apache. You can now create a site called test.dev and place it in /Users/[username]/Projects/web/test.dev/htdocs.

NOTE: If you are using RewriteRules, add RewriteBase /to keep it working.

Setting up a local DNS server

We will be setting this up so that *.dev points to 127.0.0.1. There are 2 option, the easy (using resolver) and the hard (using bind). You only need one to make it work.

Using resolver

Create the following folder.

$ sudo mkdir /etc/resolver

Create a file called dev in this folder.

$ sudo vim /etc/resolver/dev

nameserver 127.0.0.1
domain dev

Reboot to make it all come to life.

Using bind

Bind is a unix DNS server.

Open your terminal and use the sudo bash command to become the super user, not really needed but its easier. After becoming root, generate a new rndc.key

$ su -
$ rndc-confgen -a -c /etc/rndc.key

Creating the actual zone file for your .dev segment.

$ vim /var/named/db.dev

Paste this code and save it.

$TTL    86400
$ORIGIN dev.
@                       1D IN SOA       @ root (
                                        42              ; serial (d. adams)
                                        3H              ; refresh
                                        15M             ; retry
                                        1W              ; expiry
                                        1D )            ; minimum

                        1D IN NS        @
                        1D IN A         127.0.0.1
*       IN      A       127.0.0.1

Please note the trailing dot after the local! If you want your wildcard DNS to be something else, feel free to substitute it with something else. But keep in mind the trailing dot!

Adding the zone to your named config

$ vim /etc/named.conf

Locate a section that starts with ‘logging’ and insert this code before this block.

zone "dev" IN {
        type master;
        file "/var/named/db.dev";
};

Test if the config is right.

$ named-checkconf /etc/named.conf

Check if the zone is created correctly

$ named-checkzone dev /var/named/db.dev

Finally adding it to your mac’s startup list, purely for convenience. If you are a memory freak feel free to start the named server only when needed, but I am lazy and do not want to be bothered with it every single time i reboot.

$ launchctl load -w /System/Library/LaunchDaemons/org.isc.named.plist

Flush your systems DNS cache

$ dscacheutil -flushcache

Open your system preferences,and click network, then advanced button. If needed add 127.0.0.1 to your server list with the + on left and drag it to the top of the list. Make sure you have some fallback servers, like those from you ISP or others like opendns.

Do not set the search domain to the same name as your wildcard dns name, or you will end up looking at your local web server for every failed DNS lookup.

Press ok and test if it works.

$ ping whatever.dev

This should give you something like this:

PING whatever.dev (127.0.0.1): 56 data bytes
64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.031 ms
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.163 ms

I hope it makes your life easier.

comments powered by Disqus