Using dnsmasq on MacOS to setup a local domain for development
This guide covers using dnsmasq as a local DNS server on MacOS to resolve all URL’s with the .test
domain name to localhost (127.0.0.1).
This can be very useful to developers wishing to setup an efficient local development and test environment on their machine. For example, if http://myproject.com.test resolved to localhost, a local apache, nginx, or other server could respond to the request.
While any DNS server could be employed for this job, dnsmasq is a perfect choice for this type of lightweight local routing.
Regarding the .test
domain, note that this is a recommended choice per the IETF RFC’s (e.g. RFC-2606, RFC-6761). While it’s possible to configure dnsmasq for any arbitrary domain name, only .test
, .example
, .invalid
, and .localhost
are reserved for non-Internet use. A popular choice used to be .dev
until Google purchased the top-level-domain (TLD) and changed how Chrome handles .dev
URL’s.
Install and configure dnsmasq
To get started, use brew to install dnsmasq for your user:
brew install dnsmasq
At the time of writing, the brew package installer creates a sample conf file with all entries commented out. It can be found at ./etc/dnsmasq.conf
under brew’s default install folder.
Execute following commands in sequence to configure dnsmasq to resolve *.test requests to 127.0.0.1:
echo "" >> $(brew --prefix)/etc/dnsmasq.conf
echo "# Local development server (custom setting)" >> $(brew --prefix)/etc/dnsmasq.conf
echo 'address=/.test/127.0.0.1' >> $(brew --prefix)/etc/dnsmasq.conf
echo 'port=53' >> $(brew --prefix)/etc/dnsmasq.conf
The above commands simply append the required lines to the dnsmasq.conf
configuration file.
Next, use brew’s services feature to start dnsmasq as a service. Use sudo
to ensure that it is started when your Mac boots, otherwise it will only start after you login:
sudo brew services start dnsmasq
Add a resolver
Add a resolver for .test
TLD’s:
sudo mkdir -pv /etc/resolver
sudo bash -c 'echo "nameserver 127.0.0.1" > /etc/resolver/test'
This tells your system to use localhost (and therefore dnsmasq) as the DNS resolver for the .test
domain.
Test your configuration
Flush your DNS cache:
sudo dscacheutil -flushcache
sudo killall -HUP mDNSResponder
Check your configuration by running:
scutil --dns
Inspect the output. One of the entries should specify that for domain test
the system will use the nameserver 127.0.0.1
. This means that dnsmasq will now be consulted as the nameserver for any .test
URLs.
Finally, test the full stack by trying to ping random *.test URL’s such as example.test or myproject.test and confirming that they resolve to 127.0.0.1. For example:
ping -c2 example.test
Provides the output:
PING example.test (127.0.0.1): 56 data bytes
64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.022 ms
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.055 ms
OR (in cases where your Mac’s firewall settings are configured to not respond to ping):
PING example.test (127.0.0.1): 56 data bytes
Request timeout for icmp_seq 0
...
The important part to confirm is that example.test
resolved to (127.0.0.1)
.