Configuration reference
Every key the daemon parses from /etc/atlas/config.toml, with types, defaults and behavior. This page is generated from the same schema the daemon generates from its own configuration structs (atlasd config schema), so it cannot drift from what a release actually accepts. Add #:schema pointing at that schema file to your config and a TOML-aware editor validates as you type.
atlasd config check -c /etc/atlas/config.toml runs the daemon’s exact load pipeline — exit 0 means loadable, exit 1 means the daemon would refuse to start. Sections marked opt-in leave the data path byte-identical to a build without the feature until enabled.[interface]
requiredTunnel address of this node as IPv4 CIDR, e.g. 10.0.100.1/24. Bare addresses imply /24.
UDP source port every link binds by default (WireGuard-style single port). Per-link listen_port overrides it.
TUN interface name (e.g. nexus0). Identifies this daemon instance in stats files, the web UI and the CLI.
Base64 Curve25519 private key (from atlasd keygen). Keep the file mode 0600 — this is the node's identity.
unsetBrief note describing what this atlas instance is for, e.g. "office to vehicle" or "ground station to aircraft". Surfaced in the web UI header beside the interface name so an operator can tell multiple atlas instances apart at a glance. Local-only — not advertised in LSAs.
trueEndpoint roaming (WireGuard semantics, per link): when an AUTHENTICATED packet from a peer arrives from a new source address, adopt it as that peer's endpoint for the receiving link. Lets a mobile node (drone re-associating to a different ground radio / mesh relay) keep the tunnel alive without restarts. On by default; static fleets are unaffected because their traffic already arrives from the configured endpoints. Probes/keepalives are unauthenticated and never steer endpoints.
1420TUN device MTU. Default 1420 (1500 minus tunnel overhead).
unsetHuman-readable label for this node, advertised in our LSAs so peers can show it in their topology view. Optional — when omitted the daemon falls back to the system hostname.
unsetWhat this node physically is, advertised in our LSAs beside the position so peers can tell a drone from a rover from a mast without guessing from the name. Purely descriptive — nothing in the data path reads it; the topology views (atlas-sim, dashboard) use it to pick a symbol. Well-known values are listed in KNOWN_NODE_ROLES (ground-station, uav, ugv, usv, dismount, relay); anything else is passed through unchanged with a config-check warning, so a fleet can coin its own.
unsetStatic position of this node as [lat_deg, lon_deg, alt_m] (WGS-84). Advertised in our LSAs for peers' topology prediction and relay planning. Fixed installations set it here; mobile nodes instead stream fixes through the telemetry socket (node_position JSON messages), which override this value.
[[link]]
requiredOne underlay link of the bond: a UDP socket pinned to a physical device. type = "relay" makes it a relay link (peer traffic wrapped in encrypted envelopes through a Nexus Atlas relay server).
Local IP the socket binds. 0.0.0.0 = any IPv4; a bare IPv6 address selects the v6 family.
Network device the link's UDP socket is bound to (SO_BINDTODEVICE), e.g. eth0, wlan1, ppp-sik.
Link name, unique within this config. Referenced by scheduler priority_order, peer endpoint_per_link and telemetry events.
Legacy capacity field, always in Mbps. Overridden by capacity when both are set.
Nominal capacity of the physical link — the reference ceiling the scheduler's cost functions divide by. Unit-tagged string ("64 kbps", "100 Mbps", "1.5 Gbps", case-insensitive) or a bare number in Mbps. Default 80 Mbps when neither this nor bandwidth_mbps is set.
Accepted alias for probe_interval_ms.
trueSet false to keep the link configured but unused. Default true.
Per-link UDP source port overriding [interface] listen_port. REQUIRED when two links share bind_device+bind_address (SO_REUSEPORT would otherwise load-balance them against each other).
Maximum usable radio range in meters. Only meaningful with [link_monitor] prediction_source = "position"/"both": scheduler-facing loss inflates as the projected peer distance approaches it. Default: the global range_full_m.
Per-link probe (health-check) interval in ms, overriding the global [link_monitor] probe_interval_ms for this link only.
Metered-link budget: wire bytes this link may carry per quota_period. Unit-tagged string (kB/MB/GB/TB are decimal, KiB/MiB/GiB/TiB binary) or a bare number of bytes. Omit for an unmetered link. An over-budget link is not promoted by the scheduler while another link is usable, but is still used when it is the last path.
"monthly"Window the quota applies to: monthly (default), weekly, daily, or a sliding rolling-<N>d window.
1Anchor for the calendar periods: day-of-month for monthly (1-31, clamped to the month's length), ISO day-of-week for weekly (1 = Monday … 7 = Sunday). Ignored by daily and rolling-<N>d.
80Percent of the budget at which the link is reported as warning (journal event link.quota_warn, warning in the stats snapshot). 0 disables the warning.
Distance in meters where this link's range penalty starts ramping. Default 60% of max_range_m when that is set, else the global range_warn_m.
Base64 static public key of that relay, pinned — authenticates the relay itself.
ip:port of the relay server (its STUN/relay port, conventionally 3478). Required for type = "relay" unless traversal discovery resolves it.
Link-state flooding interval for THIS link in seconds, overriding the global [mesh] route_advert_interval_secs. Lets a narrow UHF bearer flood slowly while a wideband one keeps the fast cadence. Clamped to 30 s so a peer can never age this node's LSA out.
"direct"direct (default) or relay. A relay link carries peer traffic through a Nexus Atlas relay server and needs relay_server + relay_pubkey (or traversal discovery).
directrelayRound-trip time in ms past which a returning probe on THIS link stops counting as evidence the link works. Overrides the global [link_monitor] unusable_rtt_ms; 0 disables the rule for this link.
1Relative weight for the weighted_round_robin strategy. Default 1.
[[peer]]
Tunnel IPv4 CIDRs routed to this peer (WireGuard semantics), e.g. ["10.0.100.2/32"]. Bare addresses imply /32.
Base64 Curve25519 public key of the peer — its identity.
[]Known endpoints, positionally per link. **Optional**: a peer reached through a relay — or one that will only ever be reached by hole punching — has no endpoint at all. Its identity is its public key, and its address is discovered at runtime (from the relay envelope, or from a punched candidate). Requiring an endpoint here would make the whole traversal stack unusable, since "I do not know where this peer is" is precisely the problem it exists to solve.
Explicit link-name → endpoint mapping. When non-empty, atlasd uses *only* this map for outbound sends to this peer: a link whose name has no entry here is not used to reach the peer at all. Useful when each radio has its own point-to-point IP pair (e.g. a multi-modem setup) so a packet that's bound to one link's interface can't be routed to the *other* link's remote IP without bypassing kernel iface pinning.
When empty (default), the legacy positional behaviour applies: endpoint[i] is used for link i, with fallback to endpoint[0] when the index is out of range.
[[peer]]
public_key = "..."
endpoint = [] # not used when endpoint_per_link is set
endpoint_per_link = { "sik-hb" = "10.0.1.2:51820",
"sik-rfd" = "10.0.2.2:51820" }
allowed_ips = ["10.0.100.2/32"]unsetSend a keepalive to this peer every N seconds so NAT/stateful firewall mappings stay open. Omit to disable (default).
[scheduler]
5000Minimum dwell (ms) before the adaptive strategies de-escalate to fewer links; escalation is immediate. Default 5000.
0.9Enter n=2 when primary_cost / next_cost ≥ this. Default 0.9.
0.5Drop back to n=1 only when primary_cost / next_cost ≤ this. Default 0.5 (Schmitt gap of ~2× prevents flapping).
0.5Enter n=3 when primary_cost / third_cost ≥ this. Default 0.5.
0.25Drop from n=3 to n=2/n=1 only when primary_cost / third_cost ≤ this. Default 0.25.
10Piggyback a loss-probe sequence on every Nth real fragment so the peer can measure data-fragment loss directly (instead of just probe loss, which underestimates burst-loss damage on full-size fragments). Set to 0 to disable. Only takes effect when strategy = "adaptive". Default 10.
40Engage n=2 when the best link's RTT ≥ this many ms. Default 40.
100Engage n=3 when the best link's RTT ≥ this many ms. Default 100.
20Engage n=2 when the best link's loss ≥ this percent. Default 20.
50Engage n=3 when the best link's loss ≥ this percent. Default 50.
[]Link names in priority order, highest-priority first. Only honoured when strategy = "priority". Names are matched against [[link]].name entries; unknown names are ignored with a warning at engine startup.
1Send every fragment over up to this many of the best alive links at once. 1 (default) = single path. The adaptive strategies manage their own redundancy and ignore this.
"lowest_delivery_time"Multipath scheduling strategy. Default lowest_delivery_time.
lowest_delivery_timeweighted_round_robinbroadcastpriorityshortest_pathadaptiveloss_adaptivelatency_adaptive[link_monitor]
5Consecutive missed probes before a link is declared dead. Default 5.
unsetWhat feeds predictive scheduling/topology decisions: "none" (default), "rssi", "position", or "both". - rssi: local RSSI trend inflates scheduler-facing loss (see rssi_floor_dbm/rssi_lookahead_secs), and LSA-advertised per-link RSSI weights SPF costs. - position: LSA-advertised node positions/velocities are projected ahead; stretched links get expensive in SPF and the local scheduler (range_warn_m/range_full_m). - both: max of the two risks per link. Prediction inflates costs/loss only — probes remain the sole authority on link death, and dashboards keep measured values.
nonerssipositionboth250Probe (health-check) interval per link, in milliseconds. Default 250. Per-link probe_interval_ms overrides it.
1000Projected inter-node distance (m) where the position-based penalty reaches its maximum.
600Projected inter-node distance (m) where the position-based penalty starts ramping.
-88RSSI (dBm) below which a link is considered effectively dead for prediction purposes.
2How far ahead (seconds) the RSSI trend is projected.
falseLegacy switch (predates prediction_source): true behaves as prediction_source = "rssi" when prediction_source is unset.
10000Round-trip time past which a probe that DOES come back stops counting as evidence the link works, in milliseconds. Default 10000; 0 turns the rule off.
Without it, liveness means "a round trip completed eventually", which a deeply queued link satisfies forever: probes return tens of seconds late, probe loss reads 0%, the link reads up, and traffic through it measures 100% loss. Probes past this ceiling are counted as misses, so the ordinary dead_probe_count rule declares the link dead — no separate state machine, and one late probe still cannot take a link down. Per-link [[link]] unusable_rtt_ms overrides it.
[crypto]
falseWhen true, payloads are sent in plaintext (no AEAD). Useful for performance testing. Both peers must have this set identically.
1073741824Also rekey after this many payload bytes on a session. Default 1073741824 (1 GiB).
120Re-run the Noise handshake with every peer after this many seconds. Default 120.
[auth]
Pluggable peer authentication ([auth]).
Controls what happens when a HandshakeInit arrives from a static public key that is NOT in the [[peer]] list. Configured peers are always accepted (they carry explicit operator intent) — the provider only ever *extends* trust to unknown keys, so the default is exactly today's behaviour: drop them.
[auth]
provider = "keyfile"
keyfile = "/etc/atlas/authorized_peers.toml"Providers: - "static" (default): unknown keys are rejected. Identical to a config with no [auth] table. - "keyfile": unknown keys are looked up in keyfile, a TOML allowlist of [[peer]] public_key = "...", allowed_ips = [...] entries. The file is re-read when its mtime changes, so keys can be granted/revoked without restarting the daemon (revocation stops NEW sessions; established sessions live until rekey). - "command": unknown keys are passed to an external hook — command <base64-pubkey> <source-addr> — which decides. Exit 0 authorizes; each stdout line is an allowed-IPs CIDR for the peer. Any other exit status denies. This is the integration point for an external control plane (console enrollment DB, LDAP, …).
Library embedders can bypass all of this and inject their own implementation of auth::PeerAuthenticator via Engine::with_authenticator.
unsetHook executable for provider = "command".
5000Hard cap on how long the command hook may run before the handshake is dropped (the hook keeps running; its verdict is simply too late).
30A denied key is not re-checked for this long — keeps a handshake flood from an unauthorized key from hammering the file/hook.
unsetAllowlist file for provider = "keyfile".
"static"static (default, unknown keys rejected), keyfile, or command. Misconfiguration refuses to start.
statickeyfilecommand[routing]
Routing knobs.
- path_redundancy drives the 4.2 "dual-SPF" scenario: when K = 1 (default) atlas behaves as before, SPF picks one shortest path per destination; when K ≥ 2 atlas computes top-K next-hops and fans every outgoing/forwarded fragment across all of them with a receive-side dedup window. Killing any single link in the diamond becomes packet-loss-free because the alternate path is already carrying live traffic.
- static_path drives the 4.3 "static multipath" scenario: when one or more entries are present, atlas stops consulting SPF for forwarding entirely and routes purely off the operator-declared path table. Each path is a full hop list of tunnel IPs and carries a stable path_id that is stamped into the relay header so every intermediate node can pick the right next-hop without a database lookup. SPF/probing still runs (for telemetry); only the forwarding decision is overridden.
The two knobs are mutually exclusive: when static_path is non-empty the static FIB wins and path_redundancy is ignored.
1Top-K next-hops to fan out across. 1 = single-path (default, unchanged behaviour). 2+ = dual/multi-SPF.
[]Operator-declared static paths. Empty (default) = SPF / dual-SPF routing. Non-empty = static-multipath: forwarding uses these entries exclusively.
Each entry:
hopsarray of string required — Full path as a sequence of tunnel IPv4 addresses (origin first, final destination last). At least two entries required.namestring required — Human-readable label, surfaced in stats/logs.path_idinteger required — Stable u16 path identifier, stamped intoRelayHeader.path_id.
[multicast]
opt-in · default offSubscriber-aware multicast distribution trees ([multicast]). **Opt-in. Default OFF.** Off, inner multicast keeps the flat-mesh semantics: a packet to 224.0.0.0/4 is replicated at the source, once per peer. On, traffic to a group listed in groups is carried as a source-rooted SPF distribution tree instead — one copy per shared segment, forked only where subscriber paths diverge. Subscriptions are advertised in the LSA flood (additive, wire-compatible field); every node that sources or forwards a tree group should carry the same groups list.
[multicast]
enabled = true
groups = ["239.10.10.10"] # tree-distributed groups (fleet-wide)
subscribe = ["239.10.10.10"] # deliver these to THIS node's TUNfalseMaster switch.
[]Multicast groups (IPv4, 224.0.0.0/4) distributed as trees. Groups not listed here keep the flat per-peer fan-out.
[]Groups this node subscribes to: advertised to the mesh and delivered to the local TUN (the kernel still filters by the application's own group joins, exactly as with flat fan-out).
[mesh]
opt-in · default offMesh control plane configuration.
[]Bootstrap peer endpoints for initial join.
trueWhether mesh-wide config changes propagate to all nodes.
falseEnable mesh mode (gossip-based CRDT peer discovery).
60Seconds after which a non-heartbeating node is considered dead.
60How long a gossip target may go without a full roster re-send. Between full syncs a target receives only members whose clock moved since we last spoke to it, so this is the bound on repairing a document that was lost in flight. Default 60 s.
5Gossip interval in seconds (how often to sync state with a random peer).
falseAccept AND emit legacy plaintext (truncated-hash) gossip bodies for mixed fleets still running pre-v2 daemons. Default false: v2 (encrypted NAG2) only, and inbound v1 is dropped with a warning.
10Heartbeat interval in seconds.
1330Ceiling on one gossip document, in serialized JSON bytes.
The document goes out as a single UDP datagram: oversize it and the IP layer fragments it, at which point ONE lost fragment discards the entire membership update. Capping it turns that into a page — the members that did not fit lead the next document to the same target. Default 3000 (~config block + 3 members). Set 0 to disable the cap and send the whole roster in one datagram (pre-paging behaviour).
""Shared secret for mesh authorization (base64-encoded).
trueLet mesh members read this node's /api/config and /api/stats with a token derived from mesh_secret (atlasd config node-token), even under [web] protect = "all". Read-only and window-limited; it never creates a session and never authorises a write. Default true — protect = "all" is a deliberate lockdown, so set this false to close machine reads as well (the fleet compare then shows this node as unauthorized, as before).
unsetThis node's role for signed config epochs: an epoch's [roles.<name>.<section>] overlay applies only to nodes whose role matches, and target_roles gates whether an epoch is applied here at all. Optional; unset = untargeted by role-scoped epochs.
2Route advertisement interval in seconds.
90Route expiry in seconds (advertised routes removed after this).
60How often to re-contact bootstrap_peers once every seed is in the roster, in seconds.
Joining is not a one-shot: two halves of a mesh that have each converged internally share no member, so nothing but the seed list spans the split and gossip alone can never merge them. Re-sending a MeshJoin to the seeds on a slow timer is what makes a partition heal. Default 60 s; 0 disables the refresh (join once, as before).
[dns]
opt-in · default offMesh DNS ([dns]) — a per-node local resolver answering mesh names straight from the LSDB.
**Opt-in. Default OFF.** With enabled = false no socket is opened and no task is spawned. When on, the daemon binds a small DNS server (UDP + TCP) to the tunnel address and answers A/AAAA/PTR for <node_name>.<domain> from its own link-state database — no server anywhere in the mesh, no coordination plane, and each partition keeps resolving its own half's names because each half has its own LSDB.
DNS is a tenant of the tunnel, never a prerequisite for it: peer endpoints remain IP literals and nothing in tunnel establishment ever performs a lookup.
[dns]
enabled = true
domain = "atlas"
mode = "split"
[[dns.override]]
name = "video.acme.com"
a = ["10.0.100.7"]
[[dns.forward]]
suffix = "corp.acme.com"
servers = ["10.0.100.53"]"atlas"Zone suffix; a node's FQDN is <node_name>.<domain>. Must already be DNS-safe (lowercase [a-z0-9-.]).
falseMaster switch.
[]Per-suffix forwards ([[dns.forward]]): a customer's internal resolver, typically reachable only over the tunnel.
Each entry:
serversarray of string required — Resolvers for the suffix, as IP orIP:port(port defaults to 53).suffixstring required — Domain suffix (e.g.corp.acme.com) — matches the suffix itself and everything under it.
[]Listen addresses as IP:port (a bare IP gets port 53). Empty (the default) means the [interface] tunnel address on port 53. config check HARD-REFUSES wildcards (0.0.0.0/[::]) — a mesh resolver on a public interface is an open-resolver / amplification hazard — and warns when an address is neither the tunnel address nor loopback.
"split"split (default): mesh zone answered locally, everything else relayed to upstream. mesh-only (EMCON posture): out-of-zone queries answered REFUSED — no query ever leaves on an uplink.
splitmesh-only[]Split-horizon overrides ([[dns.override]]): names answered authoritatively with tunnel-side addresses when queried over the tunnel, regardless of zone — outside, public DNS answers.
Each entry:
aarray of string — IPv4 answers.aaaaarray of string — IPv6 answers.cnamestring — CNAME target. Exclusive ofa/aaaa.namestring required — Exact name to answer for (e.g.video.acme.com).
trueServe PTR (reverse) zones over the mesh's tunnel prefixes.
["9.9.9.9","149.112.112.112"]Upstream resolvers for out-of-zone queries in split mode, as IP or IP:port (port defaults to 53). Default: Quad9.
800Hard deadline for an upstream answer, milliseconds. Expiry answers SERVFAIL — a dead upstream must never become a hang, and a contested uplink never blocks in-mesh resolution.
[traversal]
opt-in · default offNAT traversal (the ".net" connectivity stack). **Opt-in. Default OFF.** With enabled = false (or no [traversal] table at all) no STUN demux runs, no netcheck task is spawned, and the data path is byte-identical to a build without traversal.
Phase 0 scope: netcheck — per-link STUN probes against two-IP observation points (our relays double as STUN servers), NAT mapping classification, and a JSON report at /tmp/atlas/<iface>.netcheck.json for the web UI / status CLI.
falseAuto-election of the shared relay set. When enabled (traversal on), the daemon periodically STUN-probes every configured relay link, advertises that RTT vector to each peer over the relay control channel, and — from the deterministic joint ranking both ends independently compute — keeps exactly relay_paths relay sessions **active**, gating the rest. A pair thus auto-converges on the same shared relay(s) with no negotiation, and re-elects the same next-best relay on failure. Off (default) = every configured relay link stays active, i.e. the legacy static behaviour.
trueRuntime relay discovery. When enabled (and traversal is on), a relay link that omits relay_server/relay_pubkey resolves its relay from the signed relay map fetched from the control plane at startup. Static per-link config always wins when present. A no-op if every relay link is statically configured.
falseMaster switch.
300Netcheck re-run cadence in seconds (it always runs once shortly after startup). 0 disables the periodic re-run.
1500Per-request STUN response timeout in milliseconds.
trueHole punching: exchange candidates with peers over the relay and try to bring up a DIRECT path alongside the relayed one. On by default when traversal is enabled — a failed punch costs nothing (the relay keeps carrying the traffic), and a successful one removes a hop and the relay's bandwidth bill.
unsetHome-region hint for relay selection, e.g. "eu-central". None → pick the lowest-RTT relay across all regions.
unsetOverride the control-plane base URL the signed relay map is fetched from ({base}/v1/relays). None → the baked-in default.
1How many relays to hold a session to **concurrently** for a peer, from the deterministically-ranked preference list (best-first). 1 (default) = one shared relay per pair, re-elected on failure. 2 = the best two relays simultaneously for redundancy, etc. A punched DIRECT path (if any) is always additional to these. Clamped to at least 1.
[]STUN observation points as IP:port. Two entries with DIFFERENT IPs are required for mapping classification (a single relay's address pair is exactly that). Later phases populate this from the signed relay map; static config always wins when set.
[qos]
opt-in · default offQoS / transport-class data-path configuration (features K1–K4 + K3 store-carry-forward).
**Opt-in. Default OFF.** When enabled = false (the default, and the state for any config that has no [qos] table at all), the data path behaves byte-identically to a build without QoS: classification, the class queue, per-class multipath and the bundle store are never constructed and the legacy outbound/inbound paths run unchanged.
The active policy is loaded at startup from /tmp/atlas/<iface>.qos.json (the same file the web UI / daemon writes) and re-read every reload_secs so an operator's "Apply" takes effect live. An absent or corrupt file falls back to PolicyTable::tactical_default.
4000000ClassQueue AQM byte budget across all classes.
"memory"Bundle durability backend: "memory" | "file".
memoryfiletrueK3 store-carry-forward for the StoreCarryForward (Bulk) class.
600000Per-bundle lifetime in milliseconds before it expires unsent.
16000000Total bundle payload byte cap.
10000Total bundle count cap.
""Write-ahead-log path when bundle_backend = "file". Per-iface OK.
1000Upper clamp on the derived deadline budget, milliseconds.
80Lower clamp on the derived deadline budget, milliseconds.
3.5Deadline budget multiplier: budget = k * worst alive-link RTT.
falseMaster switch. false (default) = legacy data path, no QoS.
8FEC block size k: number of data packets batched before parity shards are appended and the block is shipped.
200FEC RX expiry: give up on an incomplete block after this many milliseconds (deliver the data shards that arrived, drop the rest).
falseForward-error-correction master switch. Opt-in; false (default) = no FEC even for classes whose policy is Fec. When true, any class whose MultipathPolicy is Fec { overhead_pct } has its packets batched into blocks, parity shards generated, and lost packets reconstructed on the receiver with NO retransmission. Doubly gated: this switch AND the per-class Fec policy must both be set.
60FEC TX flush: emit a partial block after this many milliseconds of idle so latency stays bounded when fewer than k packets are in flight.
2How often to re-read the <iface>.qos.json policy file, seconds. 0 = never reload (load once at startup).
120Relative arrival-based hold time for the RX release buffer, in milliseconds. Each Video packet is held ~this long from local arrival then released in sequence order. 0 falls back to the default (120); never unbounded.
1024Per-peer cap on buffered Video packets in the RX release buffer. On overflow the lowest sequence is force-released early.
falseReceiver-side release buffer (jitter / reorder buffer with late-drop). Opt-in master switch; false (default) = legacy RX path. Only ever applied to the Video (DeadlineBounded) class — never to any other class or reliable traffic.
[telemetry]
opt-in · default offOut-of-band telemetry feed from per-radio adapter processes (e.g. atlas-sik). Adapters open a Unix domain socket here and push newline-delimited JSON LinkTelemetry events. Each event names a link (matching [[link]] name) and carries radio-native signals — RSSI, noise floor, TX buffer free space — that the OS can't see.
Strictly opt-in. Disabled by default; the scheduler doesn't depend on any of this for correctness.
trueReport link telemetry to the customer console (console.nexusatlas.net) every ~30 s. Opt-out — true by default, but a node that was never enrolled sends at most one token-mint request (the console answers 404 not_enrolled and the reporter stops for the daemon's lifetime). Independent of enabled, which gates only the local adapter socket.
unsetConsole base URL override. Resolution order (highest wins): NEXUS_ATLAS_CONSOLE_URL env var, this key, the built-in default (https://console.nexusatlas.net) — same chain the enroll flow and the web dashboard use.
falseAccept adapter connections on socket_path. Default false.
trueAlso answer to the pre-rename socket path (/run/nexus-atlas/telemetry.sock) by symlinking it onto whatever socket_path bound, so adapters whose units still name it keep connecting during a staged fleet upgrade. Default true. Never clobbers a real socket already sitting there.
"/run/atlas/telemetry.sock"UDS path the adapter connects to. atlasd creates the parent directory and removes any stale socket file at startup.
[metrics]
on by defaultPrometheus / OpenMetrics exposition (GET /metrics on the web server).
**On by default.** "Does it feed our NMS?" is the first question a systems integrator asks, and the answer has to be yes without an operator finding a switch first. It costs nothing when nobody scrapes: the endpoint renders from the snapshot documents the daemon already writes, in the atlasd web process, so the forwarding daemon is not on the path at all.
The endpoint is a plain READ and the node's existing [web] protect posture governs it — open on a protect = "writes" node, session- or token-gated on a protect = "all" node, exactly like /api/stats.
trueMaster switch. false makes the endpoint answer 404.
"/metrics"Exposition path. Change it only when something else on the node already owns /metrics; scrapers assume the default.
[journal]
on by defaultPersistent event journal (/var/lib/atlas/journal/<iface>.jsonl).
**On by default.** Every other view of the node is a live value: once a link flaps back up, nothing on disk remembers that it went down. The journal is what makes "what happened at 14:32?" answerable after the fact, so it has to be on for the incident nobody planned for.
The two size knobs are a hard ceiling, not a target: max_files x max_file_bytes is the most disk one interface's journal can ever use (default 4 x 2 MiB = 8 MiB). max_age_days expires rotated files sooner on a quiet node. See crate::journal for the retention math.
trueMaster switch. false stops the writer thread from starting; the emit sites become a single atomic load and nothing is written.
30Delete rotated files older than this. 0 disables the age bound and leaves the size cap as the only limit.
2097152Rotate the live file once it would exceed this many bytes.
4Files kept INCLUDING the live one. Total disk = this x max_file_bytes.
[syslog]
opt-in · default offSyslog / CEF event export to a collector (the SIEM half of the integrator question).
**Opt-in. Default OFF.** With enabled = false no socket is opened, no thread is spawned and no event is built. When on, events go to a bounded queue drained by one writer thread — the daemon never blocks on a collector that is down, and the events it had to drop are reported into the stream once the collector returns.
falseMaster switch.
"local0"Syslog facility by name (local0…local7, daemon, …) or number.
"rfc5424"Wire format: rfc5424 (structured syslog) or cef (ArcSight Common Event Format).
rfc5424cefunsetHOSTNAME field override. None uses the kernel hostname.
"info"Least severe level that is exported: emerg, alert, crit, err, warning, notice, info, debug.
1000How often the interim snapshot watcher looks for state changes, milliseconds. Irrelevant once the event journal feeds the exporter.
1024Bounded queue depth. Deeper rides out a longer collector outage; beyond it, events are dropped and counted rather than blocking.
"atlas@32473"RFC 5424 SD-ID for the structured-data block. The default carries the enterprise number IANA reserves for documentation; set a real PEN if the collector validates it.
"unix:///dev/log"Collector: udp://host:port, tcp://host:port or unix:///dev/log. A bare host:port means UDP; the port defaults to 514.
[reporting]
on by defaultCrash reporting and the watchdog ([reporting], ).
**Capture is on; sending is not.** The product's positioning is no-phone-home , so the defaults here capture a crash locally, redact it, and stop. With auto_send = false (the default) and relay_peers = false the daemon starts no upload thread and opens no socket to hub_url; a report leaves only when an operator runs atlasd crash export or atlasd crash send <id>, one report at a time. send_mode decides whether such a send names this node.
coredump is off for a harder reason: a coredump of this daemon holds a Curve25519 private key, live Noise session keys and the mesh secret. It cannot be turned on without coredump_pubkey, because the only acceptable core is one encrypted to the hub at capture time.
falseopt-in: upload spooled reports in the background instead of waiting for atlasd crash send. Off by default — per-report consent is the default posture, and this is the switch that trades it away deliberately.
falseLet systemd-coredump capture a full core and attach it encrypted. Requires coredump_pubkey; see the struct docs.
Base64 X25519 hub key a core is encrypted to at capture time.
trueMaster switch for crash capture. false installs no panic hook and no signal handlers, and writes no markers.
falseCarry whole peer public keys instead of 8-character fingerprints.
"https://console.nexusatlas.net"Collector base URL. Sovereign customers self-host; nothing in the tree hardcodes a collector beyond this default.
200Journal entries attached to a report (the tail). Capped at the hub's 200.
8388608Total spool size. Whichever bound binds first evicts the oldest.
20Reports kept in the spool.
falseSame, for the copy kept for local export.
trueRemove addresses, endpoints, hostnames and node names from the form of the report that would be uploaded.
falsePull crash reports from mesh members that have no route to the hub and forward them. Requires [mesh]; off by default, because relaying another node's diagnostics is a decision.
"attributed""attributed" (default) or "anonymous" — two modes.
Attributed carries this node's public key and presents the ingest token, so the report lands in the owning account's console. Anonymous carries no identity and no credential: the fingerprint still groups the crash with everyone else's, but nothing says whose it was. Anonymous also **forces redact_uploads** — a report that still named an endpoint would not be anonymous.
trueFeed systemd's watchdog from the data-path liveness counters. Harmless when the unit has no WatchdogSec=: with no $WATCHDOG_USEC in the environment nothing is sent.
3Consecutive failed liveness checks before the watchdog stops feeding systemd. One missed check is a scheduling hiccup; three in a row is a wedged data path.
[logging]
"info"Log level / tracing filter: trace, debug, info (default), warn, error, or any RUST_LOG-style directive string.