runbound 0.4.0

RFC-compliant DNS resolver — drop-in Unbound with REST API, ACME auto-TLS, HMAC audit log, and master/slave HA
# ─────────────────────────────────────────────────────────────────────────────
# Runbound — Master node configuration (slave/master replication)
#
# Use-case : Primary DNS node that serves writes and replicates to one or more
#            slave replicas in real time.
#
# How it works:
#   - Every write via the REST API (POST /dns, POST /blacklist, feed ops…)
#     is recorded in a ring buffer journal (1 000 events).
#   - Slaves poll GET /sync/delta?since=N (HTTPS, port sync-port) to receive
#     only the events they missed since their last sync.
#   - If a slave is > 1 000 events behind, it performs a full snapshot sync
#     (GET /sync/config) automatically.
#   - The master auto-generates a self-signed TLS certificate for the sync
#     endpoint at startup (/etc/runbound/sync-cert.pem).
#     Its SHA-256 fingerprint is logged at INFO level for slave TOFU setup.
#
# Companion slave config: see examples/slave.conf or docs/configuration.md
# ─────────────────────────────────────────────────────────────────────────────

server:
    # ── Network ──────────────────────────────────────────────────────────────
    interface:  0.0.0.0
    port:       53

    do-ip4:     yes
    do-ip6:     yes
    do-udp:     yes
    do-tcp:     yes

    # ── Access control ────────────────────────────────────────────────────────
    access-control: 127.0.0.0/8      allow
    access-control: 192.168.1.0/24   allow   # adjust to your subnet
    access-control: 10.0.0.0/8       allow
    access-control: 0.0.0.0/0        refuse

    # ── Rate limiting ─────────────────────────────────────────────────────────
    rate-limit:    200
    cache-max-ttl: 3600

    # ── DNS rebinding protection ──────────────────────────────────────────────
    private-address: 10.0.0.0/8
    private-address: 172.16.0.0/12
    private-address: 192.168.0.0/16
    private-address: 127.0.0.0/8
    private-address: fd00::/8

    # ── Master/slave replication ──────────────────────────────────────────────
    mode:      master   # default — may be omitted

    # HTTPS sync server port — must be reachable by all slave nodes.
    # The sync server binds on 0.0.0.0:<sync-port> (all interfaces).
    # The main REST API remains on 127.0.0.1:<api-port> (localhost only).
    sync-port: 8082

    # Shared Bearer token used by slaves to authenticate to the sync endpoints.
    # If omitted, a random 256-bit key is generated at startup and printed to
    # the log. Copy it to all slave configs before their first start.
    #
    # Best practice: generate once and write to a file on both nodes:
    #   openssl rand -hex 32 > /etc/runbound/sync.key
    #   chmod 600 /etc/runbound/sync.key
    # Then reference it here or set RUNBOUND_SYNC_KEY in the environment.
    sync-key:  "change-me-and-copy-to-slave"

    # ── REST API ──────────────────────────────────────────────────────────────
    api-port: 8081
    # api-key is auto-generated at startup and saved to /etc/runbound/api.key
    # Override with RUNBOUND_API_KEY environment variable.

    # ── Local zones ───────────────────────────────────────────────────────────
    # Entries added here are included in full-sync snapshots sent to slaves.
    # Entries added via POST /dns are replicated via the delta journal.
    local-zone: "home." static
    local-data: "nas.home.    300 IN A 192.168.1.10"
    local-data: "router.home. 300 IN A 192.168.1.1"

    # ── Memory guard (always active — no config needed) ───────────────────────
    # At ≥ 80 % system RAM: rate-limiter + resolver cache purged automatically.
    # Inflight semaphore: max 4 096 concurrent requests → REFUSED if exceeded.

    # ── Logging ───────────────────────────────────────────────────────────────
    verbosity: 1
    # logfile: /var/log/runbound/runbound.log

# ── Upstream resolvers ────────────────────────────────────────────────────────
forward-zone:
    name:                 "."
    forward-addr:         1.1.1.1@853
    forward-addr:         1.0.0.1@853
    forward-tls-upstream: yes