20260816 - Add retina-telemetry to the node stack - #30
Merged
Conversation
The node-side telemetry uplink, pinned like every other image via
${TELEMETRY_V:-v0.1.0}. One container per node, owning everything sent to
api.retina.fm: registration, detection streaming, heartbeat and config sync.
Three things about this service differ from the rest of the file, and all three
are deliberate.
No depends_on. Every other service waits on config-merger. This one must keep
reporting while the rest of the stack is crash-looping — that is the entire
point of it — so gating it would leave it dead exactly when its telemetry
matters most. It re-reads its inputs on every cycle, so configuration that
appears later is picked up with no restart and no ordering constraint.
No docker socket. blah2 and ADS-B liveness are derived from the detection poll
instead, which distinguishes "down" from "wedged" where container state cannot,
and the versions in the heartbeat come from the image-tag env vars passed here.
network_mode: host, to reach blah2_api on 127.0.0.1:3000. It binds no listening
ports of its own; every input is a poll or a file read, and there is no inbound
path to it at all.
Of its four mounts only /data/retina-telemetry is writable. It holds the bearer
token at 0600 and the status document at 0644, and lives under /data so the
token survives an OS update — losing it means re-registering, which needs an
operator to reactivate the node, because the server answers every registration
refusal with the same opaque 403.
DISK_PATH is set to /data/mender rather than left at its default of /data,
which is not mounted here — only its subdirectories are. Without it statvfs
would measure the container's own overlay and report a plausible, wrong
disk_free_mb.
Requires retina-gui >= v0.7.0, the first version that persists the three
consent records. Without them the service refuses to register, deliberately and
by design: a missing record means the owner was never shown that text, and
nothing is ever synthesised. owl-os#51 moves that pin.
Not tagged — this lands ahead of cutting a release.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The node-side telemetry uplink, pinned like every other image via
${TELEMETRY_V:-v0.1.0}. One container per node, owning everything sent toapi.retina.fm: registration, detection streaming, heartbeat and config sync.Three things differ from every other service here
No
depends_on. Everything else waits onconfig-merger. This one must keep reporting while the rest of the stack is crash-looping — that is the entire point of it — so gating it would leave it dead exactly when its telemetry matters most. It re-reads its inputs each cycle, so config appearing later needs no restart and no ordering constraint.No docker socket. blah2 and ADS-B liveness are derived from the detection poll, which distinguishes down from wedged where container state cannot. Versions come from the image-tag env vars.
network_mode: host, to reachblah2_apion127.0.0.1:3000. It binds no listening ports; every input is a poll or a file read, and there is no inbound path to it at all.Mounts
Of four, only
/data/retina-telemetryis writable — bearer token at 0600, status document at 0644, under/dataso the token survives an OS update. Losing it means re-registering, which needs an operator to reactivate the node, because the server answers every registration refusal with the same opaque403.DISK_PATH=/data/menderrather than the default/data, which is not mounted here — only its subdirectories are. Without itstatvfsmeasures the container's own overlay and reports a plausible, wrongdisk_free_mb.Requires retina-gui >= v0.7.0
The first version that persists the three consent records. Without them this service refuses to register — deliberately: a missing record means the owner was never shown that text, and nothing is ever synthesised. offworldlabs/owl-os#51 moves that pin.
Verified
docker compose configvalid against real docker on a node;${TELEMETRY_V:-v0.1.0}resolves tov0.1.0ret824685c9andret3773656dboth registered, streamed, and held config version 1Not tagged
Deliberate. This lands ahead of cutting a release; tagging is a separate decision.
🤖 Generated with Claude Code