Setting up a local name server on Mac OS X
Monday, November 13, 2006 at 12:17PM [`account_location`](http://dev.rubyonrails.org/svn/rails/plugins/account_location/)
for a couple of applications recently. It's a really nice way to give
individual 'clients' of an application their own domain and when we come to
scaling up, it's a really easy way of splitting customers across several
hosts. So, yeah, very nice. And it's dead easy to deploy in the first instance
-- a couple of DNS records along the lines of:
@ IN A 1.2.3.4
* IN A 1.2.3.4
There you go, every host in that domain points to 1.2.3.4.
However, it's a pest for setting up in your development environment. OK, so
you can edit `/etc/hosts` and add an entry for every single account you happen
to create. This hinders development for me -- each domain *has* to be unique,
so whenever I want to create a new account, I have to do so in Rails, *and* in
`/etc/hosts`. It's also irritating when I'm having to maintain an `/etc/hosts`
file on multiple machines. Unfortunately, the hosts file doesn't support
wildcard records, so we *have* to put every single entry in.
I'm sure there's a better solution on Mac OS X -- maybe there's something smart I could do with the NetInfo database, or maybe I could play with [Bonjour](http://www.apple.com/macosx/features/bonjour/) in some way -- but the easiest thing for me was to set up a name server on my local machine. It's really dead simple. Handily enough, [BIND](http://www.isc.org/index.pl?/sw/bind/) is already installed in the base system, just not configured and switched on. So we just have to do a little configuration. First of all, create the `rndc` configuration to control the name server:
mathie@bowmore:mathie$ sudo -s
bowmore:/Users/mathie root# rndc-confgen > /etc/rndc.conf
bowmore:/Users/mathie root# head -n5 /etc/rndc.conf |tail -n4 > /etc/rndc.key
This creates a key in `/etc/rndc.conf` which allows the `rndc` client to talk to the name server and control it. We then need to tweak the server configuration a little. In the controls section, change the port from `54` to `953` (I don't know why it's different by default, since it doesn't seem to work!). Next up we need to create a stanza in `/etc/named.conf` for the Rails application zone. Add something along the lines of:
zone "rails" IN {
type master;
file "rails.zone";
allow-update { none; };
};
around the other zone stanzas. Save that and move on. Next thing is to create `/var/named/rails.zone`. I started by copying the default `localhost.zone`, winding up with something along the lines of:
$TTL 86400
$ORIGIN rails.
@ 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
*.app1 IN A 127.0.0.1
*.app2 IN A 127.0.0.1
Save that and quit. Finally, we need to convince BIND to start up at boot. Since I'm on Tiger, we have the benefit of `launchd` to handle such mundane tasks. Simply run:
mathie@bowmore:mathie$ sudo launchctl load -w /System/Library/LaunchDaemons/org.isc.named.plist
BIND will start now, and will automatically start from now on at launch. if you're on anything older, I gather it's a case of adding:
DNSSERVER=-YES-
to `/etc/hostconfig`. You can then restart your computer for it to take effect (it would be a good idea to verify it works) or cheat and run:
sudo /usr/sbin/named
to start it for now.
Finally, you need to tell your computer to *use* the newly setup name server. In System Preferences, go to the Network pane. For every one of the connections you use, in every one of the locations you have set up, go to the TCP/IP settings and add `127.0.0.1` as the first DNS server.
Now every time you do a lookup for `foo.app1.rails`, `bar.app2.rails` or, well, anything at either domain, it will resolve to 127.0.0.1. So you can happily browse to and `account_subdomain` will be set to 'rubaidh'. Neat, huh?
Geekery,
Ruby and Rails,
Work
Reader Comments (9)
CpILL: Yeah, that should be the named.conf file. I'll update the text to make that a little more clear. Thanks!
Matthias: With the configuration as above, the DNS server will act as a caching, recursive name server. It will directly query what it reckons are the root servers and cache the results. This gives it network location independence, which is nice. But it might make name lookups a little slower than they'd normally be. I can't say it's bothered me too much so far (though I have had to reload my name server when it's cached a bad record for one reason or another).
Pim:
lwresdis not currently running on my system and it's working fine. I think (I can't remember for sure offhand, because it's been a while since I've used it) thatlwresdserves a separate purpose, acting as a dedicated caching-only nameserver for client applications when the system useslibnss-lwres. It's not normally used on Mac OS X as far as I can tell. (Unless you've been messing with your/etc/nsswitch.conf?)How about using dnsenabler ( http://cutedgesystems.com/software/dnsenabler/ ) or dnsmasq ( http://osx.hyperjeff.net/Apps )?
[...] If you want to be able to do this on your local machine (and you’re on a Mac), you can follow these instructions: http://woss.name/2006/11/13/setting-up-local-name-server-on-mac-os-x/ [...]
[...] http://agilewebdevelopment.com/plugins/account_location And you’ll need to configure your dns with a wildcard domain (*.yourdomain.com) If you want to be able to do this on your local machine (and you’re on a Mac), you can follow these instructions: http://woss.name/2006/11/13/setting-up-local-name-server-on-mac-os-x/ [...]
Great article. Thanks a lot
The last batch of Apple Updates (installed just now) forced a restart. When I did so, the nameserver didn't come back up.
I manually started named... but I have no idea what went wrong, or if it will work in the future. I wonder what they changed?
[...] Setting up a local name server on Mac OS X - [...]
[...] in the /etc/hosts (at least it will not listen). The life saver here was the following link : setting up your own DNS server locally on your [...]
[...] It needs to be configured and linked into the BIND configuration file. Using some code I found at the most helpful place on the net for what I'm trying to accomplish with one addition, I ran this:rndc-confgen > /etc/rndc.confhead -n5 /etc/rndc.conf |tail -n4 > [...]