esc
↑↓ move ↵ open

Overview

How the file is organised, and where to find a given setting.

Configuration is one TOML file. Most settings are top-level keys; features with several knobs of their own get a block.

Starting sdns without a configuration file writes sdns.conf in the current working directory and uses it. That generated file carries a comment above nearly every setting and is the authoritative description of the version you are running. The few keys it leaves out are in the configuration key index. These pages describe the same settings with more room for the reasoning behind them.

Where settings live

Page Covers
Server and listeners Bind addresses, TLS, outbound source IPs, API, logging
Resolution and DNSSEC Root servers, validation, QNAME minimisation, timeouts, depth
Cache and TTLs Cache size, prefetch, stale answers, failure caching
Access control and blocking ACLs, rate limits, blocklists, hosts file, reflection defence
Configuration key index Every key, with its default and what leaving it out means

Feature blocks ([rpz], [recursion_firewall], [ecs], [dns64], [ddr], [kubernetes], [[views]], [[forward_zone]], [plugins]) are documented on their own feature pages, since the settings only make sense alongside what the feature does.

Validate before you restart

sdns -t -c /etc/sdns.conf

The gate reads the file the way the server will. Addresses are parsed, ports are resolved through the same lookup a dial uses, CIDRs and enumerations are checked, TLS files are opened, and policy zones are compiled with the loaders the server runs. It reports every problem it finds, not just the first, and exits 1 if there was one.

An unknown key, a typo, or a setting an older sdns understood, fails -t. Startup only warns about it. The asymmetry is deliberate: you want the strict answer when you are checking a change, and you do not want a stale key left in the file to turn an upgrade into an outage.

Reloading without a restart

systemctl reload sdns       # the packaged unit sends SIGHUP
kill -HUP "$(pidof sdns)"   # anywhere else

On SIGHUP sdns reads the file again and passes it through the same gate as sdns -t, unknown keys included. A file that fails changes nothing: the error is logged and the running configuration stays. The TLS certificate is reloaded on the same signal.

These keys take effect without a restart:

Key On reload
loglevel The new level applies at once
accesslist The new list replaces the old one
clientratelimit Every client starts the new rate with a full quota
whitelist The new list replaces the old one
blocklist Added entries are blocked. An entry removed from the file stays blocked, since the API may have saved it too; remove it through the API
[[views]] The new views replace the old ones
rpz.mode shadow and enforce switch at once

Any other changed key needs a restart. It is listed in the reload’s log line on every reload until the server restarts or the file goes back. Either all the live keys of a reload apply or none do: when one of them is refused, nothing changes. dns_config_reloads_total counts reloads by outcome.

Upgrading

The file carries no version. One generated before 1.9.1 starts with a version line; it is ignored and can be deleted.

An upgrade loads the file unchanged. Nothing is migrated and no backup is written. Run sdns -t against it with the new binary: it reports any key that no longer exists and any value the new release refuses. A deprecated key logs a warning at startup. New settings take their defaults until you add them; to see them, generate a fresh configuration alongside the new binary and compare.

State directory

directory = "db"

Where sdns keeps what it writes: the RFC 5011 trust anchor database (trust-anchor.db and trust-anchor-tombstones.db), downloaded blocklists in blacklists/, the local root copy (root.zone, with hyperlocal_root) and the cache snapshot (cache.snapshot, with cache_persist). A missing directory is created, but not a missing parent. A relative path is relative to the process working directory, so a service should give an absolute one. It is required: a file that leaves it out or empty is refused.

Durations and sizes

Durations are Go duration strings: "2s", "10s", "5m", "24h". A bare number where a duration is expected fails to decode when the file is loaded, rather than being read silently as nanoseconds. A bare 0 is the exception: it decodes as zero.

Counts are plain integers. Where 0 means something other than zero, usually “use the built-in default” or “disabled”, the generated file says so above the key, and so do these pages.