A tiny local DNS that made localhost names work across my devices — and the day the VPN broke it

How I stopped fighting /etc/hosts, stopped typing IPs, and made dev services reachable from phones and other machines using dnsmasq — plus the VPN outage that taught me the limits.

Written by: Arjun Malhotra

Open laptop with code editor visible on the screen on a wooden desk
Photo by Brooke Cagle on Unsplash

It was 11:30pm, I had demoed a new payment flow to a client over Meet, and the final step required a quick test from my phone because UPI redirects behave differently on WebView. I opened my phone’s browser, typed my laptop’s IP, and watched the redirect go to the wrong domain — cookies rejected, CORS errors everywhere. My laptop worked. My phone didn’t. My colleague on the network couldn’t even resolve the hostname I was shouting across Slack.

I’d been lazily juggling /etc/hosts entries for years — one on my laptop, one on the office machine, one on a VM. It worked until it didn’t. Every time I switched networks, cloned a new service, or handed my laptop to someone for a quick test, I rewrote IPs and cursed. I wanted predictable, human names like payments.local.dev to mean the same machine from any device on my desk. I wanted SSL certs that didn’t feel like a circus. I wanted to stop asking people “Did you add 192.168.1.13 to your hosts file?”

So I set up a tiny local DNS using dnsmasq. It solved almost everything. Until the day the VPN broke it.

Why local DNS instead of mDNS or exposing a tunnel I tried mDNS/Bonjour first. It sort-of works for Macs, breaks for many Android browsers, and bleeds into weird name collisions when someone else in the office runs a machine advertising “mypc.local”. Exposing a public tunnel (ngrok, expose) is great for sharing, but I don’t want ephemeral public endpoints for every internal service, and mobile UPI flows sometimes refuse tunnels.

A tiny DNS gives predictable names, works for every device that can set DNS (phones, other laptops, routers), and plays well with local TLS when paired with a dev CA.

How I actually run it (the short, practical version) I run dnsmasq on my primary dev box. On Linux that meant:

On macOS I run dnsmasq through Homebrew and use /etc/resolver to point .dev-local to 127.0.0.1: it means my Mac resolves the names locally, and I then set the router to give my Mac’s LAN IP as DNS to other devices.

Why it stuck

The failure: VPN, resolv.conf, and a headless CI job Two months in we had a late-night deploy. I had a quick smoke test script that hit several local staging endpoints; it ran on my laptop because I use the same machine for quick checks. At 2am I reconnected to the company VPN (we use a corporate split-tunnel policy). The VPN’s DNS push replaced my DNS server. Suddenly payments.dev-local resolved to something else — or not at all. My smoke test hit a corporate proxy that returned HTML instead of JSON. The deployment failed the test. I had to dig through /etc/resolv.conf, restore the dnsmasq entry, and then re-run.

That taught me two hard lessons:

  1. dnsmasq works until another network entity (VPN, corporate DHCP) overwrites your DNS. If you don’t detect that, your tests silently fail.
  2. Running dnsmasq on your laptop ties development to that machine. If you want shared availability when the laptop sleeps, you need a router or tiny always-on box (Raspberry Pi, a ₹3,000 router that supports custom DNS) as the authoritative resolver.

The pragmatic fixes I adopted

Tradeoffs and annoyances (the things no one tells you)

What I actually walked away with Local DNS (dnsmasq) turned ad-hoc, error-prone testing into predictable, name-driven workflows. It made phone testing less painful, SSL less fiddly, and demos less embarrassing. But it also reminded me that “local” tools are brittle when network policies change. The real win wasn’t the tool itself — it was adding tiny safety rails: a quick DNS check in scripts and a decision point (laptop DNS for personal convenience, Pi/router DNS for shared reliability).

So if you demo UPI redirects from your phone, or if you get sick of telling teammates to edit hosts files: try a small dnsmasq setup. But add the two-second resolver check before anything critical. It saved me more time than switching to any single fancy tool ever did.