Skip to content

Instantly share code, notes, and snippets.

@ogrrd
Last active April 16, 2024 20:28
Show Gist options
  • Save ogrrd/5831371 to your computer and use it in GitHub Desktop.
Save ogrrd/5831371 to your computer and use it in GitHub Desktop.
Setup dnsmasq on OS X

Never touch your local /etc/hosts file in OS X again

To setup your computer to work with *.test domains, e.g. project.test, awesome.test and so on, without having to add to your hosts file each time.

Requirements

Install

brew install dnsmasq

Setup

Create config directory

mkdir -pv $(brew --prefix)/etc/

Setup *.test

echo 'address=/.test/127.0.0.1' >> $(brew --prefix)/etc/dnsmasq.conf

Change port for High Sierra

echo 'port=53' >> $(brew --prefix)/etc/dnsmasq.conf

Autostart - now and after reboot

sudo brew services start dnsmasq

Add to resolvers

Create resolver directory

sudo mkdir -v /etc/resolver

Add your nameserver to resolvers

sudo bash -c 'echo "nameserver 127.0.0.1" > /etc/resolver/test'

Finished

That's it! You can run scutil --dns to show all of your current resolvers, and you should see that all requests for a domain ending in .test will go to the DNS server at 127.0.0.1

N.B. never use .dev as a TLD for local dev work. .test is fine though.

@c835722
Copy link

c835722 commented Aug 19, 2017

Having .dev in TLD also preventev my docker-machine env dev from functioning.

@eugeneware
Copy link

Remember to NOT delete your old DNS servers from MacOS network preferences. Add 127.0.0.1 to the list and move it to the top. When you hit the + button it deletes the DNS entries by default from the list, so note them down, and add them back in, but add 127.0.0.1 to the top.

@eugeneware
Copy link

eugeneware commented Aug 26, 2017

Also, if the DNS entries you're trying to create don't actually exist, then you don't need to add 127.0.0.1 to your network preferences DNS order. If your domain suffix is blah, make sure that you add the nameserver 127.0.0.1 to /etc/resolver/blah for the OS X resolver fallback to work.

See this for more info.

@matteocng
Copy link

Thanks for this. As previously suggested, it is not recommended to use .dev, see dont use dev for development for additional info and recommendations (tl:dr .localhost, .invalid, .test, .example are discussed).

@johnny77221
Copy link

I couldn't get it work when adding it to LaunchDaemons, even add an execution as user setting
so I'll have to manually run sudo /usr/local/opt/dnsmasq/sbin/dnsmasq --keep-in-foreground after login and it works well
(I am using mac Sierra 10.12.6)

@Bahir
Copy link

Bahir commented Oct 6, 2017

I followed the setup doing my local dnsmasq network listening on Ethernet interface (10.0.0.11).
But after reboot dnsmasq is on the list of running provesses but I have to restart it manually each time I boot up the system.
After that it works.
I have no idea why it is but I have an idea that dnsmasq is runned before Ethernet going up.
That resolves why after restart the service helps.

Copy link

ghost commented Dec 13, 2017

https://stackoverflow.com/a/47744259/6629

from chrome 63+, domain names ending in .DEV get forcibly redirected to https://. It is recommended to use .TEST as the TLD for local domains.

@mcurren
Copy link

mcurren commented Dec 14, 2017

^^ correct

Copy link

ghost commented Dec 19, 2017

Instead of altering the LaunchDaemons manually, you can use the convenient brew services.

@runlevel5
Copy link

FYI Google has claimed the .dev domain, I now use .test instead

@tishma
Copy link

tishma commented Apr 18, 2018

I've had this successfully working a few years ago on yosemite, but recently I realized it fails on sierra.

manually running the dnsmasq binary (instead of loading plist daemon file) helped as it did show the reason why it failed.

brew installation doesn't seem to create /usr/local/var/run/dnsmasq/ dir required for the daemon to run. after creating this dir - it works again.

@g4macgregor
Copy link

I have set everything up accordingly, and have the /usr/local/var/run/dnsmasq/dnsmasq.pid with nobody:nobody. Should this be the same user:group as httpd is running?

@cdaringe
Copy link

missing from these instructions is how to have a domain try to resolve thru dnsmasq first, then continue to use the system DNS resolvers next. i'd love to see a recipe on how to configure that!

@webknjaz
Copy link

@ogrrd please add a big note your gist saying that people mustn't use .dev as it's a gTLD.

@ogrrd
Copy link
Author

ogrrd commented Oct 23, 2020

Thanks everybody for leaving these messages to help people who were caught in this horrifically outdated guide. I feel ashamed that I left it like this for so long to make the internet a more confusing place!

I have removed the contents of this gist now and left the link to what in 2018 seemed to be better.

I want to apologise to anyone who I caused problems for by them following this guide!

@ogrrd
Copy link
Author

ogrrd commented Oct 23, 2020

@ogrrd please add a big note your gist saying that people mustn't use .dev as it's a gTLD.

Done. 😬

@ogrrd
Copy link
Author

ogrrd commented Oct 23, 2020

Change of plan. Seeing as this page comes up for searches, I have amended it with purportedly working contents from the fork by @brablc.

@miraclebg
Copy link

