CLI reference
One binary carries everything: atlasd is the daemon, the control CLI, the web server and the tooling. (Packaging installs a nexus-atlasd compatibility symlink beside it for older unit files.) Commands default to config /etc/atlas/config.toml and interface nexus0 where those apply.
Daily drivers
atlasd keygenGenerate a Curve25519 keypair, base64-encoded — the node identity. The private key goes into this node's [interface], the public key into every peer's [[peer]] block for it.
$ atlasd keygen
✓ Keypair generated (Curve25519)
Private Key (keep secret)
private_key = "4AiNx2P9vKq8mW3jR7hT5cL0dF6gY1bZ4nS8uE2oKEY="
Public Key (share with peers)
public_key = "9XpQm4Wv7Jk2Rt8Ny5Bc1Hf3Zd6Ls0Ga9Ue7Iw2bQc="
» Add these to your /etc/atlas/config.toml
» Share only the public key with remote peers
atlasd run -c <config>The daemon itself. Under systemd, startup completes only when the TUN exists and every link is serviced (Type=notify) — "started" means the data path is up, not that the process exec'd.
$ sudo atlasd run -c /etc/atlas/config.toml
Nexus Atlas v3.0.0+7c341a4
wire 5 · relay 2 · seal 2 · pairing 3 · adapter 1 · report 2 · api 1
… handshake init from peer 1 processed, sending response
… handshake complete with peer 1
… all peer handshakes established
$ sudo systemctl start nexus-atlasd # returns when TUN + links are serviced
atlasd statusFreshness-checked digest of every daemon instance on the host: interface, address, strategy, links alive, peers established, and a bearers block with one line per member whose advert lists its bearer kinds — what it rides on, a dead kind marked (down), and the kind at the far end of this node's direct path. The thirty-second answer to "is it running and is it healthy".
$ atlasd status
Nexus Atlas v3.0.0+7c341a4
nexus0 10.0.100.1/24 lowest_delivery_time 2/2 links alive 1 peer established
bearers
node-a (this node): Ethernet + Wi-Fi
node-b: Ethernet + Cellular (down) · direct over Ethernet
atlasd stats -i nexus0 -f pretty|json|json-prettyOne-shot snapshot dump. The JSON forms are stable integration surfaces — the same document served at /api/stats.
$ atlasd stats -i nexus0 -f json | jq '.links[0]'
{
"id": 0,
"name": "wired",
"bind_device": "eth0",
"alive": true,
"rtt_ms": 0.42,
"jitter_ms": 0.05,
"loss_pct": 0.0,
"capacity_mbps": 100.0,
"quality_score": 0.98,
"tx_bytes": 104857,
"rx_bytes": 99231
}
atlasd monitor -i nexus0 -r 500Live terminal dashboard, refresh in milliseconds. Keys: q quit, g sparklines, p pause. The fastest way to watch a failover happen.
atlasd web -i nexus0 -l 0.0.0.0:9800The REST API and browser dashboard. Static UI assets are served from disk (/opt/atlas/web); without them the port is API-only.
$ atlasd web -i nexus0 -l 0.0.0.0:9800 &
$ curl -s localhost:9800/api/stats | jq .strategy
"lowest_delivery_time"
$ curl -fsS localhost:9800/api/health >/dev/null && echo healthy
healthy
atlasd journal [-c category] [-s severity] [--since 30m] [--code link.down] [--follow] [--json]Read the persistent event journal; --follow tails it live, --json makes it a pipeline source. Default limit 50 entries, newest first.
$ atlasd journal -c link -s warn --since 24h
2026-08-13 14:32:01 WARN link.down link wired on nexus0 went down reason=probe_timeout missed_probes=5
2026-08-13 14:31:42 WARN link.quota_warn link lte0 at 80% of monthly budget used_pct=80
$ atlasd journal --json -n 1
{"v":1,"seq":891,"ts":1786297001,"category":"link","severity":"warn","code":"link.down","msg":"link wired on nexus0 went down","fields":{"reason":"probe_timeout","missed_probes":5}}
Configuration tooling
atlasd config check [-c path] [--json]The daemon's exact load pipeline without starting the engine. Exit 0 = loadable (warnings allowed), exit 1 = the daemon would refuse to start. --json emits {ok, findings:[{fatal, path, message}]} for CI gates. In a record fleet, a config with an interconnect seam is also checked against the node's own record in the list it holds: every route, map or export outside the record's interconnect section is refused, naming the record and its lists (the running daemon enforces the record either way).
$ atlasd config check -c node-a.toml
✓ node-a.toml is valid
$ atlasd config check -c tuned.toml
✓ tuned.toml is loadable (2 warnings)
$ atlasd config check -c broken.toml
✗ broken.toml has fatal errors — the daemon would refuse to start
$ echo $?
1
atlasd config schemaPrint the config JSON Schema (draft-07), generated from the daemon's own structs. Point a #:schema header at it and a TOML-aware editor autocompletes and validates as you type; the configuration reference is generated from the same document.
$ atlasd config schema | head -6
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Nexus Atlas config",
"type": "object",
"required": ["interface", "link"],
"properties": {
$ atlasd config schema > config.schema.json # then: #:schema ./config.schema.json
atlasd config node-tokenPrint the time-windowed mesh read token for the X-Atlas-Node-Token header — bare token to stdout, scope and validity to stderr, so it pipes cleanly into scripts. In a record fleet it mints the node-bound form instead (n1.…, signed with this node's signing_key), which reads as far as the record's dashboard flag allows.
$ atlasd config node-token
Scope GET /api/config, GET /api/stats — no writes, no session
Valid another 4m 12s (5-minute windows — mint again after that)
9y1uTq83KfWv2mDplRcxJ7hNbA5eZsG0
» Read a locked-down mesh member over the tunnel:
$ curl -H "X-Atlas-Node-Token: $(atlasd config node-token)" \
http://10.0.100.2:9800/api/stats
atlasd config keygen-author [--out path]Generate the Ed25519 author keypair that signs fleet configuration epochs (written mode 0600).
atlasd config sign-epoch --policy <file> --epoch <n> [--confirm-secs 90] [--target-roles a,b]Sign a policy TOML into a distributable config epoch offline, with optional role/node targeting (selectors intersect) and the commit-confirm window baked in.
atlasd config wizardOffline provisioning-bundle authoring shell. Binds loopback only by default — it deliberately has no auth of its own.
Node identity & fleet list
For a record fleet ([auth] provider = "fleet", see Identity and authorisation). The fleet subcommands author the list on the operator host and default to /etc/atlas/fleet-list.toml; every edit refuses to write a list that would not validate. fleet revoke, fleet push and peer evict remove nodes; fleet invite, fleet cert and fleet pending admit them (see admission modes). fleet add-node --sink and fleet set-caps --sink make a record a read-only member — it may subscribe and receive, never send data, relay or author; it gets no classes unless --classes names some, which fleet check then warns about — the record a feed gateway host runs with. fleet set-update-class, fleet rollout, fleet rotate and fleet set-lifeline drive pushes and rotations.
atlasd keygen --identityA whole node identity: the record UUID, an X25519 transport keypair and an Ed25519 signing keypair, printed as the node's [interface] lines, with the fleet add-node command for the operator on stderr.
$ atlasd keygen --identity
node identity generated (keep the private lines secret, file mode 0600)
# [interface] — this node
node_id = "af2e580d-5365-4b5f-acfa-9a9da1f69e73"
private_key = "…"
signing_key = "…"
# public halves — for the fleet list
public_key = "aC+J3tbTGW+7vBHMWMDbeCnjdsFxCxNS4W5gCmxAHWk="
signing_public_key = "2b2Z8FwiOSi2wJgh17Zp8cPK5Kg6q0/Am7usCaiSDTY="
On the operator host:
atlasd fleet add-node --name <name> --node-id af2e580d-5365-4b5f-acfa-9a9da1f69e73 \
--transport-key aC+J3tbTGW+7vBHMWMDbeCnjdsFxCxNS4W5gCmxAHWk= \
--signing-key 2b2Z8FwiOSi2wJgh17Zp8cPK5Kg6q0/Am7usCaiSDTY= \
--allowed-ip <tunnel-ip>/32
atlasd fleet init --fleet <id> [--file path] [--force]Start the authoring copy of a new fleet's list. The fleet id scopes each node's high-water mark.
atlasd fleet add-node --name n --node-id uuid --transport-key k --allowed-ip cidr [--signing-key k] [--role r] [--relay] [--classes a,b] [--config-author] [--dashboard none|own|fleet] [--sink]Add a record, least privilege unless the flags say otherwise. --transport-key, --signing-key, --allowed-ip and --role repeat. --sink makes a read-only member: it may subscribe and receive, never send data, relay or author, and gets no classes unless --classes names some (which fleet check then warns about).
$ atlasd fleet add-node --name sensor --node-id de8bae79-560d-43fb-b269-0e12b9c478a8 \
--transport-key lZJk7MeEDtZbjfDhy7L56+C9tncbO4P+7lUjpnUt7k0= \
--allowed-ip 10.0.9.3/32 --role sensor --dashboard none
record `sensor` added to /etc/atlas/fleet-list.toml (unsigned — run `atlasd fleet sign`)
atlasd fleet set-caps <name|uuid> [--relay bool] [--classes a,b] [--config-author bool] [--dashboard none|own|fleet] [--sink bool]Change a record's flags. The edit clears the signature until the next fleet sign; a change that would leave the list invalid writes nothing and exits 1. --sink true clears the classes unless --classes is given; --sink false restores the least set when none are left.
$ atlasd fleet set-caps sensor --classes Telemetry,Position
`sensor`: relay=false classes=[Telemetry,Position] config_author=false dashboard=none (unsigned — run `atlasd fleet sign`)
atlasd fleet set-interconnect <name|uuid> [--may-import a,b] [--may-export c] [--clear] [--file path]Set what a record may import and export as an Atlas Interconnect seam host, in its [node.ext.interconnect] section. --may-import lists the routes and mapped local addresses the node may announce from another network, --may-export this network's hosts it may expose; each is comma-separated, "" means none, and a list left out keeps its value. --clear removes the section: the node may import and export nothing. Write 0.0.0.0/0 for anything. The edit clears the signature until the next fleet sign; an empty list is warned about, and the first list whose records carry extensions gets a note, because nodes on release 3.0.0 or older cannot verify it and keep the list they hold.
$ atlasd fleet set-interconnect op-a --may-import 10.0.9.0/25,10.0.101.130/32 --may-export 10.0.101.0/24
`op-a`: may_import [10.0.9.0/25, 10.0.101.130/32] · may_export [10.0.101.0/24] (unsigned — run `atlasd fleet sign`)
note: records now carry extensions — a node on release 3.0.0 or older cannot verify this list and keeps the one
it holds; publish it once the fleet runs a build with record extensions
$ atlasd fleet sign
$ atlasd fleet push
atlasd fleet sign [--file path] [--key /etc/atlas/config-author.key] [--seq n]Bump the sequence number (or set it) and sign with a config-author key, the same key config keygen-author makes for epochs.
$ atlasd fleet sign
fleet `field-1` seq 2 signed by 3c24f045 (4 records, ffc955e8)
atlasd fleet show [--file path | -c config] [--json] [--revoked]Summarise a list file, or with -c the list a node config runs with (its bootstrap copy or a newer cached one). --json prints the GET /api/fleet shape; --revoked lists only the revocations. A record with an interconnect section shows an interconnect line (may_import [10.0.9.0/25] · may_export [10.0.101.0/24]), and extension keys this build does not know are listed as kept and signed as they are.
$ atlasd fleet show --file fleet-list.toml
fleet `field-1` · seq 2 · 4 records · signed ffc955e8
drone (e191..81b6) af2e580d-5365-4b5f-acfa-9a9da1f69e73
allowed_ips 10.0.9.2/32
roles uav
capabilities relay=true classes=[Control,Voice,Position,Telemetry,Video,Bulk] config_author=false dashboard=own
transport 6142ed49 valid
transport 5123339a valid
signing e5c003f3 valid
sensor (94b6..9806) de8bae79-560d-43fb-b269-0e12b9c478a8
allowed_ips 10.0.9.3/32
roles sensor
capabilities relay=false classes=[Telemetry,Position,Bulk] config_author=false dashboard=none
transport 115b28e5 valid
signing 8a10e10a valid
atlasd fleet verify [--file path]Verify the signature against the trust anchors in config-authors.toml; exit 1 on failure.
$ atlasd fleet verify
fleet `field-1` seq 1: signature OK (anchor `operator`)
atlasd fleet check [--file path] [--json]Validate the records and report the signature state. Errors exit 1: duplicate ids, names or keys, empty allowed_ips or classes, unknown class names, more than two keys of a kind valid at once, config_author without a signing key, more than 32 record extensions or a key over 32 characters, an interconnect section that does not parse. Warnings: an empty interconnect may_import or may_export ("this node may not act as a seam host"), overlapping allowed_ips, a record without a signing key, config_author on a record without the operator role, and a sink record that also names classes, config_author, relay or dashboard = "fleet" (each ignored at enforcement).
$ atlasd fleet check
fleet `field-1` seq 0: 4 records, 0 error(s), 0 warning(s), signature unsigned
$ atlasd fleet check --json
{"errors":[],"ok":true,"signature":"unsigned","warnings":[]}
atlasd fleet revoke <name|uuid|node id|key>… [--reason text] [--push config] [--push-relays] [--no-rotate] [--file path] [--key path]Remove records, or single keys given in base64, for good (see Revocation): list them as revoked, rotate the mesh secret to the remaining records, bump the sequence number and sign. --push hands the list to the daemon of that node config, which floods it; --push-relays sends the revoked transport keys to the relay registry with the staff token from $ATLAS_CONTROL_PLANE_TOKEN or --token-file. --no-rotate keeps the mesh secret, which leaves the removed node able to read gossip until the next rotation.
$ atlasd fleet revoke drone03 --reason "lost on sortie 12" --push /etc/atlas/config.toml --push-relays
removed `drone03` (5a1c..9e02) — id and keys revoked
mesh secret rotated (rot-1791801600-mesh_secret), sealed to 5 remaining record(s)
fleet `field-1` seq 8 signed by 3c24f045 (5 records, 9b0e7d21)
fleet `field-1` seq 8 handed to the atlas0 daemon — it floods it over its sessions
relay registry: 2 revoked key(s) for fleet `field-1` seq 8 (revoked_clients_seq 8)
atlasd fleet push [--file path] [-c config] [--relays] [--control-plane url] [--token-file path]Hand a signed list to the daemon running -c, which verifies it like a list from a peer, adopts it and floods it; and with --relays, send its revoked transport keys to the relay registry. An unsigned list is refused.
atlasd fleet show --revokedWhat the list has revoked, oldest first. A removed node is listed with its id and each key it held.
$ atlasd fleet show --revoked
revoked (4):
transport 7d0e44a1 of gs since 1791720000 (key copied to a laptop)
node drone03 5a1c..9e02 since 1791801600 (lost on sortie 12)
transport 2b9f61c0 of drone03 since 1791801600 (lost on sortie 12)
signing e07a3d55 of drone03 since 1791801600 (lost on sortie 12)
atlasd fleet invite --name n (--allowed-ip cidr | --pool cidr) [--classes …] [--relay] [--dashboard none|own|fleet] [--role r] [--ttl 15m] [--uses 1] [--region r] [-c config] [--json]Ask the running daemon to mint an invitation and print its v=2 pairing code on stdout (the summary goes to stderr). Unnamed flags are least privilege; a multi-use invitation with --pool gives each node the next free /32 and numbers the names. --list shows every invitation with its state and the nodes it admitted; --withdraw <id> voids one. Needs a record fleet. See Pairing code.
$ atlasd fleet invite --name drone07 --allowed-ip 10.1.0.17/32 --ttl 15m
invitation 7c41e09a2f5d4b8e9a3c11d07f62b5e4 for `drone07` — 1 use(s), expires in 15m
classes Telemetry,Position,Bulk · relay no · address 10.1.0.17/32
the code carries 1 anchor(s), 0 author(s), the address 10.1.0.17/32 and this node's address 10.1.0.1/24 — all under the token's MAC (202 characters)
atlas:pair?v=3&k=<this node's key>&n=drone07&a=<anchors>&i=10.1.0.17/32&h=10.1.0.1/24&t=<token>
atlasd fleet cert (--node name|uuid [--file list] | --name n --node-id uuid --transport-key pub [--signing-key pub] --allowed-ip cidr --fleet id) [--classes …] [--relay] [--dashboard …] [--psk-id id] [--expires 365d] [--key authority.key] --out F.certSign a record as a fleet certificate with the authority key (default /etc/atlas/config-author.key). Any node that trusts that key admits the certificate's holder with its flags and no list entry. Warns when the key is not an anchor on this host. See Fleet certificate.
$ atlasd fleet cert --node drone-c --file /etc/atlas/fleet-list.toml --expires 365d --out drone-c.cert
certificate for `drone-c` (5e0b..c4a1) in fleet `tenant-1` signed by 3c24f045 → drone-c.cert (812 bytes, expires 1823341500)
on the node: [auth] cert_file = "drone-c.cert"
atlasd fleet pending list [--json] | approve <id> (--allowed-ip cidr | --pool cidr) [--name n] [--classes …] [--relay] [--dashboard …] [--role r] | deny <id> [--block 1h] [--reason text] | unblock <id> [-c config]The approval queue of the running daemon ([auth] pending = true). approve mints the knocking key's record — signed into the next list when this node can sign, else kept here and forwarded to an author — and the node's next retry gets a session; deny blocks the key for --block or [auth] block_secs. list also shows records this node minted on their way to an author (queued `n` (via) — status (author `a`)) and, on an author with [auth] accept_forwarded = false, records other nodes forwarded (forwarded <id> … — awaiting approval), which approve <id> signs exactly as minted and deny <id> refuses. See The approval queue and forwarding.
$ atlasd fleet pending list
5d2e81a0 from 198.51.100.23:51820 "phone-07" 4× first 9s ago last 1s ago
$ atlasd fleet pending approve 5d2e81a0 --allowed-ip 10.1.0.70/32 --classes Position,Telemetry
approved as `phone-07` (9b1f..07c2), 10.1.0.70/32 — in fleet list seq 3
atlasd fleet pull -c config [--file path] [--with-queued]Copy the verified list a node runs with into the authoring file — after that node signed newer lists itself, from invitations, approvals or a dashboard removal — so the next edit builds on it. --with-queued also adds the records the node minted and still holds — a record an author refused, or one waiting for an author it cannot reach; they are unsigned until you run fleet sign and push. fleet revoke --cert F revokes a certified record that has no list entry.
atlasd fleet select-area --polygon area.geojson [-c config] [--json] [--revoke [--yes] [--reason text] [--no-rotate] [--file path] [--key path]]Resolve a GeoJSON polygon (Polygon, Feature or FeatureCollection, [lon, lat]) against the last known positions of the daemon running -c, and print the records inside with the age of each fix, the count outside and the records with no position. --revoke then removes exactly the listed records — never the node of -c — from the authoring file as fleet revoke does, signs, and hands the list to that daemon; it asks first unless --yes. The reason defaults to removed by area. See Remove nodes by area.
$ atlasd fleet select-area --polygon sofia.geojson -c /etc/atlas/config.toml
fleet `field-1` seq 7 · 3 inside · 2 outside · 1 without a position
inside n3 4c1e..a902 (42.69770, 23.32190) fix 1 s ago
inside n4 91b0..33fe (42.70120, 23.33810) fix 1 s ago
inside n5 07da..c4e1 (42.68840, 23.31570) fix 4 min ago (advert aged out)
no fix n2 e5a3..1b7c
atlasd fleet set-geofence <name|uuid> (--polygon f.geojson [--grace-secs 600] [--action isolate|zeroize] | --clear) [--file path]Set or remove a record's [node.geofence] in the authoring file. The list is left unsigned until fleet sign. Outside its fence for --grace-secs, the node isolates itself (reversible) or zeroizes. See Give a node a geofence.
$ atlasd fleet set-geofence n1 --polygon burgas.geojson --grace-secs 300 --action isolate
`n1`: fence of 4 points, isolate after 300 s outside (unsigned — run `atlasd fleet sign`)
atlasd fleet zeroize <name|uuid|node id> [--not-before unix | --delay-secs N] [--no-revoke] [--no-rotate] [--reason text] [--cancel] [--push config] [--file path] [--key path]Sign a remote zeroize command for one node into the authoring file and sign the list. By default the same list also revokes the node, with a mesh-secret rotation; --no-revoke keeps its record. --not-before or --delay-secs holds the command; --cancel drops the node's pending command; --push hands the list to that node config's daemon, otherwise push it with fleet push. A revoked node can still be named by name or UUID. See Wipe a node remotely.
$ atlasd fleet zeroize n2 --delay-secs 600 --push /etc/atlas/config.toml
zeroize `n2` (e5a3..1b7c) not before 1791802200 (in 600 s)
revoked `n2` (e5a3..1b7c) in the same list — id and keys, it can never rejoin
mesh secret rotated (rot-1791801600-mesh_secret), sealed to 2 remaining record(s)
fleet `field-1` seq 9 signed by 3c24f045 (2 records, 1 command(s), 4f7a2c10)
$ atlasd fleet zeroize n4 --no-revoke
zeroize `n4` (9b02..77de)
not revoked (--no-revoke): `n4` stays a record
fleet `field-1` seq 10 signed by 3c24f045 (2 records, 2 command(s), 8c31e0f5)
$ atlasd fleet zeroize n4 --cancel
dropped 1 command(s) for `n4`
atlasd peer evict <name|uuid|node id|key id|key|peer id> [--reason text] [-c config]Ask the running daemon to tear one peer's sessions down now. It is a reset: a peer that still has a record reconnects; revocation is what keeps it out. Exits 1 when no peer matches or the daemon does not answer within 5 s.
$ atlasd peer evict relay --reason "stale endpoint"
evicted peer 3 (c41f..07ad)
atlasd identity show [-c path] [--json]This node's identity as the daemon would resolve it at start: node id and UUID, record name, flags, each key with its validity and whether this node holds it, and the fleet list's sequence number.
$ atlasd identity show
interface atlas0
mode record fleet
node id e191..81b6 (af2e580d-5365-4b5f-acfa-9a9da1f69e73)
record drone
capabilities relay=true classes=[Control,Voice,Position,Telemetry,Video,Bulk] config_author=false dashboard=own
transport 6142ed49 valid · held here
transport 5123339a valid · held here
signing e5c003f3 valid · held here
fleet list `field-1` seq 2
atlasd fleet set-update-class <name|uuid|node id> required|best-effort|left-behind [--pinned] [--file path]Set a record's update class for fleet pushes in the authoring list — unsigned until atlasd fleet sign, then pushed. required gates a release and aborts it when silent or failed; best-effort is tracked, never awaited; left-behind is outside targeting and both gates, and takes the newest epoch after [config_mgmt] left_behind_grace_secs unless --pinned. See Push a release the fleet cannot half-take.
$ atlasd fleet set-update-class relay-van required
`relay-van`: update class required (unsigned — run `atlasd fleet sign`, then push)
$ atlasd fleet set-update-class test-bench left-behind --pinned
`test-bench`: update class left_behind, pinned (unsigned — run `atlasd fleet sign`, then push)
$ atlasd fleet sign
fleet `field-1` seq 12 signed by 3c24f045 (6 records, 5be2a1c0)
atlasd fleet rollout status [-c config] [--json] · release [--force] · abort [--reason text]The staged rollout this node drives. status prints both gates — the canary gate and the release gate with its required, confirmed, silent and failed counts, the deadline and an abort cause when there is one — and every node's class and state. release signs phase 2 (--force past an unmet canary gate); abort signs the pre-rollout policy forward, to the canary set or, once released, to everyone. The web API's /api/config/rollout/* does the same.
$ atlasd fleet rollout status -c /etc/atlas/config.toml
rollout r-1791900000-9f3a1c2e · phase aborted · canary epoch 13
canary gate: 1 of 1 canaries applied and confirmed
aborted by: relay-van (4f02..c8d1) silent (release phase)
release gate (epoch 14): required node relay-van (4f02..c8d1) did not confirm by the deadline for the released epoch 14 — the rollout aborts
gs1 9b1e..40aa required applied epoch 14 confirmed
relay-van 4f02..c8d1 required unknown no epoch SILENT
drone-a d1a0..7c21 best_effort applied epoch 14 confirmed
test-bench e77a..1b06 left_behind* left_behind epoch N-1 held
(* pinned: never takes a new epoch)
atlasd fleet rotate plan --kind mesh-secret|node-transport|node-signing[,…] [--subject node] [--next-key b64] [--next-signing-key b64] [--publish-in secs] [--activate-after secs] [-c config] [--push config] · status [-c config] [--json] · activate <id> · retire <id> [-c config] [--force] [--reason text] [--at unix] · cancel <id>Rotations on the three-step schedule. plan signs a schedule into the list: the mesh secret is minted and sealed to every record, a node key names the subject and its next public key (--next-key for a transport key, --next-signing-key for a signing key); publish is now unless deferred with --publish-in, activate follows after [rotation] default_publish_to_activate_secs unless --activate-after sets it. activate, retire and cancel take --push too, and every step defaults to --file /etc/atlas/fleet-list.toml and the author key. status prints every rotation, each node's reported state, the retire gate and the nodes still on old material. activate brings activation forward to now. retire signs the retire step and is refused until every required node, and a node rotation's subject, reports active in the gossiped view of -c (--force is recorded on the node whose view was overridden). cancel withdraws a rotation that has not activated. See Rotate keys and the mesh secret without stranding anyone.
$ atlasd fleet rotate plan --kind mesh-secret --push /etc/atlas/config.toml
rot-1791900000-mesh_secret: new mesh secret sealed to 6 of 6 record(s); published 1791900000, activates 1791903600
fleet `field-1` seq 14 signed by 3c24f045 (5be2a1c0)
fleet `field-1` seq 14 handed to the atlas0 daemon — it floods it over its sessions
$ atlasd fleet rotate retire rot-1791900000-mesh_secret -c /etc/atlas/config.toml
error: retire waits for 1: relay-van — wait for them, or pass --force
atlasd fleet set-lifeline <name|uuid|node id> [--off] [--file path]Flag a record as a lifeline node (a bootstrap peer) in the authoring list, unsigned until atlasd fleet sign: after each retire it keeps accepting the retired key or secret for [rotation] lifeline_secs, so a straggler still finds a node that speaks its material. --off clears the flag.
Dashboard accounts & tokens
atlasd web adduser|passwd|deluser|list-usersDashboard account management — argon2id at rest, sessions as signed cookies. Create accounts before exposing :9800 beyond localhost.
atlasd web remove-passkeyThe break-glass path when a hardware security key is lost — removes a passkey from an account so password sign-in works again.
atlasd web token add ci --scope read|write [--expires 30d]Mint an API token for automation; the secret is printed exactly once. token list and token revoke manage the set; scopes are documented in the API reference.
$ atlasd web token add ci --scope read --expires 30d
atlas_kQ3nX8vLw2Jm7RfT5cYp0dHb4gZs9uEaIo6WqBNVkPr
$ atlasd web token list
ci atlas_kQ3n read created_at=1786295400 by=admin expires=1788887400 last_used=never
Complete footage
For classes with retain = true (see complete footage by backfill). Both commands read -c for the interface and the [qos.retain] paths. A clear goes to the running daemon, which executes it itself, or straight to disk when none runs.
atlasd retain status [--json] | clear [--class C] [--dest ip] | export --class C --dest ip [--stream hex] [--out f]The sender's journal: retained classes, size against max_bytes, whether it is sealed at rest, backfill served, one line per stream. clear empties it at the end of a flight; export writes the sender's copy of a stream in the capture export format, for comparison with the receiver's.
$ atlasd retain status
retained classes: Video
journal: 226.3 MiB of 2048.0 MiB in 4 segment(s) under /var/lib/atlas/atlas0.retain (sealed at rest)
journaled 187500 · dropped 0 · requests 41 · backfill queued 12972 sent 12972
Video → 10.0.0.1 stream 3d4c 187500 packets seq 0..187499 226.3 MiB
atlasd capture status [--json] | export <peer> <class> [--stream hex] [--out f] | clear [--class C] [--peer ip]The receiver's archive: completeness per origin, class and stream, with missing and unrecoverable counts. export writes a stream in sequence order with its gaps annotated (.atlcap, the input of tools/atlas-capture); without --stream, every stream of that origin and class. The dashboard's Export button calls POST /api/capture/export with {"peer", "class", "stream"}, up to 256 MiB.
$ atlasd capture status
captures: 226.3 MiB of 2048.0 MiB under /var/lib/atlas/atlas0.capture
requests sent 41 · answers 41 · backfill received 12972 · duplicates 0
10.0.0.2 Video stream 3d4c 100.00 % 187500 of 187500 missing 0 unrecoverable 0
$ atlasd capture export 10.0.0.2 Video --out sortie.atlcap
stream 3d4c: 187500 packets, 0 missing, 0 unrecoverable → sortie.atlcap
Diagnostics & support
atlasd --version | -VOne line on stdout, for scripts and bug reports: the release, + the git short hash of the build it was made from, then every contract number this binary speaks (Versioning says what each one covers). A build made outside a git checkout reads +unknown; packaging may set the hash through ATLAS_BUILD. atlasd --help and the atlasd run banner show the same release as v3.0.0+7c341a4 with the contract row under it, and atlasd status shows the release. The wire number is the one that decides whether two nodes form one fleet.
$ atlasd --version
atlasd 3.0.0+7c341a4 · wire 5 · relay 2 · seal 2 · pairing 3 · adapter 1 · report 2 · api 1
$ atlas-config --version
atlas-config 3.0.0+7c341a4
$ nexus-atlas-relay --version
nexus-atlas-relay 3.0.0+7c341a4 · wire 5, 4 · relay 2
atlasd support-bundle -i nexus0 [-o file.zip] [--no-crashes]One redacted zip: config (secrets stripped by allowlist), stats, health, journal tail, scheduler log, netcheck, QoS state, versions, crash spool. It prints every redaction it performed — private keys cannot leave by accident.
atlasd crash list|show|export|purge [<id>]The local crash spool — capture is on by default, and reports stay on the node until an operator acts. IDs match by unique prefix; export writes a signed zip for manual handling.
atlasd crash send <id> [--anonymous|--attributed]Explicit, per-report upload to the console. Anonymous mode strips identity and forces redaction; background auto-send exists but is off by default.
atlasd enroll <code>Enroll this node into a hosted console account, with proof-of-possession of the node key. The only way a node ever becomes console-connected.
Patterns worth stealing
# CI gate: fail the pipeline when a config would not load
atlasd config check -c deploy/node-a.toml --json | jq -e '.ok'
# Yesterday's link flaps, machine-readable
atlasd journal -c link -s warn --since 24h --json
# Watch a failover as it happens
atlasd monitor -i nexus0 -r 250
# Print the schema your editor should validate against
atlasd config schema > config.schema.json