Backroom Relay

wss://backroom.jck.xyz/ws

A dumb pipe,
on purpose.

Backroom Relay is a WebSocket rendezvous point for devices that encrypt end to end. Two peers behind NAT dial out, meet in a room named by a secret only they hold, and every frame is forwarded byte for byte. The relay holds no keys, reads nothing, and stores nothing.

Read the docs Client contract ● one static binary, one WebSocket dependency
iOS companion dials out macOS app dials out backroom-relay sees room id, sizes, timing · never keys or plaintext a6 09 f2 3c … sealed frames sealed frames … 4e d1 8b 77
01

Two devices, neither reachable

The relay was built for Backroom, a macOS agent app with an iOS companion. The phone needs to reach the Mac from anywhere, and the Mac sits behind NAT where nothing can dial it. So both ends connect out to this relay, present the same room id, and the relay pipes frames between them.

Nothing about it is Backroom-specific. Any two endpoints that already share a secret can derive a room id from it, seal their traffic end to end, and use the relay as a meeting point. It is a generic pipe, and it is documented as one.

02

Confidentiality is not the relay's job

The relay is structurally unable to read traffic, not merely promising not to. There is no key material anywhere in the codebase, and no code path that parses, transforms, or logs a frame's payload. The access model has two parts, both deliberate:

  • End-to-end encryption on the endpoints provides confidentiality and integrity. Every byte crossing the relay is ciphertext sealed under a key derived from an offline pairing.
  • The room id is an unguessable capability. It is a high-entropy secret the two devices already share. The relay admits at most two connections per room, so even a party who somehow learns a room id cannot join an established pair.

There is no relay-side auth secret, and that is a decision, not an omission: a shared relay secret would have to be distributed to every client, which is strictly worse than a per-pair capability. The full security model spells out the threat model and what each class of attacker actually gets.

03

Stated plainly, because "end to end" is often read as "invisible"

The relay can see

  • The room id and therefore that a pair is talking. Logged only as a six-character prefix, never in full.
  • Frame sizes and timing the shape of the traffic, not its content.
  • The source IP of both ends used for per-IP rate limiting and nothing else.

The relay can never see

  • Keys no key material exists anywhere in the relay codebase.
  • Plaintext method, path, body: all sealed before they reach the wire.
  • History nothing is persisted. State is an in-memory map that dies with the process.

No amount of relay compromise turns into commanding the Mac: a forged frame does not decrypt, and is dropped before anything acts on it.

04

Built to refuse features

No database. No persistence. No accounts. No auth server. No message history. No rooms-list endpoint. No admin API. State is an in-memory map of room id to its at-most-two peers, and nothing survives a restart. That is correct behaviour: a dropped connection just reconnects.

Every one of these omissions is load-bearing for the dumb-pipe security model. A relay that could list rooms or replay history would be a relay worth compromising.

05

The entire HTTP surface

EndpointPurpose
GET /ws?room=<id> The one WebSocket endpoint. Binary frames are forwarded verbatim to the other peer in the room; text frames from the relay signal presence.
GET /healthz Liveness probe. Returns 200 ok plus an X-Relay-Rev header naming the deployed commit. Reveals nothing about rooms or traffic.

That is all of it. There is deliberately no endpoint that enumerates rooms or peers. The client contract covers every response, close code, and control frame a client can encounter.