kudurru

Kubernetes-native DNSKudurru Community Licensev0.1.0 “stone”

authority over every zone.

kudurru is a DNS server for the networks you run: authoritative zones, a resolver that forwards over every encrypted transport or resolves from the root with DNSSEC validation, blocking with client groups, and a dashboard that shows why each answer was given. One Go binary, as a single container or as a Kubernetes Deployment with CRDs.

kudurru-0 query log 20.1 q/s
  1. 21:04:59 robert-laptop A nas.home.example.com authoritative 38 µs
  2. 21:04:56 kids-tablet A doubleclick.net blocked 109 µs
  3. 21:04:53 living-room-tv A media.streaming.example cached 52 µs
  4. 21:04:50 thermostat TXT metrics.vendor.example blocked 273 µs
  5. 21:04:47 robert-phone AAAA api.weather.example forwarded 12.6 ms
  6. 21:04:44 nas PTR 20.0.0.10.in-addr.arpa authoritative 31 µs
  7. 21:04:41 doorbell A events.camera.example cached 47 µs
  8. 21:04:38 kids-laptop HTTPS app-measurement.com blocked 167 µs
  9. 21:04:35 robert-laptop A registry.k8s.example forwarded 9.4 ms
Sample traffic, rendered in your browser. Each bar follows the seven v0.1.0 stages; logging observes the result after the chain returns.
binary1every role, every shape
transports5Do53 · DoT · DoH · DoQ · DoH3
block lookup p991.14 µs1,000,000 rules, 0 allocations
3 M list entries90 MBresident in the blocking benchmark

ILineage

Projects that shaped kudurru.

These projects inspired kudurru's DNS features, dashboard, blocking and deployment model.

InspirationFromWhat it means in kudurru v0.1.0
01API-first design and one binary Gravity Every node runs the resolver, API and dashboard. Kubernetes replicas share configuration through the apiserver.
02Authoritative DNS and encrypted transports Technitium Primary and forward zones, SOA serial management, AXFR and IXFR out, NOTIFY out, TSIG on UDP/TCP/DoT, DoT/DoH/DoQ/DoH3 and per-zone query ACLs.
03A clear view of DNS activity Pi-hole Stat tiles, 24-hour charts, a query log that says why, one-click allow/deny and views across nodes.
04Powerful blocking blocky / AdGuard Home hosts, domain, adblock and regex lists; client groups; per-group policies and schedules; zero-allocation matchers with a benchmark regression gate.
05Load balancing at the edge dnsdist An optional kudurru supervisor renders, checks and runs dnsdist. Authenticated PROXYv2 preserves client IPs on the backend hop.
06Virtual IPs on bare metal keepalived A kudurru supervisor renders and runs keepalived (VRRPv3, authenticated, nopreempt), so the VIP follows dnsdist health.

How kudurru brings these ideas together

  • CRDs as the source of truth

    In a cluster, zones, records, lists, groups and policies are Kubernetes objects. In Docker the same YAML goes into SQLite.

  • OIDC sign-in and role-based access control

    viewer, auditor, operator, zone-admin and admin, scoped per zone. A login with no role binding is refused, never silently admin. Needs a license key (free for personal use).

  • An integration framework

    The external-dns webhook provider writes records in v0.1.0. The Cloudflare split-horizon sink and UniFi inventory source are planned for v0.2. Integrations need a license key (free for eligible personal use).

IIPipeline

Every query takes the same path.

A fixed chain of stages reads lock-free snapshots of zone trees, policies, compiled lists and upstreams. The query path never touches the store, so a node keeps answering from its last good snapshot when the store is unreachable.

