How can we help?
LocalDNS is a small, transparent developer tool. Most questions are answered below — and because it's open source, you can always read exactly what it does.
Get help
Report an issue
Found a bug or have a request? Open an issue on GitHub — the fastest way to reach the developers and track a fix.
Read the docs
Architecture, per-OS setup, the CLI, and testing notes all live in the repository's README and docs — the source of truth.
Get the latest build
Downloads for macOS (dev build), Windows and Linux are on the Releases page, with changelogs for every version.
Quick start
- Install & open LocalDNS. The app appears in your menu bar (macOS) or system tray (Windows/Linux).
- Add a rule. Go to Rules → Add Rule, enter a pattern like
*.myapp.testand a target such as172.30.0.3, then save. - Verify it answers. In a terminal:
dig @127.0.0.1 -p 15353 api.myapp.testshould return your address. Try a name you didn't configure to seeNXDOMAIN. - Let your system use it. Complete the one-time zone registration (see macOS below), then every app — browsers included — resolves your names.
On headless Linux, the CLI does the same thing: localdns add '*.myapp.test' 172.30.0.3 && localdns serve.
macOS: the one-time setup
A sandboxed Mac App Store app can't write to /etc/resolver on its own, so LocalDNS uses the same App-Store-safe pattern as other hosts-file managers: it asks you to run one command, once.
- In the app's Setup panel, copy the command it shows (a
sudo mkdir+chmodthat grants your user access to/etc/resolver) and run it in Terminal. Your password is entered in Terminal — the app never sees it. - Back in the app, pick the
/etc/resolverfolder once in the open panel. LocalDNS stores a security-scoped bookmark and writes its zone files directly from then on — no more prompts.
Until you do this, the server still runs and answers on 127.0.0.1:15353 — macOS just won't route system lookups to it yet. LocalDNS only ever touches files it created (each begins with a # LocalDNS marker); anything else is reported as a conflict and left alone.
Troubleshooting
A name isn't resolving in my browser
- First confirm the server itself answers:
dig @127.0.0.1 -p 15353 <name>. If that works but the browser doesn't, the zone isn't registered with your system resolver yet — complete the setup step for your OS. - Check the rule is enabled and the pattern matches.
*.myapp.testmatchesmyapp.testand any subdomain depth; an exact rule matches only that name. - Browsers and the OS cache DNS. Try a fresh request, a new tab, or restart the browser.
“Managed elsewhere” next to my zone
Something other than LocalDNS already registers that zone (another resolver file, an NRPT rule, or a routing domain). LocalDNS never overwrites state it didn't create. Remove the foreign registration, or choose a different zone.
Port 53 conflict (Windows)
Docker Desktop or WSL may already hold 0.0.0.0:53. LocalDNS avoids the fight by binding a specific loopback address (127.65.43.53:53) plus 127.0.0.1:15353, which coexists with them. If a rule still doesn't resolve, confirm the localdns-helper service is present (it's demand-start and stops itself when idle).
Linux: zone routed but not answering
LocalDNS registers zones with systemd-resolved on a dedicated localdns0 link. If names don't resolve, check that localdns-agentd is active and that systemd-resolved is your stub resolver. The agent re-applies its configuration on boot and after a resolved restart.
Nothing works after a rule change
Use the built-in Self-Test (the status orb) — it fires a real query at the server and reports the result. LocalDNS re-syncs zones automatically when rules or the port change; if you're on the CLI, localdns serve hot-reloads on a file watch.
Uninstalling & cleanup
Choose “Unregister All Zones” in the app to remove every registration LocalDNS created, then delete the app. On macOS you can also enable “remove on quit.” Because LocalDNS only owns state it created (marked files, tagged NRPT rules, its dedicated link), uninstalling leaves the rest of your resolver configuration exactly as it was.
Privacy & security
LocalDNS collects nothing and talks to no server; the DNS listener is loopback-only. For the full details, see the Privacy Policy. Because the app is open source, you can audit every claim in the source code. Found a security concern? Please report it privately via a GitHub security advisory on the repository rather than a public issue.
Still stuck?
Open an issue at github.com/sibidharan/localdns/issues with your OS and version, the rule you configured, and what dig @127.0.0.1 -p 15353 <name> returns. That's usually all it takes to pin down the problem quickly.
Prefer email? Write to support@selfmade.ninja — no account needed — and we'll help you out.