Polari
Networking and topology

Isle VPN

What we built, what it gives you, and why we passed on Tailscale and Headscale. Written for a reader with a networking background; the networking and topology model is the context.

Family
isle-vpn: Isle Link (WireGuard-based) and Isle Bridge (OpenVPN-based)
Authority
The isle. Polari mirrors state and files proposals; an operator applies them on the isle

The short version

We run our own WireGuard and OpenVPN deployments under one app family and we keep the control plane on the isle itself. Tailscale is out because its coordination server is proprietary SaaS. Headscale is licence-clean but is a central coordination authority, which is the one thing this design refuses to have. Everything a managed overlay is liked for at the user level, except automatic NAT traversal, is covered by machinery we already control. NAT traversal is the gap, and it is a planned item rather than a surprise.

Where a VPN sits in the addressing

An app on an isle is exposed rung by rung, each rung a deliberate enablement, default most restrictive. The VPN is a rung of its own between the archipelago and the mesh.

.isleOwn VLAN behind the router. Fully trusted. Names never cross.
.archIsles federated as one L3 network while the measured path meets a floor.
.vpnReachable by members of the VPN this isle's gateway belongs to. Names served by the gateway's DNS.
.meshZero-trust state relays. Consumers are not peers.
webPublic. Only through an explicit expose gateway.

Two consequences matter. The .vpn option exists on a device only when a gateway-kind VPN app is installed there, so exposure cannot outrun the tunnel. And the isle side is the configuration authority: the VPN app's config API binds to isle-local addresses and refuses anything arriving over the tunnel interface. Polari mirrors state and files proposals; an operator applies them on the isle with isle vpn apply. Nothing reachable through the VPN can change the VPN.

Two providers, ten kinds

Isle Link is WireGuard-based: Noise-framework key-based tunnels, kernel data plane, driven through wg and netlink and never embedded, so our GPLv3 tree stays clear of the GPLv2 tools. Isle Bridge is OpenVPN 2.x-based: x509 identity with a CA and revocation list, TCP/443 traversal, and layer-2 tap bridging, driven through the management interface. The rule of thumb: Link when both ends run ours, Bridge when joining a network or an OpenVPN-only box. Every row carries one of two labels so nobody mistakes a blind relay for a hub.

KindWhat it doesLabelPlacement
Link NodeThe device gets its own /32 on a Link network; nothing behind it is sharedendpointcontainer
Link GatewayCarries the isle subnet; makes the .vpn rung availableendpointrouter extension
Link RelayForwards encrypted datagrams between peers that cannot reach each other; holds no keysblindcontainer
Link HubMembership authority; routes between members; can carry other isles' subnetssees trafficKVM guest
Link ExitA hub plus WAN masquerade; off until the knob is turnedsees trafficKVM guest
Bridge ClientJoins a Bridge server with a certificate; works over TCP/443endpointcontainer
Bridge ServerCertificate-issuing hub with live per-client control and revocationsees trafficKVM guest
Bridge SpanStretches the isle VLAN across sites at layer 2 (a tap bridged into the isle bridge)sees trafficrouter extension
Bridge ExitA Bridge server plus WAN masquerade; off until the knob is turnedsees trafficKVM guest
Bridge PeerAn OpenVPN-only box joined as a gateway peerendpointcontainer

Placement: one rule per body

  • KVM guest for every kind that sees traffic and holds authority: hub, server, exit. Own failure domain, own bridge, WAN masquerade on its own interface, keys and CA on its own disk. Never inside the router, never a container sharing the host network namespace. Link guests run OpenWrt; Bridge guests run Debian with the CA built on first boot and the management interface bound to localhost.
  • Router extension for every kind that carries the isle's own subnet or VLAN: gateway, span. The subnet, DHCP, DNS and firewall zones live on the OpenWrt router guest, so the tunnel that carries them lives there too. WireGuard in its own zone with the listen port opened on the WAN-facing zone only, or an OpenVPN tap bridged into the isle VLAN.
  • Container for endpoints, clients, peers and the blind relay. No subnet, nobody else's keys, fine on rented hardware.

