Running a broker
A network that needs no server still needs a place for two frogs to find each other across the internet. That is what a broker is. It holds no authority over your network, and a blank one refills itself from the nodes on their next check-in. But be clear about what it carries: on one site a pond is complete without it — while in internet mode the broker is the only thing linking your remote sites, and if you lose it you lose everything on the far side of it, the whole remote LAN. It is the one piece with a public address \u2014 though a WireGuard address, silent to anyone without the right key: a scanner sweeping the internet gets no answer, and only peers that already hold credentials can reach it at all. It is the one piece to build to last.
Same software, same one line of config on the node, same tunnel machinery — but a broker does one of two different jobs, and which one you're doing sets the whole deployment.
Across the internet
Nodes sit behind home routers, phone tethers, office NAT — no stable address, no inbound path. The broker needs a publicly-routable IP and, in practice, a DNS name in front of it. A small VPS is the whole requirement: a fixed public IP, a name, a few dollars a month.
On one site
On a campus, a warehouse, or a ship, every node already reaches every other — the broker isn't there to make anything reachable. It's there to lay shortcuts, so traffic across a big site stops threading ten boxes to get across the room.
This isn't a diagram of an ideal. It's how the FrogNet development network is actually wired today: two self-complete LANs, each behind a .1 gateway, meeting across the internet only through a WireGuard-silent broker — and the single path between the outside world and the fabric is the air-gapped file drop. Reference and deployment are the same picture.
.1 gateway and runs with no broker at all. The broker only joins the two across the internet — a WireGuard address that answers no stranger — and the one way anything moves between the outside world and the fabric is the air-gapped drop: a file, checked against a list of the operations allowed to exist.Clean machine or upgrade — it asks only for what it can't work out: the public name clients will use, the API port (default 18257), the WireGuard port range, the first pond's name and address plan, the operator console password, and an admin token (or it generates one). Two constants aren't negotiable, and it refuses you if you fight them: a node base always ends in .1 (because .1 is always FrogNetHost in any subnet), and the pond lives inside 10.0.0.0/8 clear of the transit and chorus ranges.
That last line is the only proof the install worked, and it's worth reading rather than glancing at. The postflight doesn't ask the services whether they're happy — it tries things and reports what happened. It sends a real request through the real front door. It tries, as the web user, to read the admin token and the private config, and fails the install if either succeeds. It calls an admin route with no credential and requires a refusal, then with one and requires an answer. A green line means those things were tried, not assumed.
The broker service opens and manages its own port, terminates its own encryption, and is what your tunnels attach to — nodes talk to it directly, and no web server sits in front of it. The web tier on port 80 is the operator console (and, if this machine also serves your site, the site's pages). A person opens those. No node ever does. The web tier is the one that faces strangers with a browser — so it's built with a wall down the middle of it.
An HTTP control plane with an air gap behind the web tier isn't a reluctant compromise — it's the recommended architecture, and here it's simply what the software does. Co-location is safe when the only thing crossing between the two is a file in a directory, checked against a list of the operations permitted to exist. The attack surface remains zero.
The same posture, in full — the security architecture →
Picture a sprawling site — a manufacturing floor, a campus, a ship. Every node reaches every other; the network forms perfectly well on its own. But the only physical route from the far end to the office runs through every box in between. Ten hops, each adding delay and one more thing that can fail. Nothing is broken. It's just long. Point pond.conf at a broker on the LAN, put the two distant nodes in one chorus, and it mints a tunnel between them — the tunnel doesn't make them reachable, it makes them adjacent.
Nothing else has to be told about this, and that's what makes it safe on a site already running. Discovery measures a tunnelled path exactly the way it measures a wired one, and the shorter round trip wins on its own merits. The chain doesn't disappear — it drops to a fallback and takes over unchanged the moment the tunnel stops answering. You're not overriding anything; you're handing the network a better option and letting it choose. Two cautions: a shortcut that isn't shorter won't be used (measure the long path first), and the tunnel rides the same wire as everything else — it fixes distance, not bandwidth.
One command talks to the broker, and it goes through the same front door every node uses — there's no private back channel for the operator, deliberately. If the gate is broken you find out with your first command, instead of having a side entrance that hides the outage.
Four operations, in order of how much they destroy. Each takes a real consistent backup first — through the database's own backup interface, never by copying the file. The rule underneath all four is the only thing worth memorising: kernel state comes down before records go away. Every one tears the tunnels down the same way the broker retires a single tunnel — interfaces deleted, port forwards removed, namespaces released — and only then deletes anything. Skip that and you leave interfaces and held ports with nothing naming them, and the next install allocates around ghosts.
Each destructive one makes you type an exact phrase — DESTROY ALL TUNNELS, CLEAR ALL NODES, RESET THE DATABASE. That isn't ceremony: these are reachable from a web front door, and the difference between an operation a stray retry can trigger and one it can't is a required string the retry doesn't carry. And db reset is a recoverable operation rather than a catastrophe — the nodes hold the truth, and they'll tell it to a blank broker the next time they check in.
Own the rendezvous too
On one site a pond needs no broker at all. Across the internet it is the only connection between your remote machines — lose it and the LAN on the far side goes with it. So put the internet-facing one on a machine you build to last, and run a second on a big LAN only to straighten a long path.