using dnsmasq on mac os for local development


Are you also editing your /etc/hosts file on you mac to have development domains? Are you annoyed of not being able to have wildcard domains? – If you answer yes than you are probably like me and have just been too lazy in the past to find a better solution.

While trying out kubernetes locally, with the help of minikube, I finally dug into finding a better solution – dnsmasq. To my surprise it was harder to setup than expected, especially to get it working with minikube. Therefore here a few steps to setup dnsmasq on mac os:

some background

Dnsmasq is a lightwight service offering, amongst other things, a local DNS server. Is is quite popular and easy to setup – if there wouldn’t be some mac os specifics.
On mac os there is already a DNS server running called mDNSResponder. In Yosemite apple actually removed it only to reintroduce it again with El Capitan and it is still present in Mojave. Every DNS request will either be answered by mDNSResponder or forwarded to an upstream DNS server and it listens on the default DNS port, 53.

install and configure

The most convenient way to install dnsmasq on mac is brew:

brew install dnsmasq

The next step is to configure dnsmasq and start it. 
We do let dnsmasq only listen on the loopback interface and run on a none standard port 5354: 

echo "listen-address=127.0.0.1" >> $(brew --prefix)/etc/dnsmasq.conf
echo "port=5354" >> $(brew --prefix)/etc/dnsmasq.conf
sudo brew services start dnsmasq

This was already enough to have dnsmasq running.
Too serve a custom DNS entry we need to first add the entry to the dnsmasq configuration and configure mDNSResponder to forward this domain to dnsmasq.
A practical approach is to foward e.g. “*.local” to dnsmasq. This way you only have to configure mDNSResponder once and your specific entries to dnsmasq.
mDNSResponder is looking for files in “/etc/resolver”, while the name of the file is the corresponding domain to configure. Very important to know, mDNSResponder does load files automatically, but only at creation time! So don’t get frustrated if changes you make to the files don’t get picked up automatically.

sudo mkdir -v /etc/resolver
sudo tee -a /etc/resolver/local >> EOF
port 5354
nameserver 127.0.0.1
EOF

Using the scutil tool you can validate the effective configuration of mDNSResponder.

scutil --dns

Output should include something like the following:

resolver #9
  domain   : local
  nameserver[0] : 127.0.0.1
  port     : 5354
  flags    : Request A records, Request AAAA records
  reach    : 0x00030002 (Reachable,Local Address,Directly Reachable Address)

Lastly we can add our custom domain entries to dnsmasq:

# *.minikube.local
echo "address=/.minikube.local/192.168.64.11" >> $(brew --prefix)/etc/dnsmasq.conf
# testserver.local
echo "address=/testserver.local/192.168.1.9" >> $(brew --prefix)/etc/dnsmasq.conf
sudo brew services restart dnsmasq

I hope this helped you! Happy developing!

Leave a comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.