Private keys are generated on the device at apply time and never rendered or pushed. Hooks are templated toggles (forward, masquerade, route-add), never free-text scripts. Exits render with masquerade off.

The three levels and who serves them

LevelDefinitionVPN kinds usedNever
IsleOwn LAN, fully trusted. A VPN extends it to a device elsewhere or joins two sites as one isle.All ten
ArchipelagoIsles federated as one network while the measured path meets the floor: round trip ≤ 150 ms, loss ≤ 1 percent, ≥ 1000 kbps (placeholders). Membership is measured, not declared.All ten; gateway-to-gateway links through a blind relay by defaultRouting hubs on hardware you do not own
MeshZero-trust state relays. Consumers receive state and send returns through the proposal seam; they are not peers.Relay bodies, TCP/443 rendezvous, opt-in exitsAny membership authority

Each level has its own topology display on the Polari side, pairing the level's definition and the kinds usable there with the live rows crossing it.

How this stands in for a managed overlay

What people like about a managed overlay is not the protocol; Tailscale runs WireGuard, same as Isle Link. The value is the coordination layer, and each of its functions maps onto machinery we already have:

FunctionManaged overlayIsle VPN
Identity and joinIdentity-provider login to the coordination serverA join request that a person on the isle approves; consent is a row both sides keep, revocable per child
Key exchangeNode keys registered with the coordinatorKeys made on the device; public keys ride the isle's push; proposals carry peers, never private material
Relay behind NATEncrypted HTTPS relaysLink Relay: a blind UDP forwarder with no keys, safe on a rented box
NamesMagic DNSThe gateway's DNS serves <app>.vpn to members; .isle never crosses
Access controlAn ACL policy file at the coordinatorAccess-rule rows rendered to nftables on the router
Subnet routes, exitsAdvertised routes, an exit-node flagThe gateway carries the isle subnet; exit kinds masquerade only when the knob is on
Client onboardingApp loginThe rendered config imported by the stock WireGuard app from a QR code; OpenVPN for Android (GPLv2) for Bridge
ObservabilityAn admin consolewg show counters and the OpenVPN management interface mirrored as rows; per-level topology pages
Direct-path discoverySTUN, hole punching, relay fallbackNot built. Relay fallback exists; direct-path discovery is the open item below

Why not Tailscale

Rejected on licence.

The client and relay code are BSD-3-Clause and would be fine. The coordination server the client depends on, for login, key registration and ACL distribution, is proprietary software run as a service by Tailscale Inc. Polari is GPLv3 and a proprietary dependency is a hard blocker. Using the open client without that control plane means replacing it, which is the Headscale question.

Why not Headscale

Passed on architecture, not licence.

Headscale is BSD-3-Clause and GPLv3-compatible; we could ship it. It is a central coordination server: one authority holding identity, keys and policy for the whole network. Two of our rulings run the other way. The isle is the authority for its own VPN and refuses configuration from over the tunnel, and federation between isles goes through blind relays by default, with routing hubs only on hardware the household owns. It would also be a third stack to drive next to WireGuard and OpenVPN, with an overlapping feature set. It stays on the books as a possible adapter for anyone who wants the tailnet model wholesale; it is not a provider.

The honest gap

Direct-path discovery.

A managed overlay finds a direct UDP path with STUN and hole punching and falls back to a relay only when it must. We have the relay fallback and we already record link measurements per destination. The missing piece is small: probe direct reachability, prefer it when it meets the floor, drop to the blind relay when it does not. It belongs in the VPN plan as its own phase and does not change the placement or authority model above.

Reference

pol vpn kinds              the ten kinds and the rule of thumb
pol vpn placements         where each kind runs and at which levels
pol vpn topology <level>   isle | archipelago | mesh — definition, floor, kinds, live rows
pol vpn qr <peer>          a rendered config as a QR code for the stock WireGuard app
isle vpn install <kind>    on the isle: container, --in <guest>, or --on-router
isle vpn apply <proposal>  apply what Polari proposed

← All documentation