udp kids-tablet 192.168.1.42 IN A doubleclick.net
  1. 01ingress
  2. 02identify
  3. 03control
  4. 04authoritative
  5. 05blocking
  6. 06cache
  7. 07upstream
  8. →log
  1. ingress41 bytes over UDP from 192.168.1.42, under the prefix rate limit
  2. identify192.168.1.42 is client kids-tablet, member of group kids
  3. controlwell-formed, one question, no CHAOS class
  4. authoritativeno local zone covers doubleclick.net
  5. blockingpolicy kids matches list default-ads, rule ||doubleclick.net^, mode zeroIP
  6. logstatus blocked list, EDE 15 (Blocked), list default-ads

;; ANSWERblocked109 µs

doubleclick.net.  600  IN  A  0.0.0.0
01 ingress
Checks query shape and per-prefix rate limits; answers CHAOS and health probes
02 identify
Matches the source IP or CIDR to client groups and their merged policies
03 control
Drops malformed queries
04 authoritative
Answers names in local zones from an in-memory tree
05 blocking
Evaluates the client's merged policies: lists, services, safe search
06 cache
Sharded TTL cache with prefetch, serve-stale and in-flight coalescing
07 upstream
Forwards to the client's upstream group over DoT, DoH, DoQ or Do53, or resolves from the root servers with DNSSEC validation
→ log
After the chain returns, the observer records the answer and its reason

Seven stages decide the answer; the log observer records the result after the chain returns. The fixed order also reserves local, rewrite, dnssec and postprocess for later releases. The scenarios use illustrative names and addresses.

IIIFeatures

What v0.1.0 includes.

01Zones

50–80ms

AXFR of a 100,000-record zone

Authoritative, with real serials.

Primary and forward zones come from DNSZone and DNSRecordSet objects and are answered from an in-memory tree that every replica holds.

  • Wildcards, CNAME and DNAME chasing, NODATA versus NXDOMAIN, per-zone query ACLs
  • SOA serial stamping with coalescing, records that expire on their own, BIND zone file import and export
  • AXFR and IXFR out; TSIG on UDP, TCP and DoT; NOTIFY out with retries
  • SERVFAIL, never NXDOMAIN, for a primary zone that has not loaded yet

Secondary and stub zones, RFC 2136 updates: v0.2. DNSSEC signing: v1.0.

Zones and upstreams

02Resolver

5

transports: Do53, DoT, DoH, DoQ, DoH3

Every transport. One listener set.

Do53 over UDP and TCP, DoT, DoH over HTTP/1.1 and HTTP/2, DoQ and DoH3, each with a certificate reloader, in front of one pipeline.

  • Upstream groups with parallel_best, strict, random and rtt_weighted strategies, conditional forwarding, ECS strip, forward or add
  • Opt-in recursive groups: resolution from the root servers with QNAME minimization and DNSSEC validation, no client subnet sent
  • Sharded TTL cache with prefetch, serve-stale (RFC 8767) and in-flight coalescing; it is restored after a restart
  • SO_REUSEPORT listeners on every core: 53 % more UDP throughput
  • Per-prefix rate limits that slip TC=1 before they drop
Network setup

03Blocking

1.14µs

p99 lookup against 1,000,000 suffix rules, 0 allocations

Lists, groups, schedules. No allocations.

A clean-room parser compiles hosts, domain, adblock and regex lists into one matcher chain. Allow wins, @@ exceptions apply, and answers are checked through their CNAME chain.

  • Client groups by IP and CIDR, with merged policies and weekday schedules (a policy beyond the default needs a license key, free for eligible personal use)
  • 150 blocked services in 14 categories, and safe search for the search engines and video sites that document it
  • A block page that says which list blocked a site, with a request-access form that reaches an admin
  • Answers with zeroIP, NXDOMAIN, a custom IP or REFUSED, tagged with EDE 15 or 17
Lists, groups and policies

04DHCPv4

3

voters in the optional quorum failover group

Addresses, leases and local names.

