For a good number of years I was using Basecamp’s Pow for local web development
and one of my favourite features was the in built local DNS resolver that meant
*.dev would resolve to
127.0.0.1. This mean that I had a unique
hostname for every site I was building and running locally which I have found
Unfortunately Pow no longer sees active development (the GitHub repo has been archived) so I wanted to see if I could set up the same kind of local resolver on my Mac without using it.
It turned out to be pretty straightforward!
Note: We’re using
.localhost instead of
.dev because Google own the
TLD and in 2017 they added an HSTS rule to Chromium that forces any
domain to use HTTPS. As you can imagine, this is not ideal for local development
so web developers everywhere had to adjust their setups.
First of all we need to install Dnsmasq. This will handle the local name resolution. If you’re using Homebrew this is dead simple:
$ brew install dnsmasq
Then we need to configure it to resolve any domain name that ends in
.localhost to resolve to
Uncomment the following line:
# /usr/local/etc/dnsmasq.conf conf-dir=/usr/local/etc/dnsmasq.d
Add the following file to the Dnsmasq configuration directory:
# /usr/local/etc/dnsmasq.d/localhost address=/.localhost/127.0.0.1
dnsmasq as root (It needs to be running as root to be able to bind to
$ sudo brew services start dnsmasq
Next we need to tell macOS about the local resolver.
Add the following file (You will need to do this as
# /etc/resolver/localhost nameserver 127.0.0.1 domain localhost search_order 1
And voila! Any domain ending in
.localhost should now resolve to
We can test this with a ping:
$ ping foobar.localhost PING foobar.localhost (127.0.0.1): 56 data bytes 64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.122 ms 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.262 ms 64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.281 ms
So why is this useful?
That’s a very good question! Here’s some of the reasons I’ve found:
- If you’re developing an app that relies on a number of small services it can be useful to differentiate them by domain.
- It makes OAuth callback URL’s more readable.
- It’s useful for external services that require a domain name to authenticate. A good example of this is font services such as Typekit or Hoefler & Co.
- It just looks pretty up there in the URL bar!