Skip to content

v2.12.0 — the site network

Choose a tag to compare

@wmantly wmantly released this 12 Aug 02:07
· 21 commits to master since this release
c423ae4

v2.12.0

The directory is now where the WireGuard cluster is configured. Sites, devices,
LAN mapping and internet exits all live here; each site's gateway reads the
roster and configures itself. Requires theta-gateway v3.0.0.

  • feat: the site network. A site that joins the directory is on the network
    — no separate mesh to set up. siteId IS the site's ldapServerId, already
    allocated once cluster-wide by the master at join time (under a lock, after
    two spokes were once handed the same one), so the mesh needs no allocator of
    its own. That one number drives LDAP replication, the gateway's
    172.24.0.<id> address, and the site's 10.<id>.0.0/16.
  • feat: /network page, visible to any signed-in user because enrolling
    your own devices is not an admin task. Sites tab shows each site's addresses
    and whether its gateway has actually published a key — joined-but-not-started
    is a real state that used to look identical to healthy. Devices tab enrols
    hardware and picks an exit. Exit Access tab is admin-only.
  • feat: devices with optional key custody. Supply a public key and the
    private half never reaches the server; omit it and one is generated, rendered
    into a config once, and forgotten — never stored, never logged, not
    recoverable. Addresses come from the site's own pool, lowest-free so a
    removed device returns its address rather than a counter marching upward.
  • feat: per-device internet exits. Two independent things: a site marked
    exitOpen is saying it is willing to carry traffic; a grant says a user may
    use it. Revoking a grant immediately drops affected devices back to local
    breakout rather than leaving them routed somewhere they may no longer go.
    Exit choice is a routing rule on the gateway, so switching exits produces a
    byte-identical device config and needs no reconnect.
  • feat: DNS is pushed as the mapped address, not the physical one. A device
    handed 192.168.1.1 only resolves while sitting on that LAN; over the tunnel
    what is routed is the shadow range. The site form shows the translation as
    you type and warns when an address is outside both mapped LANs, where it
    cannot be mapped and devices would get no resolver at all.
  • feat: MTU clamped to 1380 in device configs. Mesh-then-exit is WireGuard
    inside WireGuard, and a device sized for one hop blackholes large packets on
    the second — the classic "SSH works, HTTPS hangs".
  • feat: devices running theta-agent are configured over the agent's existing
    websocket instead of a human copying a file. The push deliberately carries no
    private key: the agent holds its own.
  • feat: the hub — the site carrying 10.0.0.0/8 as a catch-all — is chosen in
    the UI rather than implied by which site holds the master directory, since
    the natural hub is a cheap always-up VPS.
  • change!: utils/mesh_route.js stops being a workaround. It existed because
    WireGuard lived inside the gateway container's namespace, so the only path to
    a peer was a userspace relay on a port derived from the site index. A peer
    site's directory is now simply 10.<siteId>.0.2:3001, and the derived-port
    contract the two repos had to keep in sync is gone. An address in the retired
    scheme deliberately resolves to nothing rather than silently naming a
    different site. The public-endpoint fallback stays, so a deployment whose
    containers have no route into the mesh still replicates over the internet.
  • fix: the roster now reaches every site. It is written at each site (a
    gateway publishes to its own directory) but replication only flows
    master -> spoke, so two halves were missing: a spoke's public key never left
    the spoke, and a spoke never learned any other site existed. Either alone
    means the mesh works only at whichever site happens to be the master. Spokes
    now forward their gateway details over POST /api/site/spokes — the channel
    they already have, with the credential they already hold — and the master
    carries the whole roster in its export. Roster edits push a resync
    immediately instead of waiting for an unrelated catalog change. A site's own
    row is never overwritten by an incoming export, since the local copy is
    always at least as fresh.
  • fix: exit interfaces need their own key. A gateway's exit interface and
    its mesh interface presented the same public key to the same remote, which
    keeps one endpoint and one session per peer key — so the remote's endpoint
    flapped between the two and they invalidated each other's session. Verified
    against wireguard-go: with one key on two interfaces the remote settled on
    whichever handshook last while both kept re-handshaking; with separate keys
    it holds two stable peers. Gateways now publish a second gatewayExitPublicKey
    and GET /api/mesh/peers tells an exit site which gateways to accept under
    it, allowed only the device addresses actually using that exit.
  • docs: The Site Network.