An opt-in DHCPv4 server on Linux/SQLite assigns addresses on direct or trusted-relay subnets, with persistent leases and reservations.

  • Dashboard setup stages scope topology and enable/disable changes for restart; live options and reservations use the active scope API
  • Multiple subnets, conflict checks, network/boot options and native/dnsmasq lease import
  • Optional A/PTR records in a dedicated DHCP domain, with persistent name ownership
  • Optional three-node quorum failover commits lease ownership before replying; DHCPv6 is not supported
  • Docker requires a local DHCP-capable source build; systemd packages need a capability drop-in
DHCPv4 setup and cutover

05Identity

0

OIDC logins that become admin without a role binding

OIDC sign-in. Scoped roles.

Sign in with your identity provider, or with local accounts on a single box. Every write lands in the audit trail with who did it and which permission allowed it.

  • OIDC with a backend-for-frontend and PKCE; local users with Argon2id and lockouts
  • Roles viewer, auditor, operator, zone-admin and admin, scoped per zone
  • API tokens, service accounts, and Kubernetes ServiceAccount tokens checked with SubjectAccessReview
  • The chart's aggregated ClusterRoles are generated from the same permission file
  • Roles, OIDC and the audit trail need a license key; a free personal key covers up to 3 nodes
People, roles and tokens

06Kubernetes

2

Helm charts, with configuration and Kubernetes schema checks

The apiserver is the replicated store.

DNSZone, DNSRecordSet, BlockList, ClientGroup and Policy are CRDs. Every replica watches them and serves from memory, so an apiserver outage does not stop answers.

  • Helm charts kudurru and kudurru-crds, with a render matrix checked against the binary's configuration schema and kubeconform
  • Each object records its owner: the API, a file, an integration or Kubernetes. Writes from another source are rejected
  • An external-dns webhook provider that writes DNSRecordSet objects (needs a license key, free for eligible personal use)
  • The same YAML works in Docker: kudurru apply -f zone.yaml
Helm guide

07Edge and VIP

3

nodes in the compose HA profile, one VIP

dnsdist in front. A VIP that follows health.

kudurru supervises the programs that do this best instead of rewriting them. dnsdist and keepalived stay unmodified, in their own containers, and kudurru renders, checks and runs them. The supervisors need a license key; a free personal key covers up to 3 nodes.

  • kudurru edge run renders dnsdist's configuration, runs --check-config before every swap and tracks backends by health
  • PROXYv2 with an authenticated TLV keeps the real client IP for groups and the query log
  • kudurru vip run runs keepalived with VRRPv3 unicast, auth_hmac and nopreempt
  • Serve from memory; degrade, never stop
Compose HA

IVDashboard

A dashboard that answers why.

Pi-hole's dashboard, rebuilt for more than one node. Every chart drills down into the query log, and every query in the log names the list, rule, cache state, upstream and node behind its answer. It ships inside the binary.

The kudurru Dashboard page
01 / 06Two nodes, 24 hours: queries by answer type and by client.

Tour every page in the guide

VDeploy

One binary. Pick the shape.

In Kubernetes the apiserver is the replicated store. In Docker it is embedded SQLite. Follower mode and raft arrive later behind the same Store interface, so nothing above it changes.

mkdir -p kudurru/secrets && cd kudurru
openssl rand -base64 32 > secrets/encryption_key
openssl rand -base64 18 > secrets/admin_password
docker run -d --name kudurru --restart unless-stopped \
  -p 53:53/udp -p 53:53/tcp -p 8080:8080 \
  -v kudurru-data:/var/lib/kudurru \
  -v "$PWD/secrets:/run/secrets:ro" \
  -e KUDURRU_ENCRYPTION_KEY_FILE=/run/secrets/encryption_key \
  -e KUDURRU_ADMIN_PASSWORD_FILE=/run/secrets/admin_password \
  ghcr.io/robertherbaugh/kudurru:0.1.0
dig @127.0.0.1 example.com

Open https://<host>:8080/ and sign in as admin with the password in secrets/admin_password. The first start creates a self-signed certificate; keep a safe copy of the encryption key. Guide

