Self-hosted service
razvandimescu/numa avatar
razvandimescu/numa

Numa: a single-binary DNS resolver with .numa service domains and ODoH

Portable DNS resolver in Rust — .numa local domains, ad blocking, developer overrides

1,443 stars105 forksRustMIT

At a glance

What is it?
Numa bundles ad blocking, local service naming, DNSSEC validation and an ODoH relay into one Rust binary. It is aimed at developers who want .numa hostnames and portable DNS without running a Pi-hole or a cloud account.
Who is it for?
Adopt Numa if you want .numa service names, ad blocking and a DNS-over-TLS listener from one binary, and you are willing to run it with root privileges on port 53. Skip it if you need a mature web control plane with per-client policy or you cannot tolerate a project whose documentation you must read before trusting the Windows binding behaviour.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The problem Numa targets: local names and portable blocking

Two problems sit behind this project. The first is naming local services. A developer running a Vite frontend on port 5173 and an API on 8000 normally edits /etc/hosts, generates certificates with mkcert, or puts nginx in front. Numa instead lets you register a service and reach it as frontend.numa over HTTPS with a certificate it issues itself. The README states that WebSocket passthrough works, which matters for hot module reload. The second problem is ad and tracker blocking that follows the laptop. Pi-hole and AdGuard Home assume a machine that stays on one network. Numa is described as portable: run it on a coffee shop or hotel network and the blocking still applies because the binary is local. The audience is developers and technically comfortable users who want both behaviours without maintaining a separate DNS host.

Resolution modes and where queries actually go

Numa exposes three resolution modes. In forward mode, the default, it acts as a transparent proxy to your existing system DNS, adding caching and ad blocking on top. The README is explicit that captive portals, VPNs and corporate DNS are respected in this mode, which is the pragmatic default for a laptop that moves between networks. In recursive mode, Numa resolves from root nameservers itself, so no upstream resolver sees the full query pattern. Adding [dnssec] enabled = true turns on chain-of-trust validation: RRSIG signatures, DNSKEY verification, DS delegation and NSEC/NSEC3 denial proofs. The third mode, auto, probes root servers at startup and falls back to encrypted DoH when they are unreachable. That fallback is the interesting design decision, because a network that blocks port 53 to root servers pushes you back to an encrypted upstream, which reintroduces a party that can see your queries. The README does not state which DoH provider is used in auto mode, and that is worth checking before you rely on it. Blocking itself comes from the Hagezi Pro list, refreshed daily according to the documentation.

Getting it running: install paths, port 53 and the Windows binding quirk

Installation is platform-specific. macOS uses brew install razvandimescu/tap/numa, Linux uses a curl install script from the repository, Arch has pacman -S numa, and cargo install numa works everywhere. Docker images are published at ghcr.io/razvandimescu/numa for linux/amd64 and linux/arm64. The foreground command is sudo numa, because port 53 requires root or administrator rights. The dashboard is served at http://numa.numa, with http://localhost:5380 as the fallback address. System integration is a separate step: sudo numa install on macOS and Linux registers a launchd or systemd service, while on Windows numa install must run as administrator and requires a reboot. One Windows detail deserves attention. The built-in Dnscache service owns 127.0.0.1:53, so Numa binds 127.0.0.2:53 instead and installs an NRPT rule to route queries there. If you edit the config on Windows, bind_addr and api_bind_addr must point at 127.0.0.2, not 127.0.0.1. That is a real footgun for anyone copying a Linux config across. Configuration can also live in numa.toml, and the Docker instructions show mounting it at /root/.config/numa/numa.toml.

Local services, TLS and the certificate trust problem

