Skip to content

Configuration Reference

import { Aside } from ‘@astrojs/starlight/components’;

homeDNS reads a single YAML file passed via --config. Copy config.example.yaml from the repo root as your starting point.


server:
name: homeDNS # Display name — shown in web admin header
data_dir: ./data # Base path for persistent storage (SQLite DB, etc.)

Configures DNS wire-protocol endpoints. Each listener is independently toggled.

listeners:
do53:
enabled: true
bind: ":53" # Standard DNS; use ":5353" in dev to avoid privilege issues
dot:
enabled: false
bind: ":853" # DNS over TLS — requires tls.cert_file + tls.key_file
doh:
enabled: false
bind: ":8443" # DNS over HTTPS
path: /dns-query # RFC 8484 path

Shared TLS material used by the DoT and DoH listeners.

tls:
cert_file: ".certs/server.crt"
key_file: ".certs/server.key"

See Quick Start for generating a self-signed dev cert.


Controls the iterative recursive resolver built into dnsd.

recursion:
enabled: true
max_queries: 50 # Max upstream queries per resolution
query_timeout: 3s # Per-query timeout
max_cname_hops: 8 # CNAME chain limit (prevents infinite loops)
dnssec_validate: false # Enable DNSSEC validation (stub — full validation is v2)

Global defaults and health-probe settings for the forwarding engine.

forwarding:
default_strategy: failover # fallback strategy when no per-forwarder strategy is set
health:
slow_above: 20ms # Upstream classified as "slow" above this RTT
failing_after: 3 # Consecutive probe failures before "failing" status
probe_interval: 30s # Time between latency probes
probe_timeout: 2s # Individual probe timeout
sample_window: 3 # Rolling window size for RTT averages

Health states: healthy (avg < slow_above, no errors), slow (avg ≥ slow_above), failing (last failing_after probes all errored). Failing upstreams are skipped by all strategies.


Optional static upstream list. When forwarders.servers is populated, the runtime uses this YAML list. When empty, the runtime falls back to API-stored conditional forwarders created via the web UI or dnsctl.

forwarders:
contact_method: sequential # How to pick from the server list (see below)
servers:
- id: cloudflare-dot
protocol: dot # do53 | dot | doh | doq | doh3
address: "1.1.1.1:853"
dnssec: true # Forward DNSSEC DO-bit
timeout: 2s
skip_tls_verify: false # Do not skip in production
- id: cloudflare-doh
protocol: doh
address: "https://1.1.1.1/dns-query"
dnssec: true
timeout: 3s
ValueBehaviour
sequentialTry servers in order; fall back on failure
parallel_firstRace all servers; first valid response wins
lowest_latencyPrefer server with lowest observed probe latency

DNS blocking engine (Pi-hole / AdGuard Home style).

filter:
enabled: true
default_refresh: 24h # Interval between automatic list re-downloads
action: nxdomain # Block action: nxdomain | nodata | sinkhole | refused | custom_cname
sinkhole_ipv4: 0.0.0.0 # Returned for A queries when action is "sinkhole"
sinkhole_ipv6: "::" # Returned for AAAA queries when action is "sinkhole"
sinkhole_ttl: 60 # TTL of sinkhole responses

List sources (URLs, formats) are managed via the Filter page in the web admin or dnsctl filter.


CIDR-based access control for DNS queries.

acl:
allow_query: # Who may send any DNS query
- 0.0.0.0/0
- ::/0
allow_recurse: # Who may trigger recursive resolution
- 127.0.0.0/8
- ::1/128
- 10.0.0.0/8
- 192.168.0.0/16
- 172.16.0.0/12

A separate deny list (acl.deny_query) can be defined to explicitly reject sources before the allow check.


Token-bucket per-source-IP rate limiting on the DNS data plane.

rate_limit:
enabled: true
qps: 100 # Sustained queries per second per source IP
burst: 200 # Burst allowance above QPS
window: 1s # Token refill window

Persistence backend for zones, forwarders, filter sources, DDNS policies, and users.

storage:
driver: memory # memory | sqlite
path: "" # Path to SQLite DB file when driver is "sqlite"
  • memory — all config is ephemeral; resets on restart. Good for testing.
  • sqlite — data survives restarts. Uses WAL mode; safe to copy the .db file for backups while the daemon is running.

The HTTP server that hosts the REST API and embedded web admin SPA.

management:
enabled: true
bind: 127.0.0.1:8080 # Address to listen on — loopback by default
allow_cidrs: # Only these source IPs may reach the API
- 127.0.0.0/8
- ::1/128
debug: false # When true, raw error details surface in the web UI

GET /api/v1/version exposes the debug flag so the web UI can adjust its error display at bootstrap time.


logging:
level: info # debug | info | warn | error
format: text # text (human-readable) | json (structured, recommended for prod)

homeDNS watches the config file for changes by default. Writing a new config in place triggers a reload without dropping active DNS connections. SIGHUP support is version-dependent — see docs/RUNBOOK.md for current behaviour.