The issue is caused by Internet sharing - disable it and port 53 will not be used by mDNSesponder!

@encryptblockr
Copy link

scutil --dns shows that DNS queries for specific domains should be routed via the specified nameservers but this is not working
what could be wrong?

using macos big sur
followed everything as directed

@brablc
Copy link

brablc commented Apr 18, 2021

And dnsmasq is running:

 $ sudo brew services
Name    Status  User Plist
dnsmasq started root /Library/LaunchDaemons/homebrew.mxcl.dnsmasq.plist

And taking connections?

 $ nmap -p 53 127.0.0.1
PORT   STATE SERVICE
53/tcp open  domain

@eddideku
Copy link

eddideku commented Sep 2, 2022

Whats the significance of the resolver?

Has anyone used dnsmasq to setup a pre-production testing scenario?

For example:

mylivesite.com is on server 1.2.3.4
mylivesite.com is also migrated to a different server with updates on server 2.2.2.2

I can do this in /etc/hosts file easily enough, however I need to make sure subdomains are working, ideally it would be nice to use dnsmasq's wildcard feature that /etc/hosts can't utilize

echo 'address=/.mylivesite.com/2.2.2.2' >> $(brew --prefix)/etc/dnsmasq.conf

Right now, I can't figure out how to do this with dnsmasq, it's routing to the old server (ie 1.2.3.4)

@mcrstudio
Copy link

You should not use .dev or .local if you're developing web applications locally. I stumbled across an issue where my Remix SSR Web App was taking 5 seconds or so to make an API request to the API running on my machine.

https://mywebapp.local -> http://myapi.local

The issue was that .local uses mDNS generally which is reserved for multicasting. This was a cause of my long response times. If you're using dnsmasq for local development, please use .lan.

@michaelmior
Copy link

The .test TLD has been officially reserved by the IETF for testing. I don't think this is the case for .lan.

@brettinternet
Copy link

@imkonsowa
Copy link

Thanks, worked great for me!

@capaj
Copy link

capaj commented Nov 24, 2023

@imkonsowa are you on sonoma? I followed all the commands and I still don't get .test to resolve to my localhost

@imkonsowa
Copy link

@capaj Yes I'm on sonoma, have you configured a webserver to listen and proxy traffic for a .test host?

@mavogel
Copy link

mavogel commented Dec 12, 2023

Setup MacOS Sonoma networking for the .hack TLD. Including this resource I read

  1. https://mjpitz.com/blog/2020/10/21/local-ingress-domains-kind/
  2. https://allanphilipbarku.medium.com/setup-automatic-local-domains-with-dnsmasq-on-macos-ventura-b4cd460d8cb3

and concluded the setup for k8s kind, but it also worked to a local nginx webserver running on port 8088

setup

brew install kubernetes-cli dnsmasq
# to keep it dry
export LOCAL_CUSTOM_TLD="hack"
# register .hack TLD locally
echo "address=/.${LOCAL_CUSTOM_TLD}/127.0.0.1" >> $(brew --prefix)/etc/dnsmasq.conf
# configure the local resolver
sudo mkdir /etc/resolver/
cat <<EOF | sudo tee /etc/resolver/${LOCAL_CUSTOM_TLD}
nameserver 127.0.0.1
EOF
# restart local dnsmasq service
sudo brew services restart dnsmasq
# restart mDNSResponder
sudo killall -HUP mDNSResponder
# verify the new resolver was picked up
scutil --dns
# ... should show $LOCAL_CUSTOM_TLD
resolver #8
  domain   : hack # <- 
  nameserver[0] : 127.0.0.1
  flags    : Request A records, Request AAAA records
  reach    : 0x00030002 (Reachable,Local Address,Directly Reachable Address)

test it with a subdomain of .hack

ping -c 1 nginx.random.${LOCAL_CUSTOM_TLD}
# ...
PING nginx.random.hack (127.0.0.1): 56 data bytes
64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.052 ms

--- nginx.random.hack ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 0.052/0.052/0.052/0.000 ms

run a local docker container on port 8088 to test it

docker run --rm -p8088:80 --name nginx -d nginx
# test it
curl -I nginx.random.hack:8088

HTTP/1.1 200 OK
Server: nginx/1.25.3
Date: Tue, 12 Dec 2023 12:24:58 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Tue, 24 Oct 2023 13:46:47 GMT
Connection: keep-alive
ETag: "6537cac7-267"
Accept-Ranges: bytes

# remove it
docker stop nginx

HTH sb 🎉

@brablc
Copy link

brablc commented Dec 12, 2023

For my personal project I solved this by making my LAN IP static in DHCP server and adding *.lan.mydomain.com wildcard A record to this IP. The advantage is that I can test on mobile devices easily - livereload working like magic on multiple devices. When on the road I use *.lh.mydomain.com A 127.0.0.1 instead.

@datlife
Copy link

datlife commented Jan 10, 2024

If you are running into issue why dig or nslookup still doesn't work with your domain. It turns out they don't use the official system resolver on Mac OS (ref: https://stackoverflow.com/questions/50914268/os-x-etc-resolver-dev-isnt-working-why-not )

Therefore, to test a domain . Use this

dscacheutil -q host -a name argocd.ml-dev.test

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment