···11+# Configuration
22+33+## Location
44+55+The config file is loaded from one of two places:
66+77+1. The path set in the `ONIS_CONFIG` environment variable
88+2. `onis.toml` in the current working directory (default)
99+1010+If the file does not exist, all options fall back to their defaults. Every field is optional. A default config is provided here, with the default values that are used.
1111+1212+## Options
1313+1414+### `[appview]`
1515+1616+| Key | Type | Default | Description |
1717+|-----|------|---------|-------------|
1818+| `bind` | string | `"0.0.0.0:3000"` | Address and port for the appview HTTP server |
1919+| `tap_url` | string | `"ws://localhost:2480/channel"` | WebSocket URL for [TAP](https://github.com/bluesky-social/indigo/tree/main/cmd/tap) |
2020+| `tap_acks` | bool | `true` | Whether to acknowledge TAP messages |
2121+| `tap_reconnect_delay` | u64 | `5` | Seconds to wait before reconnecting after a TAP connection error |
2222+| `index_path` | string | `"./data/index.db"` | Path to the shared zone index SQLite database |
2323+| `db_dir` | string | `"./data/dbs"` | Directory for per-DID SQLite databases |
2424+2525+### `[appview.database]`
2626+2727+| Key | Type | Default | Description |
2828+|-----|------|---------|-------------|
2929+| `busy_timeout` | u64 | `5` | Seconds to wait when the database is locked |
3030+| `user_max_connections` | u32 | `5` | Max connections for per-user database pools |
3131+| `index_max_connections` | u32 | `10` | Max connections for the shared index database pool |
3232+3333+### `[dns]`
3434+3535+| Key | Type | Default | Description |
3636+|-----|------|---------|-------------|
3737+| `appview_url` | string | `"http://localhost:3000"` | URL of the appview API |
3838+| `bind` | string | `"0.0.0.0"` | Address for the DNS server to listen on |
3939+| `port` | u16 | `5353` | Port for the DNS server |
4040+| `tcp_timeout` | u64 | `30` | Seconds before a TCP connection times out |
4141+| `ttl_floor` | u32 | `60` | Minimum TTL enforced on all DNS responses |
4242+| `slow_query_threshold_ms` | u64 | `50` | Log a warning for queries slower than this (milliseconds) |
4343+| `ns` | list\[string\] | `["ns1.example.com.", "ns2.example.com."]` | NS records served for all zones (fully qualified, trailing dot) |
4444+| `metrics_bind` | string | `"0.0.0.0:9100"` | Bind address for the metrics HTTP server |
4545+4646+### `[dns.soa]`
4747+4848+Default SOA record values for zones without a user-published SOA. These fields are defined in RFC 1035 Section 3.3.13 and are primarily relevant for nameserver maintenance operations between primary and secondary servers.
4949+5050+| Key | Type | Default | Description |
5151+|-----|------|---------|-------------|
5252+| `ttl` | u32 | `3600` | SOA record TTL in seconds |
5353+| `refresh` | i32 | `3600` | SOA refresh interval in seconds |
5454+| `retry` | i32 | `900` | SOA retry interval in seconds |
5555+| `expire` | i32 | `604800` | SOA expire interval in seconds |
5656+| `minimum` | u32 | `300` | SOA minimum (negative cache) TTL in seconds |
5757+| `mname` | string | `"ns1.example.com."` | Primary nameserver (fully qualified) |
5858+| `rname` | string | `"admin.example.com."` | Admin email in DNS format (fully qualified) |
5959+6060+**Field details:**
6161+6262+- **`refresh`** -- The interval at which secondary nameservers should poll the primary to check if the zone's serial number has incremented.
6363+6464+- **`retry`** -- If a secondary fails to reach the primary during a refresh attempt, it retries after this many seconds.
6565+6666+- **`expire`** -- If a secondary cannot reach the primary for this long, it stops serving the zone entirely and returns SERVFAIL. This is the upper bound on how long stale data can be served.
6767+6868+- **`minimum`** -- Originally defined in RFC 1035 as a lower bound on TTL for all RRs in the zone (resolvers would set TTL to the maximum of the record's own TTL and this value). RFC 2308 redefined this field to mean the **negative caching TTL** -- how long resolvers should cache NXDOMAIN and NODATA responses.
6969+7070+- **`mname`** -- The FQDN of the primary nameserver for the zone. Must include the trailing dot.
7171+7272+- **`rname`** -- The email address of the zone administrator, encoded in DNS format: the `@` is replaced with a `.`, so `admin@example.com` becomes `admin.example.com.`. Must include the trailing dot. This is informational and not used by resolvers programmatically, but it is exposed in SOA query responses.
7373+7474+### `[verify]`
7575+7676+| Key | Type | Default | Description |
7777+|-----|------|---------|-------------|
7878+| `appview_url` | string | `"http://localhost:3000"` | URL of the appview API |
7979+| `bind` | string | `"0.0.0.0"` | Address for the verify API server |
8080+| `port` | u16 | `3001` | Port for the verify API server |
8181+| `check_interval` | u64 | `60` | Seconds between scheduled verification runs |
8282+| `recheck_interval` | i64 | `3600` | Seconds a zone must be stale before reverification |
8383+| `expected_ns` | list\[string\] | `["ns1.example.com", "ns2.example.com"]` | Expected NS records that indicate correct delegation (should match `dns.ns`) |
8484+| `nameservers` | list\[string\] | `[]` | Custom resolver IP addresses (optional, uses system resolvers if empty) |
8585+| `dns_port` | u16 | `53` | Port used when resolving against custom nameservers |
8686+8787+## Example config
8888+8989+A full `onis.toml` with all defaults:
9090+9191+```toml
9292+[appview]
9393+bind = "0.0.0.0:3000"
9494+tap_url = "ws://localhost:2480/channel"
9595+tap_acks = true
9696+tap_reconnect_delay = 5
9797+index_path = "./data/index.db"
9898+db_dir = "./data/dbs"
9999+100100+[appview.database]
101101+busy_timeout = 5
102102+user_max_connections = 5
103103+index_max_connections = 10
104104+105105+[dns]
106106+appview_url = "http://localhost:3000"
107107+bind = "0.0.0.0"
108108+port = 5353
109109+tcp_timeout = 30
110110+ttl_floor = 60
111111+slow_query_threshold_ms = 50
112112+ns = ["ns1.example.com.", "ns2.example.com."]
113113+metrics_bind = "0.0.0.0:9100"
114114+115115+[dns.soa]
116116+ttl = 3600
117117+refresh = 3600
118118+retry = 900
119119+expire = 604800
120120+minimum = 300
121121+mname = "ns1.example.com."
122122+rname = "admin.example.com."
123123+124124+[verify]
125125+appview_url = "http://localhost:3000"
126126+bind = "0.0.0.0"
127127+port = 3001
128128+check_interval = 60
129129+recheck_interval = 3600
130130+expected_ns = ["ns1.example.com", "ns2.example.com"]
131131+nameservers = []
132132+dns_port = 53
133133+```
+7-7
onis-common/src/config.rs
···141141 slow_query_threshold_ms: 50,
142142 soa: SoaConfig::default(),
143143 ns: vec![
144144- "ns1.kiri.systems.".to_string(),
145145- "ns2.kiri.systems.".to_string(),
144144+ "ns1.example.com.".to_string(),
145145+ "ns2.example.com.".to_string(),
146146 ],
147147 metrics_bind: "0.0.0.0:9100".to_string(),
148148 }
···176176 retry: 900,
177177 expire: 604800,
178178 minimum: 300,
179179- mname: "ns1.kiri.systems.".to_string(),
180180- rname: "admin.kiri.systems.".to_string(),
179179+ mname: "ns1.example.com.".to_string(),
180180+ rname: "admin.example.com.".to_string(),
181181 }
182182 }
183183}
···193193 pub port: u16,
194194 /// Seconds between scheduled verification runs.
195195 pub check_interval: u64,
196196- /// Seconds a zone must be stale before rechecking.
196196+ /// Seconds a zone must be stale before reverification.
197197 pub recheck_interval: i64,
198198 /// Expected NS records that indicate correct delegation.
199199 pub expected_ns: Vec<String>,
···212212 check_interval: 60,
213213 recheck_interval: 3600,
214214 expected_ns: vec![
215215- "curitiba.ns.porkbun.com".to_string(),
216216- "maceio.ns.porkbun.com".to_string(),
215215+ "ns1.example.com".to_string(),
216216+ "ns2.example.com".to_string(),
217217 ],
218218 nameservers: vec![],
219219 dns_port: 53,