Deployment shapes
ShapeSource of truthConfig writesRelease
docker run, composeAnswers: one nodestate.db on a volumen/av0.1.0
Kubernetes, several replicasAnswers: every pod, through apiserver outagesCRDs in the apiserverapiserver HAv0.1.0
Kubernetes, one node (Pi-hole on k3s)Answers: one podstate.db on a PVCn/av0.1.0
Compose HA, static twinsAnswers: all nodes, VIPthe same file-managed config on independent SQLite nodesdistribute files to every nodev0.1.0
Compose HA, follower modeAnswers: all nodesthe primary's state.dbprimary, fenced promotev0.2
Compose HA, raftAnswers: all nodesreplicated state.dbany nodev1.0
  • linux/amd64 + linux/arm64
  • distroless, nonroot
  • cosign keyless signatures
  • SBOM + SLSA provenance
  • deb · rpm · apk with systemd

Move over

Bring your DNS with you.

Start with the server you run today. Each guide maps your configuration, explains the gaps and walks through testing before you switch.

Coming from

Pi-hole

Keep the lists and local names you trust. Add authoritative zones, encrypted DNS listeners and Kubernetes CRDs.

Groups become client groups and policies. Adlists become block lists; local DNS records become zone records.

Before you switch. If Pi-hole serves DHCP, configure kudurru's opt-in DHCPv4 on Linux/SQLite or keep DHCP on your router. Preserve leases and reservations before switching. Translate regex extensions and reserve device addresses.

Move from Pi-hole

Coming from

AdGuard Home

Bring your DNS filters, client rules and encrypted upstreams into a server with explicit object ownership and shared Kubernetes configuration.

Filters become block and allow lists. Persistent clients become client groups; per-client settings become policies.

Before you switch. Review rule modifiers, global exceptions and DNS rewrites. AdGuard's full filtering syntax is not supported in v0.1.0.

Move from AdGuard Home

Coming from

Technitium

Move primary zones, conditional forwarding, blocking and recursive resolution to a Go binary with a dashboard, CLI and Kubernetes API objects.

Export primary zones as standard zone files. Recreate conditional forwarders, access controls and blocking policies explicitly.

Before you switch. Inventory DNS Apps, DNSSEC signing and secondary zones. These need a separate service or a later kudurru release. Recursion with DNSSEC validation is an upstream group mode.

Move from Technitium

Compare all four DNS servers

VIThe name

koo-DOO-roo

A kudurru was a Babylonian boundary stone that recorded a land grant and the rights attached to it. The name reflects what a DNS zone represents: authority over a defined space.

The original stone was kept in a temple, while the landholder held a clay copy—a fitting inspiration for authoritative DNS and the copies shared through zone transfers. Our release names follow that story: stone, clay copies, temple.

VIIRoadmap

stone, clay copies, temple.

  1. v0.1.0this release

    stone

    The stone itself: one record of authority.

    • Resolver with DoT, DoH, DoQ and DoH3
    • Opt-in recursion with DNSSEC validation
    • Opt-in DHCPv4 on Linux/SQLite, dashboard setup and three-node quorum failover
    • Primary and forward zones, AXFR and IXFR out
    • Blocking with client groups, services and safe search
    • Dashboard with long-term views, OIDC and RBAC (a free personal key unlocks them)
    • CRDs and Helm, compose HA with dnsdist and keepalived
  2. v0.2.0

    clay copies

    The landholder's copies: secondaries and followers.

    • Secondary and stub zones, RFC 2136
    • Active Directory DNS replacement for a single-domain forest
    • DNSSEC validation of forwarded answers, RPZ feed import
    • Cloudflare split-horizon sink, UniFi inventory
    • Follower-mode HA
    • dnstap and tracing
  3. v1.0

    temple

    Where the original is kept.

    • DNSSEC signing, catalog zones
    • RPZ publishing
    • Raft store: writes on any node
    • ACME, a Pi-hole API façade
    • API freeze

Milestones and exit criteria: design record, section 13.

Start with one container.
Grow into a cluster.