Skip to content

Agent (edge-agent, ea)

One static Go binary per router CPU, started by procd (/etc/init.d/edge-agent, link shipped in the image). Source: edge/agent.

Loop

Every poll (1 min, 5 s while a change waits for confirmation, sooner when the control plane pushes):

  1. Roll back a change that was never confirmed (also right after a restart).
  2. GetDesiredState. Success confirms a pending change.
  3. Converge: a new version is rendered to uci lines and applied through the guard. A version that failed or was rolled back is not retried until the control plane sends a new one.
  4. Maintain: put VXLAN back into its bridge if it fell out; home re-discovers its endpoints every 10 min (renews leases); travel re-dials a path whose last handshake is older than 3 min.
  5. ReportState: key, endpoints, active endpoint, last handshake, apply status. Success confirms a change applied in this sync.

Alongside: the path watcher (probe each path every 2 s, fail over after 2 misses, move back after 3 good probes) and the realtime client (WebSocket, heartbeat every 30 s, reconnect with backoff, "state changed" and debug commands).

Packages

Package Role
internal/netconfig Facts (stock uplink, LAN bridge), render uci lines, bridge repair
internal/guard Snapshot network, firewall, dhcp; apply; confirm or roll back; deadline on flash
internal/ladder Home endpoint discovery (IPv6 pinhole, UPnP mapping); travel dialer (wg set live, proof = ping reply through the path)
internal/pathwatch Route VXLAN over a healthy path
internal/realtime WebSocket client, debug command execution (timeout, 64 KB cap)
internal/wireguard Key on first start (crypto/ecdh X25519); private key never leaves the router
internal/identity, internal/fsutil Atomic writes (temp + fsync + rename)
internal/doctor ea doctor checks

CLI

Command
ea serve The daemon
ea status Identity, role, config version, last sync, apply status, endpoints, paths, path in use
ea sync Ask the daemon to sync now (SIGUSR1) and wait for the result
ea enroll Enroll again; a running daemon switches to the new identity
ea doctor Enroll code, identity, DNS, HTTPS (clock hint), token; exit 1 on failure
ea version

All take --json. Files: /etc/jumo/agent.json (overrides), identity.json, wg.key, facts.json, desired.pb, rollback/ (pending change); /var/run/jumo/status.json, agent.pid.

Lessons from the lab (each has a test or a code comment)

  • Replace a running binary by temp file + rename (ETXTBSY).
  • Log to stdout: procd files stderr as daemon.err.
  • Ship /etc/rc.d/S99edge-agent in the image: an enable from uci-defaults only works from the second boot.
  • No VXLAN tunlink: a WireGuard restart destroyed the VXLAN device.
  • Allow SSDP replies (UDP source port 1900) on the uplink, or UPnP looks absent.
  • Request a pinhole for the address the kernel uses as source; keep a stable SLAAC address (wan6.reqaddress=none).
  • Judge a dialed endpoint by a reply through its interface, not by a new handshake (established sessions do not renegotiate for 2 minutes).