Skip to content

Config file

This page covers the on-disk YAML file layer — format, where Conduit looks for it, how paths resolve, and how load and validation behave at startup and on reload. For overlays, effective config, and snapshots, see Configuration model. For conduitctl reload, SIGHUP, and export, see Reload and export.

Overview

Conduit reads one primary YAML file at process start. That file is the durable file layer operators edit in git or configuration management. The running process remembers that path for later reloads — SIGHUP and conduitctl reload always re-read the same file, not an arbitrary path you pass to conduitctl validate.

flowchart TD
  Start[Process start] --> Read[Read configured file]
  Reload[SIGHUP or conduitctl reload] --> Read
  Read --> Parse[Parse + apply defaults]
  Parse --> Validate{Validation OK?}
  Validate -->|yes| Snapshot[Build / swap runtime snapshot]
  Snapshot --> Run[Dataplane serves DNS]
  Run --> Reload
  Validate -->|no| Serving{Was DNS already being served?}
  Serving -->|no| Exit[Exit process — DNS never started]
  Serving -->|yes| LastGood[Reject file — keep last-good snapshot]

The same parse and validation steps run on startup and on reload. If validation fails, Conduit checks whether the dataplane was already answering queries: no means startup never succeeded (process exits); yes means a reload was rejected and the last-good snapshot stays active.

File format

  • Encoding: UTF-8 text.
  • Syntax: YAML mapping at the top level.
  • Unknown keys: Rejected at parse time (deny_unknown_fields on the YAML schema). Typos in block names fail before validation runs.
  • schema_version: Required. Must be 1 — omitting it fails YAML parsing; any other value fails validation.

Top-level blocks

Each block maps to a section in the canonical config model. The table below follows the same order as Reference: config schema in the nav — ingress, policy, answer path, upstream, process, control, then observability. Behavioral detail is on topic pages; field lists are in the Reference pages.

BlockRoleLearn more
schema_versionConfig schema version (1)This page
listenersDataplane ingress (client DNS)Reference: listeners
aclsOptional client IP ACL (global; per-listener override on listeners)Client ACLs, Reference: acls
rulesDeclarative policyRules and actions, Reference: rules
rhaiScript sandbox limits (scripts come from rules)Sandbox limits, Reference: rhai
data_sourcesLookup tables for Rhai and CIDR views for ACLsData sources, Reference: data sources
data_source_limitsLoad-safety caps for data_sources tablesLoad-safety limits, Reference: data sources
lookupAnswer-path profiles and ordered providersArchitecture — Lookup, Reference: lookup
cachesNamed DNS answer cache instances for lookup cache providersDNS answer cache, Reference: caches
poolsUpstream pools and backends; optional per-pool health:Pools and backends, Backend health, Reference: pools, Reference: health
forwardUpstream timeout, egress sources, transportReference: forward, Dual-stack forwarding
orchestratorRetry and transaction limitsReference: orchestrator, Retries and transactions
dataplaneDataplane runtime model (worker threads)Runtime and concurrency, Reference: dataplane
shutdownGraceful drain of in-flight transactions on stopRuntime and concurrency — Graceful drain, Reference: shutdown
controlControl plane gRPC listen addressgRPC and conduitctl, Reference: control
loggingProcess log level and outputLogging, Reference: logging
metricsBuilt-in Prometheus / OTEL exportMetrics, Reference: metrics and tracing
tracingPer-query pipeline tracesTracing, Reference: metrics and tracing
eventsEvent export queue and sinksEvent export, Reference: events

Sparse files and defaults

You do not need every block in the file. When a block is omitted, Conduit applies built-in defaults during YAML parse — the same values you see after a successful conduitctl export on a sparse config. The smallest runnable file needs only schema_version, listeners, and pools; see Minimal configuration.

Omitted control: means no gRPC listener — conduitctl apply, export, and reload against a running server are unavailable until you add control: and restart the process.

Path resolution (base directory)

Relative filesystem paths in the config resolve against the directory containing the config file, not the process working directory. Absolute paths are used as-is. This keeps scripts, data files, TLS material, and dnstap sockets stable when systemd or a chroot changes the process working directory.

Exception: the config file path you pass when starting conduit is resolved relative to the process working directory (or as an absolute path). Use an absolute path inside a chroot or container (for example /etc/conduit/conduit.yaml) so reload always re-reads the same location.

Field Example
Rhai script path in rule actions type: rhai, value: scripts/policy.rhai
data_sources path (type: csv or type: cidr) data/blocklist.csv
control.tls cert_path, key_path, client_ca_path
events.sinks dnstap destinations unix:run/dnstap.sock (path after unix:)

Example — config at /etc/conduit/conduit.yaml and value: scripts/policy.rhai loads /etc/conduit/scripts/policy.rhai. The same rule applies to cert_path: tls/server.pem and destinations: ["unix:run/dnstap.sock"].

Use absolute paths when assets live outside the config directory tree.

What makes a config runnable

Beyond parsing and validation, a config must be operationally sufficient:

Requirement Why
At least one listener under listeners.listeners Clients need an address to send DNS queries
At least one pool with at least one backend Route must forward somewhere
Unique pool name values Duplicate names fail validation
Non-empty backend address values Parsed as ip:port upstream destinations
Backend weight ≥ 1 when set Omitted weight defaults to 100

An empty listeners.listeners list may pass validation but Conduit will not accept client DNS on any address.

Validation

conduitctl validate checks a file without a running server:

conduitctl validate --file conduit.yaml

On success it prints ok to stdout. On failure it prints each error to stderr and exits non-zero. Use this in CI or before reload — a passing validate is a strong signal that startup or reload will succeed for compile-time dependencies.

What validation checks

Validation has two stages:

  1. Structural and cross-field — examples of what fails:

  2. Unsupported schema_version

  3. listeners.threads = 0, empty listener addresses, duplicate pool names, pools with no backends
  4. Invalid forward.sources_v4 / sources_v6, unsupported forward.source_selection
  5. Rule hook/action mismatches (retry on request hook, set_source_v4 without configured sources)
  6. Invalid events sink destinations, duplicate sink identities
  7. Invalid control.listen_address, metrics / tracing profile and endpoint fields
  8. Unsupported rules.match_mode (only first_match today)

  9. Runtime snapshot compile — the same step Conduit runs after YAML validation at startup and on reload:

  10. Rhai scripts referenced by rules are read, compiled, and checked for metric registration

  11. Data sources (for example CSV lookup tables) are loaded from disk
  12. Forward and pool-forward settings are compiled

Compile errors use prefixed messages such as script 'path': …, rule 'name': …, and data source 'name': ….

Full rules evolve with the product; Reference: config schema lists fields and constraints per block.

What validation does not check

conduitctl validate does not open TLS PEM files, bind listener sockets, or open dnstap socket paths. It does not verify that upstream backends are reachable — Conduit only checks address format in YAML.

Startup vs reload

Event Config path On parse/validate/compile failure On success
Process start Path recorded at start Exit before DNS (YAML or compile error printed to stderr) Install snapshot, start dataplane
SIGHUP (Unix) Same path re-read from disk Log error; keep last-good snapshot New snapshot for later queries; clear overlay
conduitctl reload Same path on server RPC error; keep last-good snapshot Same as SIGHUP
conduitctl apply --clear Startup path unchanged (not re-read) RPC error; keep last-good snapshot Clear overlay only; file layer stays as last loaded

Reload does not apply edits you only made locally unless they are saved to the configured file path first. To drop an overlay without re-reading disk, use conduitctl apply --clear — see Reload and export — clear vs reload.

Some successful reloads still log pending (restart required) when listeners or forward changed — snapshot updates, but listener bind or egress sockets need a process restart. See Configuration model.

Example configs in releases

Location Contents
Release tarball conduit.minimal.yaml, conduit.reference.yaml
Debian package /etc/conduit/conduit.yaml (conffile), examples under /usr/share/doc/conduit/examples/

conduit.reference.yaml is a fuller field walkthrough; topic pages and Reference: config schema are the maintained documentation for each block.