Connection Establishment
Three stages: TLS, identification handshake, registration. A connection that fails any of them is dropped without a session.
Stage 0 — TLS
Section titled “Stage 0 — TLS”The tunnel listener is TLS 1.3 unless the server runs with tunnel_insecure, in which case agents must connect with -insecure. There is no negotiation and no fallback: an agent expecting the other transport is dropped here.
Agents verify the server against the system root store, or against the SPKI pins in their config file.
Stage 1 — Identification handshake
Section titled “Stage 1 — Identification handshake”Both peers send one newline-terminated JSON object. The server allows 5 seconds.
{"id":"woho-client","version":"261002"}{"id":"woho-server","version":"261002"}Dropped on invalid JSON, an unexpected id, an oversized line, or timeout.
Stage 2 — Registration
Section titled “Stage 2 — Registration”The agent sends a length-prefixed register message (4-byte big-endian length + JSON).
{ "type": "register", "payload": { "client_uuid": "550e8400-e29b-41d4-a716-446655440000", "client_name": "web-prod-01", "hostname": "web-prod-01", "os": "linux", "arch": "amd64", "client_version": "261002", "auth_key": "XXXX-XXXX-XXXX" }}| Field | Rule |
|---|---|
client_uuid | A well-formed UUID, kept across reconnects |
client_name, hostname | At most 128 bytes |
os, arch, client_version | At most 32 bytes |
auth_key | XXXX-XXXX-XXXX; omitted when the agent has none |
A violation is a rejection, not a truncation. The key is then checked — see Connection scenarios. A refused or invalid registration is recorded on the machine’s timeline and in History, with the address and the identity it claimed.
sequenceDiagram
participant C as Agent
participant S as Server
C->>S: TCP connect, TLS
C->>S: {"id":"woho-client","version":"…"}
S-->>C: {"id":"woho-server","version":"…"}
C->>S: register { client_uuid, client_name, auth_key, … }
alt accepted
S-->>C: registered
Note over S: Machine online in the panel
else refused
S-->>C: AUTH_FAILED / AUTH_REQUIRED
Note over S: Recorded on the timeline
end
After registration
Section titled “After registration”Heartbeats every 30 s; the server drops a connection it has not heard from in 120 s. Stats every 10 s. Agent-reported facts (distribution, kernel, addresses, CPU, memory, mounts) arrive with registration and the stats.
Why a session ended is kept with it: agent closed, read timeout, replaced by a new connection (the same client ID registered again), key revoked, closed by admin, server shutdown. The agent reconnects with backoff — 1, 2, 5, 10, 30, then 60 s — and gets a new session.
Pending connection limits
Section titled “Pending connection limits”A connection occupies a slot from accept until registration succeeds: 256 server-wide and 32 per source address by default. A registered agent holds no slot. A refused connection is closed at once and the agent retries with its normal backoff. See Tunnel connection caps.