Back to Blog

Get in Touch

Using BIND locally on OS X for easy access to subdomains

By Jon Kinney June 2, 2010 in rails, subdomain

Missing

With the advent of plugins like subdomain-fu, it has become quite easy to develop web applications that use subdomains. For the latest project I'm working on at Intridea, I need to allow clients to custom brand a web application with their company's look and feel; I chose to use subdomains to achieve this goal.

In a staging or production environment, this involves modifying the DNS and adding a wildcard entry that points all hosts to the primary domain. For example, most hosted DNS management systems allow for creating new entries via some sort of GUI as seen here at the name.com DNS management screen:

NameDotCom management console

In this case simply add "*" in the Record Host column, and the server's IP in the Record Answer column. Then with a slight modification to the VirtualHost:

ServerAlias *.appname.com

you're usually in business.

To develop and test the subdomain aspect of a web application like this, developers usually edit their hosts file locally and add an entry that piggybacks on the localhost entry. On Mac OS X the hosts file is found at "/etc/hosts" and the setup I described might look something like this:

127.0.0.1       localhost appname.local client1.appname.local

While this works for sites where there are only a few pre-defined subdomains, it is less desirable for situations where the application itself has the ability to introduce a new subdomain dynamically. When you want the app to be able to respond to any subdomain in development, it's best to setup a local DNS server that will be able to handle a request to any subdomain without the need to continually modify configuration files.

To do this locally on OS X I'll show you how to use the built in DNS server BIND. BIND should also be included with most flavors of Linux so this guide may work there as well, but there may be slight differences in the configuration files which could create small inconsistencies. Off hand, I know that OS X/Unix is pickier about tabs and spaces in it's configuration files whereas Linux, for the most part, will accept any formatting. Let us know in the comments if you are able to get this setup working in a Linux environment!

A few notes on the setup instructions:

You'll be editing files at the command line so make sure you are somewhat comfortable with Terminal before proceeding. As always, I recommend that you make backups of any configuration files you'll be editing so that you can reference or revert to them if necessary without digging around on another mac or the web to find a suitable restore file. You can backup any file by using the cp command and appending .bak (or similar) to the end of the file like so:

$ sudo cp /etc/named.conf /etc/named.conf.bak

You'll also need to have root permissions to edit the files referenced in this guide so to elevate your terminal session issue the following command (the rest of the guide will assume elevated root permissions):

$ sudo -s

BIND is disabled by default on OS X, but it's easy to configure and turn on. Follow these steps to a happier development environment.

  1. Create the "rndc" configuration file by issuing the following command:

    $ rndc-confgen > /etc/rndc.conf
    
  2. Create a keyfile that will allow the rndc client to talk to the name server and control it.

    $ head -n5 /etc/rndc.conf |tail -n4 > /etc/rndc.key
    
  3. Edit the /etc/named.conf file to add a zone for the application. The zone can be named whatever you want, I'll call it "appname.local", it looks like this:

    zone "appname.local" IN {
      type master;
      file "appname.zone";
    };
    

    and I placed it between the "localhost" zone and the "0.0.127.in-addr.arpa" zone in my named.conf file.

  4. To make sure the named.conf file is setup properly use the built in tool checkconf:

    $ named-checkconf /etc/named.conf
    

    If this returns nothing then the named conf file is syntactically correct.

  5. Create the zone file in "/var/named/appname.zone". It should look like this (make sure you have the spaces/tabs the same!):

    appname.local. 7200    IN       SOA     appname.local. root.appname.local. (
              20100601 ;    Serial (a date in this case)
              15      ; Refresh every 15 minutes
                3600    ; Retry every hour
                3000000 ; Expire after a month+
                86400 ) ; Minimum ttl of 1 day
                  IN      NS      appname.local.
                  IN      A       127.0.0.1
    *.appname.local.        IN      A       127.0.0.1
    
  6. To make sure the zone file is setup properly use checkzone:

    $ named-checkzone /var/named/appname.zone
    

    It should return something like:

    zone appname.local/IN: loaded serial 20100601
    OK
    
  7. After the zone file is setup you need to tell BIND to start when the machine boots. Issue the following command:

    $ launchctl load -w /System/Library/LaunchDaemons/org.isc.named.plist
    
  8. Set up your machine's network adapter's DNS to look locally so BIND will resolve first. On Mac OS X go to System Preferences and edit each network adapter that you use, modifying the DNS settings to have "127.0.0.1" as the DNS server.

    PICTURE OF AIRPORT SETUP FOR SNOW LEOPARD

  9. Finally startup BIND and Flush the DNS Cache:

    $ sudo /usr/sbin/named
    $ sudo dscacheutil -flushcache
    

    If the above commands don't seem to work then try rebooting your machine to make sure BIND is properly started.

Note: If you're using passenger locally on OS X you'll also need to modify your VirtualHost file to have an alias. I'm using the passenger preference pane which makes this dead simple:

PICTURE OF THE PASSENGER PREF PANE WITH THE ALIAS SPECIFIED

You can also edit the VirtualHost file directly and specify the ServerAlias if necessary.

You should now be able to visit any subdomain of your local app and have it resolve!

Medium

Jon Kinney

Jon has been developing web applications both large and small since 2004. The first programming language that actually captured his attention was Perl, which he learned during a web programming course at the University of Wisconsin-Eau Claire, a school from which he later graduated with a degree in Management Information Systems. In his studies, Jon decidedly took the programming track of his chosen major and also learned VB, C#, PHP, and even JSP, but it was his independent pursuit of Ruby beginning in 2006 that really solidified his love for creating amazing things with code. After spending the beginning of his career pursuing Ruby in large Microsoft based consulting firms, Jon is excited to be working for the open source focused team at Intridea. During his free time Jon loves to spend time with his family, record and mix music for local ensembles and also plays in a recreational hockey league during the winter.

More posts by Jon Kinney

Jon Kinney

Captain Hammer told me they call it bash
Jon Kinney

One of the great features of older Macintosh keyboards was the ability to ...

Jon Kinney

In a staging or production environment this involves modifying the DNS and ad...