Services are registered over the HTTP API, for example a POST to localhost:5380/services with a JSON body naming the service and its target_port. The README also mentions path-based routing, so app.numa/api can map to port 5001, and LAN discovery over mDNS so a service registered on one machine resolves from another. The DNS-over-TLS listener on port 853 has two certificate modes. The default generates a local CA, and numa install adds it to the system trust store on macOS, Linux and Windows. The README notes that Firefox keeps its own NSS store and ignores the system one, so HTTPS for .numa services in Firefox needs manual trust of the CA. The alternative is bringing your own certificate via [dot] cert_path and key_path, for instance a Let's Encrypt certificate obtained through a DNS-01 challenge on a domain pointing at the Numa instance. In that mode clients connect with no trust-store setup. ALPN "dot" is advertised and enforced in both modes, and a handshake with mismatched ALPN is rejected as a cross-protocol confusion defense. Phone setup is handled by numa setup-phone, which prints a QR code and requires [mobile] enabled = true in numa.toml.

ODoH relay mode and what it does not hide

Running numa relay turns the same binary into a public ODoH endpoint, following RFC 9230. ODoH separates the party that knows your identity from the party that knows your query, which is the point of the protocol. The README argues that the curated DNSCrypt list currently has one surviving relay, so each new deployment expands the relay set. That argument is about ecosystem supply, not about your own privacy, and the distinction matters. If you run a relay, you are providing a service to others; your own queries are not anonymised by that act. The README also does not describe what logging a relay keeps, how it is rate limited, or what abuse controls exist. For a public endpoint those are the questions an operator needs answered before exposing it, and the supplied material does not answer them. Treat relay mode as something to investigate in the source and packaging directory rather than something the README settles.

Where Numa is the wrong tool

The comparison table in the README positions Numa against Pi-hole, AdGuard Home and Unbound, and the honest reading is that it is not a drop-in replacement for any of them. Pi-hole and AdGuard Home are built around a household or office deployment with a web control plane, per-client policy and a long operational history. Numa's dashboard exists, but the README does not describe per-client rules, scheduled blocking or group policies, which are standard in AdGuard Home. If you administer DNS for other people, those gaps matter more than the .numa convenience. Unbound is the closer comparison on the resolution side, and it is a dedicated recursive resolver with a much longer track record and a configuration surface that operators already know. Numa's recursive mode is described as optional rather than the default, and the README does not present throughput or cache behaviour figures, so there is no basis here for claiming it performs like Unbound under load. The other limitation is operational: port 53 requires root, the binary runs as a system service, and on Windows it reconfigures DNS routing through an NRPT rule. On a managed corporate machine, that combination may simply not be permitted.

Maintenance, release cadence and licence

The repository shows three releases in roughly three months: v0.21.0 in June 2026, v0.22.0 in July, v0.23.0 in August, with the last push in September 2026. That cadence implies you should expect to upgrade regularly rather than pin and forget. Because Numa runs as a system service and installs a CA into the system trust store, an upgrade is not a purely local operation: on macOS and Linux the service is managed by launchd or systemd, and on Windows the install path involves an administrator step and a reboot. The blocklist refresh is described as daily, so that part maintains itself. The project is MIT licensed, which permits commercial and private use and modification, provided the licence text is retained. Note that the licence covers the code, not the Hagezi blocklist that Numa downloads, which has its own terms; if you redistribute a build with the list embedded, check that separately. Nothing here is legal advice. The zero-DNS-library claim in the README also carries a maintenance implication: protocol bugs are the project's to fix, not an upstream crate's, so watch the issue tracker around DNSSEC and ODoH changes.

Editorial conclusion

Adopt Numa if you want .numa service names, ad blocking and a DNS-over-TLS listener from one binary, and you are willing to run it with root privileges on port 53. Skip it if you need a mature web control plane with per-client policy or you cannot tolerate a project whose documentation you must read before trusting the Windows binding behaviour. Verify first that your platform's install path works: run sudo numa install, open http://numa.numa, and confirm that [mobile] enabled = true is present before running numa setup-phone.

Official sources

  1. Issues
  2. License: MIT
  3. razvandimescu/numa on GitHub
  4. README
  5. Releases
Community notes

Community notes