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

Headless and service install

This page covers running DNSY as a systemd service on a server with no desktop: a dedicated service user, the hardened unit, freeing port 53, and reaching the web panel over SSH.

The unit and the user definition live in the repository as examples/dnsy.service and examples/dnsy.sysusers. Distribution packages install them to /usr/lib/systemd/system/dnsy.service and /usr/lib/sysusers.d/dnsy.conf. For a tarball or cargo install setup, copy them there yourself (or to /etc/systemd/system/dnsy.service and /etc/sysusers.d/dnsy.conf).

With a .deb or .rpm (Linux packages) everything below is already in place except enabling the service: the package creates the dnsy user, installs the unit and a sample /etc/dnsy/dnsy.toml, and leaves the service disabled and stopped. Edit the config, deal with port 53 if needed, then sudo systemctl enable --now dnsy.

Service user

dnsy.sysusers is a sysusers.d file that creates a system user and group named dnsy with /var/lib/dnsy as its home:

u dnsy - "DNSY DNS server" /var/lib/dnsy
sudo install -m 0644 examples/dnsy.sysusers /etc/sysusers.d/dnsy.conf
sudo systemd-sysusers

Install and enable the unit

The unit runs /usr/bin/dnsy --config /etc/dnsy/dnsy.toml serve. --config is a global flag, and /etc/dnsy/dnsy.toml is also its default. If the binary is elsewhere, for example /usr/local/bin/dnsy from a tarball install, change that one ExecStart= line (or override it with sudo systemctl edit dnsy).

sudo install -m 0644 examples/dnsy.service /etc/systemd/system/dnsy.service
sudo install -d -o root -g dnsy -m 0750 /etc/dnsy
sudo install -m 0640 -g dnsy examples/dnsy.toml /etc/dnsy/dnsy.toml
sudo systemctl daemon-reload
sudo systemctl enable --now dnsy

The unit sets StateDirectory=dnsy (so /var/lib/dnsy, the default server.data_dir, is created and owned by the dnsy user) and ConfigurationDirectory=dnsy (/etc/dnsy). Keep data_dir and zones.dir under /var/lib/dnsy: with ProtectSystem=strict that is the only writable path.

Hardening in the unit: the process runs as dnsy, never as root; AmbientCapabilities and CapabilityBoundingSet hold only CAP_NET_BIND_SERVICE, which is what lets it bind port 53, 853 and 443; NoNewPrivileges, ProtectSystem=strict, ProtectHome, PrivateTmp, ProtectKernel*, RestrictAddressFamilies (IPv4, IPv6 and Unix sockets only) and SystemCallFilter=@system-service limit the rest. The unit restarts on failure.

Check it with systemctl status dnsy. After editing dnsy.toml, sudo systemctl restart dnsy.

Port 53 and systemd-resolved

On Ubuntu and similar hosts systemd-resolved already holds 127.0.0.53:53, and DNSY fails to start with address already in use. Follow Port 53 and systemd-resolved to bind a different address or turn the stub listener off, then sudo systemctl restart dnsy.

The first-run bootstrap code

On a fresh data directory no users exist. Once every listener has bound, DNSY writes a one-time bootstrap code (valid one hour, shown once) to standard error, which systemd sends to the journal:

journalctl -u dnsy | grep 'bootstrap code'

A start that fails to bind prints no code, so fix the bind error first (see Troubleshooting) and look again. Use the code in the web panel or API to create the first administrator, as described in Users, tokens and sessions.

Reaching the web panel and API

The API and web panel listen on loopback only (api.listen = ["127.0.0.1:5380"] by default), so they are not reachable from other machines. From your workstation, forward the port over SSH:

ssh -L 5380:127.0.0.1:5380 user@dns-host

Then open http://127.0.0.1:5380 locally. The REST API is served on the same port. Keep the API on loopback unless you add TLS and a firewall rule; see Security.