On this page
Beacon
How does the fleet know a host is alive without asking it? Each host publishes a small health document on a timer; every liveness verdict in Stado is a read of that document's contents and age, never an ssh probe.
What it is
A beacon is one JSON document per host: the host's own slug, a reported_at
timestamp, a disk line, and a units{} map with one entry per declared unit,
each carrying its state (deploy/host_health_beacon_macos.sh). The unit
list is not fixed in the script — "the labels this host is judged on are the
ones the registry declares for it", matched by target name or declared
hostname with the .local suffix dropped. For each label the writer asks
launchd in both the GUI and system domains, and a live process outranks
history: the previous run's exit code is read only when nothing is running
now.
The fleet's beacons are published on a one-minute timer
(stado-rs/src/monitor/host_silence/mod.rs).
Who declares it
The host itself. Linux and macOS writers collect local disk and service
state, then call stado host publish-beacon FILE — an authenticated PUT
through the scoped host-health API, requiring STADO_HOST_HEALTH_API_URL
plus the dedicated stado-host-health-beacon Skarbiec grant. Missing
routing, an unreadable or over-broad grant, an insecure non-loopback HTTP
URL, failed authorization, and backend errors all leave the prior beacon
untouched and return failure; there is no cloud CLI, provider SDK, direct
bucket URL, ambient credential, or cross-backend fallback in the writer
(operations).
The relay
A machine with no stado binary can still collect its own beacon, but it
cannot hand it in — and one published by hand goes stale within the hour,
which is worse than none because it still looks like reporting. So a host
that has the binary and the grant relays: on every tick it already runs, it
collects over the approved channel and publishes on the silent host's behalf
(deploy/host_health_beacon_macos.sh). The relay speaks only for hosts
nobody is reporting: it asks the store which beacons are stale and skips any
host fresh within the relay window, because an earlier relay carrying an
older unit list overwrote a correct document with a thinner one, and a
just-installed service read as missing for as long as the relay kept winning.
Who observes it
stado host health <target>, stado registry beacon-age, stado registry doctor, and the read side of the service layer: stado service list joins
the declared managed set against the latest beacons and issues no ssh at all,
because the moment you most need to ask "what is supposed to be running here"
is the moment the host has stopped answering
(stado-rs/src/deploy/service/model/managed/status.rs). The autonomy
cycle's service reconciliation reads the same documents
(operations).
Readers resolve a target to its beacon object through the slug
rule in monitor/host_health.rs — target name, declared hostnames, and their
first dot-labels, in order.
Where it lives in the store
host_health/<slug>.json, inside the deployment's namespace — the latest
document only, one per host (monitor/host_health.rs). Because the prefix
holds only the latest document, a gap closes over itself the moment the host
comes back; the durable record of the gap is the silence record,
state/host_silence/<host>/<started_at>.json, opened when the newest beacon
crosses the threshold and closed by the first fresher beacon
(monitor/host_silence/transitions.rs).
Silence, and what stale means
A host counts as silent when its newest beacon is older than the fleet-wide
threshold: STADO_SILENCE_THRESHOLD_SECONDS, default 300 seconds — five
minutes, because at a one-minute publication interval three consecutive
misses is a host that has stopped talking and one miss is a slow pmset
call. A value that is not a positive integer falls back to the default rather
than disabling the detector (monitor/host_silence/transitions.rs). No
beacon at all is silent — a host that has never published is not a host that
is fine. A beacon stamped in the future is not silent: clock skew on the
publisher is not an outage.
A stale beacon cannot describe the present, so nothing derives a confident
verdict from it. A unit read through a stale beacon is unknown, never
active and never missing (deploy/service/model/managed/status.rs;
operations: "a stale beacon is unknown, never
missing"), and staleness never authorizes a host mutation, with the single
beacon-unit exception operations documents. Unit states a
fresh beacon can report: active, inactive, failed; missing means the
beacon exists and does not carry the unit; unknown means no beacon or an
empty state (deploy/service/model/vocabulary.rs).
Commands that act on it
stado host publish-beacon <file-or-dash>
stado host health <target>
stado registry beacon-age
stado host ping <target>
stado host link <target>
host link answers "why did this host go quiet": beacon age, recorded
silences, and the reader refusals filed against it. Full flags in the
cli reference.
Not to be confused with
- A probe. A beacon travels outward from the host; nothing dials in.
Endpoint reachability is a separate observation (
stado service verify). - A silence record. The beacon is the latest state; the silence record is the durable history of its gaps (observation).
- The registry. The registry declares which units the host is judged on; the beacon reports what launchd or systemd actually says about them.
Source: this website