Skip to content

dnsdist: build from source against quiche; DoQ + DoH3 by default - #4

Open
sorcmach wants to merge 1 commit into
mainfrom
dnsdist-source-build-doq
Open

dnsdist: build from source against quiche; DoQ + DoH3 by default#4
sorcmach wants to merge 1 commit into
mainfrom
dnsdist-source-build-doq

Conversation

@sorcmach

@sorcmach sorcmach commented May 14, 2026

Copy link
Copy Markdown
Member

Summary

Upgrades dnsdist from the Debian package (1.9.14, no QUIC) to a source build of the latest stable 2.0.x against cloudflare/quiche, and enables DoQ + DoH3 as default endpoints. Avoids the PowerDNS apt repo so the install chain stays at github.com TLS rather than a third-party repository that prunes old versions.

What lands

  • lib/dnsdist_build.sh (new): source-build orchestrator. Resolves the latest dnsdist-2.0.* and quiche 0.x.y tags via git ls-remote; pinnable via DNSDIST_VERSION / QUICHE_VERSION in install.conf. Builds quiche with cargo build --release --features ffi, then dnsdist with meson/ninja. Caps ninja -j at mem_mb / 1500 so 2 GB VMs don't OOM compiling dnsdist.cc at -O3.
  • Build deps are installed via apt; anything not already manually-installed gets marked auto, and a post-build apt-get autoremove --purge reaps the lot. Runtime libs (libluajit, libsodium, libssl3t64, libcap2, libnghttp2, libsystemd0, libedit2, libfstrm0, libre2, libcdb) are kept manual. Before/after dpkg snapshots written to /var/lib/opennic-tier2-install/.
  • Custom configs/systemd/dnsdist.service.template installed to /etc/systemd/system/dnsdist.service; takes precedence over Debian's unit. step_dnsdist_remove_apt_package follows with apt-get remove dnsdist so the apt binary disappears cleanly. _dnsdist user persists because we use remove, not purge.
  • /etc/ld.so.conf.d/opennic-tier2-dnsdist.conf registers /opt/dnsdist/lib with the dynamic loader (no LD_LIBRARY_PATH in the unit).
  • dnsdist.conf.template gets addDOQLocal() bindings on UDP 853 for IPv4 + IPv6 (shares the LE cert with DoT; UDP and TCP sockets are distinct so port-853 reuse is intentional).
  • make_stamp.py learns a doq subcommand (protocol 0x04). steps_nginx.sh renders a DOQ_STAMP. The info-page template gets a DoQ endpoint row and a DoQ stamp block.
  • verify.sh gains a kdig +quic probe with a UDP-listener fallback.
  • README.md updated: new :853/udp firewall requirement, the longer install time (10-15 min, mostly the source build), the two version-pin options.

Out of scope

  • Production migration on dns.sorcerousmachine.com. Re-running install.sh after this lands triggers the build + apt-remove + service swap; until then the running 1.9 is unaffected.
  • DNSCrypt registry PR #1045 stamp update. Adding sdns://04... entries is a follow-up once the resolver is on the new binary.

Test plan

  • Quiche 0.28.0 builds cleanly from the cargo+ffi path on a 2 GB Debian 13 LXC
  • dnsdist 2.0.5 builds against quiche; verified Enabled features: includes dns-over-quic dns-over-http3 dns-over-tls(openssl) dns-over-https(nghttp2) dnscrypt
  • apt-get autoremove --purge removed 80 build-only packages; all designated runtime libs survived (libluajit-5.1-2, libsodium23, libssl3t64, libcap2, libnghttp2-14, libsystemd0, libedit2, libfstrm0, libre2-11, libcdb1)
  • /opt/dnsdist/bin/dnsdist --version works after autoremove; ldd resolves libquiche.so.0 via /etc/ld.so.conf.d (no env override)
  • dnsdist.conf re-renders with DoQ stanzas; --check-config validates against the source-built binary
  • make_stamp.py doq produces well-formed sdns://04... stamps
  • Live migration on dns.sorcerousmachine.com
  • kdig +quic against the public IP returns a record post-migration
  • DNSCrypt registry PR #1045 amended with sdns://04... entries

Debian 13 ships dnsdist 1.9 without QUIC, and Debian doesn't have a
libquiche package, so DoQ requires building both quiche and dnsdist
from upstream git. The alternative is the PowerDNS apt repo, which has
its own pruning policy and adds an external trust root; this approach
keeps the chain at github.com TLS + Cloudflare's quiche source.

The build step lives in lib/dnsdist_build.sh:
  - Resolves the latest dnsdist-2.0.x tag and the latest quiche 0.x
    tag via `git ls-remote`. Optional install.conf pins
    (DNSDIST_VERSION, QUICHE_VERSION) lock to specific tags.
  - Installs runtime libs (libluajit, libsodium, libssl3t64, libcap2,
    libnghttp2, libsystemd0, libedit2, libfstrm0, libre2, libcdb)
    as manually-installed packages.
  - Installs build deps (rustc, cargo, cmake, golang-go, ragel,
    meson, ninja-build, boost, python3-yaml, python3-venv, all -dev
    headers) and marks anything we newly installed `auto`. A
    developer's pre-existing build-essential / git survives.
  - `cargo build --release --features ffi` for quiche (with
    --recurse-submodules for BoringSSL). libquiche.so + quiche.h +
    a generated quiche.pc end up under /opt/dnsdist.
  - meson + ninja for dnsdist with -Dquiche=enabled and a custom
    CPATH/LIBRARY_PATH so the executable target picks up quiche
    headers/lib (dnsdist's meson.build doesn't propagate them through
    libdnsdist-common to the executable, only assumes system paths).
  - ninja-job cap of `mem_mb / 1500` so cc1plus doesn't OOM on 2 GB
    VMs while compiling dnsdist.cc at -O3.
  - Final `apt-get autoremove --purge` reaps the auto-marked build
    deps; runtime libs survive because they're manual. dpkg
    before/after snapshots get saved to /var/lib/opennic-tier2-
    install/ for audit.

Custom systemd unit at /etc/systemd/system/dnsdist.service points at
/opt/dnsdist/bin/dnsdist and overrides anything Debian's apt package
left under /usr/lib/systemd/system. step_dnsdist_remove_apt_package
follows up with `apt-get remove dnsdist` so the apt-installed binary
goes away cleanly (the _dnsdist user persists via remove-not-purge).

A /etc/ld.so.conf.d/opennic-tier2-dnsdist.conf entry registers
/opt/dnsdist/lib with the dynamic loader so dnsdist finds
libquiche.so.0 without LD_LIBRARY_PATH gymnastics in the unit.

dnsdist.conf gets addDOQLocal() bindings on UDP 853 for IPv4 (and
IPv6 when RESOLVER_IPV6 is set), sharing the LE cert with DoT. DoQ
and DoT coexist on port 853 because they're different transports
(UDP vs TCP).

make_stamp.py learns a `doq` subcommand emitting protocol-0x04
stamps. steps_nginx.sh renders a DOQ_STAMP into the info page; the
template gets a DoQ row in the endpoints table and a DoQ stamp block.
scripts/verify.sh adds a `kdig +quic` probe with a UDP-listener
fallback when knot-dnsutils 3.0+ isn't installed.

README documents the new ~10-15 min install time (mostly the build),
the new :853/udp firewall requirement, and the version-pin options.

End-to-end build verified on a 2 GB Debian 13 LXC: quiche 0.28.0 +
dnsdist 2.0.5 with `Enabled features: ... dns-over-quic dns-over-
http3 dns-over-tls(openssl) dns-over-https(nghttp2) dnscrypt ...`.
autoremove --purge cleaned 80 packages; /opt/dnsdist intact and
dnsdist --version works without LD_LIBRARY_PATH after ldconfig.

Production migration deferred until PR review.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant