-
Notifications
You must be signed in to change notification settings - Fork 0
Machines on the board
Everything on a tile is one glance's worth, ordered by how likely it is to be the reason you looked:
| Which one wants you | The accent bar down the left edge, and that machine sorts to the top. It is the only thing that gets that bar — a machine's own colour never touches it. |
| Sessions | One chip each, with the window count. Green means it is asking you something; amber means it finished. Click one and you are in that terminal. |
| Load, and the fullest disk | Amber over 74%, red over 90%. Only the disk in the most trouble: a board wants to know there is a problem, not to inventory the filesystems. |
| Two uptimes | The machine's, and how long this Argus has been running. Three Argus instances on one box report the same machine uptime; the second number is the one that tells them apart. |
| Its address, and a button to copy it | Because the useful thing is often not "open it here" but the address itself, to paste into a terminal or send to somebody. |
| A line of your own | A note you write, kept per machine: what the box is for, what it was doing, why it looks like that. Everything else on the tile, the machine said. This is the part only you know. |
The footer counts what is actually there — 4 argus on 2 machines, when three of them are on
one box.
A session chip carries the agent's name when the session says so — argus [claude] — with
the model in its tooltip. Both come from what the agent declared on its own pane
(@argus_agent, @argus_model, written by the status line hook Argus can install for you),
and neither is ever inferred: a board has no process tree to read and no business running
ps on another machine, so a tile that guessed would be a tile that is occasionally wrong
about a box you cannot see. A session that says nothing shows nothing.
It costs one list-panes per machine per sweep, so forty sessions cost what two do. The
model is in the tooltip rather than on the chip because a tile with six sessions would
otherwise carry six model names, and the question a board answers is which machine needs
me.
Two directions, and the network decides which one you can have.
Write the machine down and the board polls it. This is the better arrangement wherever it works: a request that fails is the signal that a machine is down, and there is one file that says what is being watched.
# ~/.config/panoptes/config.yaml
listen: 0.0.0.0:8070
token: <the board's own token, generated on first run>
machines:
- name: hetzner
url: http://hetzner.internal:8090
token: <a watcher token from that machine's Argus>
# Where a *browser* should go, when that is not where this board asks.
reach: http://hetzner.example.com:8090
colour: 4 # optional; otherwise from the name
note: the one paying rent # optional; a reader can write over itOn the Argus side, a watcher token is a key that opens GET /api/overview and nothing
else — no shell, no files, no writes, no proxy:
# ~/.config/argus/config.yaml, on each machine
watchers:
- name: panoptes
token: <16+ characters, not the same as the main token>Some networks only go one way. Measured on the pair this was written for: two boxes on the same wire, same /25, each with the other's MAC in its ARP table, and one of them refusing everything inbound. A board on the reachable side will never poll the other, and no amount of configuration on the board changes that.
So the machine opens the connection instead, in the direction that already works:
# panoptes config: allow it
registration_token: <16+ characters, different from the board's token>
forget_after: 45 # seconds of silence before it stops being believed# argus config, on the machine that cannot be reached
report_to:
url: http://board.internal:8070
token: <the registration token>
name: gpu2 # what you want it called on the board
reach: http://gpu2.internal:8090 # where a browser should go
every: 10What it sends is what GET /api/overview returns and nothing else: hostname, uptime, load,
memory, the fullest disk, and the session names with which of them is ringing. No file, no
path, no token, no command. Off unless configured.
This is not a workaround anybody invented here — it is what Prometheus does in agent mode, and what every dial-out agent does: Tailscale, Cloudflare Tunnel, Teleport, the kubelet registering with its API server. Local pull, remote push.
Three rules keep it honest:
- Announcing and looking are different keys. The registration token cannot read the board; the board's token cannot invent machines.
- The list you wrote by hand wins. A machine announcing a name you have configured is refused, so nothing holding the registration key can quietly replace a real machine with one of its own.
-
Silence is the only signal there is. No request fails when nobody is asking, so a
machine that stops calling in goes cold after
forget_afterrather than staying green for ever.