Skip to content
fmtrPublic

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

56 Commits

Folders and files

Repository files navigation

hold: HOme Lab DNS

hold is a small, ad-blocking DNS server for home labs. It forwards ordinary queries to DNS-over-HTTPS or local DNS resolvers, caches responses, and exposes a small HTTP API for clearing the cache, refreshing the blocklist, and toggling blocking.

The distinctive part is its rule-driven transformer. Rules match both DNS names and record types, capture reusable parts of a name, and construct a new DNS answer from those captures. Rewrites can be recursive, so the output of one rule can become the input to another:

api.service.  --rewrite-->  api.lan.  --rewrite-->  192.168.1.10
printer.vpn.  --rewrite-->  printer.example.net.  --route-->  private DNS
ads.example.  --rewrite-->  BLACKHOLE

That makes hold useful when a home network has several naming schemes, split DNS, overlay-network names, or local services that should resolve without maintaining every hostname individually.

Should I use this instead of Pi-hole or AdGuard Home?

Probably not if you mainly want a polished DNS appliance. Pi-hole and AdGuard Home are considerably more mature, have friendly administration interfaces, and are better choices for most networks.

hold exists for cases where their record-rewrite systems are too limited. A single hold rule can map {domain}.service. to {domain}.lan., retain the captured label, pass the result through further rules, and choose a resolver from the transformed name. Blocking participates in the same recursive pipeline, so a rewrite that eventually reaches a blocked domain is blocked too.

Run from GitHub

hold requires Python 3.14 or newer. Until the package is available from PyPI, use the latest GitHub release. With uv, run v0.1.1 directly from its Git tag:

uvx --no-sources --from "git+https://github.com/fmtr/hold.git@v0.1.1" hold --config ./settings.yaml

Copy the example settings file, adjust the listen address and upstream resolvers for your network, then point a test client at the configured port. hold is intended for trusted home-lab networks, not exposed or high-availability production infrastructure.

DNS normally uses port 53, which most operating systems reserve for privileged processes. On Linux, you can allow unprivileged processes to bind from port 53 upward until the next reboot with:

sudo sysctl -w net.ipv4.ip_unprivileged_port_start=53

Running hold with sudo also works, but running the whole service as root is not recommended. For an initial test, leave the settings file unchanged and override its port from the command line:

uvx --no-sources --from "git+https://github.com/fmtr/hold.git@v0.1.1" hold --config ./settings.yaml --server '{"port":5353}'

Rewrite rules at a glance

Sources are regular-expression patterns. {SUBDOMAIN} captures one label and {SUBDOMAINS} captures one or more labels; captured values can be inserted into the target:

rewriter:
  is_recursive: true
  items:
    - source: {name: '{SUBDOMAIN}\.service\.', records: 'A|AAAA|CNAME'}
      target: {name: '{SUBDOMAIN}.lan.', records: CNAME}
    - source: {name: '{SUBDOMAIN}\.lan\.', records: 'A|AAAA|CNAME'}
      target: {name: 192.168.1.10, records: A}
    - source: {name: 'ads\.example\.', records: 'A|AAAA|CNAME'}
      target: BLACKHOLE

See the rewrite guide for matching, recursion, routing, and a larger example. See the quick start and settings reference for operation.

Documentation

License

hold is licensed under Apache 2.0.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages