Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Install

DNSY is one binary, dnsy. It needs no runtime dependencies: SQLite is bundled and TLS uses rustls.

Prebuilt binaries

Every tagged release publishes archives and installers for Linux, macOS and Windows with the web UI embedded; see Releases for the targets, installers and checksum verification.

On Debian, Ubuntu, RHEL, Rocky, Alma and Fedora, the release also has .deb and .rpm packages that install the binary, a sample config and the systemd unit (they never start the service):

sudo apt install ./dnsy_<ver>_amd64.deb          # or arm64
sudo dnf install ./dnsy-<ver>-1.x86_64.rpm       # or aarch64

See Linux packages and Headless and service install.

Every archive also holds dnsy.toml, an annotated sample configuration. Copy it to /etc/dnsy/dnsy.toml or let the binary write it for you, see Starter configuration.

From source

git clone https://github.com/repsyio/dnsy && cd dnsy
cargo build --release -p dnsy          # no node needed; the UI paths answer 404

To embed the web UI, build it first. just build does both steps (it needs node and pnpm):

just build                             # pnpm build in web/, then cargo build --features embed-ui
./target/release/dnsy version

The UI is compiled into the binary with the embed-ui feature from web/dist/dnsy/browser. Building that feature without web/dist prints a warning and fails to compile, so run just build rather than passing the feature by hand.

Starter configuration

A fresh install has no config file, and the defaults assume root (port 53, /etc/dnsy, /var/lib/dnsy). dnsy config init writes the annotated starter file to the --config path (default /etc/dnsy/dnsy.toml, parent directories are created):

sudo dnsy config init                  # the annotated defaults, the same text as the archive's dnsy.toml
dnsy --config dnsy.toml config init --dev
dnsy --config dnsy.toml serve

--dev writes a configuration that runs without privileges: DNS on 127.0.0.1:5353, the API on 127.0.0.1:5380, state under ./dnsy-data (relative to the working directory) and the public upstreams 1.1.1.1 and 9.9.9.9, so queries resolve. Try it with dig @127.0.0.1 -p 5353 example.com. An existing file is never overwritten unless you pass --force.

Release profile

cargo build --release uses fat LTO, one codegen unit, stripped symbols and overflow checks (integer overflow panics instead of wrapping). Panics unwind: a panic ends one connection task, not the process. A release binary with the UI embedded is about 17 MB (29 MB before the profile), and a clean release build takes roughly three minutes on a laptop-class machine.

The embedded UI ships a brotli and a gzip copy of every text asset (written by pnpm build in web/); the server picks one from Accept-Encoding and sends Vary: Accept-Encoding.

Files and users

PathPurpose
/etc/dnsy/dnsy.tomlconfiguration (override with --config or DNSY_CONFIG)
<server.data_dir>/dnsy.dbSQLite database: users, tokens, rules, keys, query log
<zones.dir>/*.jsonzone files

Binding port 53 or 853 needs privilege: run as a dedicated non-root user and grant CAP_NET_BIND_SERVICE (or listen on high ports behind a forwarder). On systemd hosts, systemd-resolved may already hold 127.0.0.53:53; see Port 53 and systemd-resolved. The data directory, the key passphrase file and TLS private keys should be readable by that user only.

Build time

Every binary embeds its build timestamp (dnsy version prints it, SOURCE_DATE_EPOCH makes it reproducible). DNSSEC validation uses it as a lower bound for a sane system clock.