Flow

Running pilot behind a firewall

When UDP is blocked, compat mode tunnels Pilot packets over HTTPS/WSS to the beacon — same overlay, different wire.

When you need compat mode

The default Pilot daemon binds a public UDP socket and reaches peers either directly or via beacon hole-punch. That model works on home ISPs, cloud VMs (GCP, AWS, Azure), and most corporate networks. It does not work on:

If your daemon registers fine but heartbeats keep failing, or queries to specialists time out with relay-retransmit errors flooding the log, you're likely in one of these environments. Compat mode is the answer: same daemon binary, same overlay, just a different wire from your daemon to the beacon.

Enabling compat mode

Compat mode is opt-in via one CLI flag on the standalone pilot-daemon binary:

pilot-daemon -transport=compat

That's it — every other flag has a working default. As of v1.10.3 the daemon uses a single outbound TCP/443 connection for everything: the beacon WSS bridge AND the registry. Explicit form:

pilot-daemon \
  -transport=compat \
  -compat-beacon=wss://beacon.pilotprotocol.network/v1/compat \
  -tls-trust=system \
  -registry=registry.pilotprotocol.network:443 \
  -registry-tls -registry-trust=system

Flag semantics:

The daemon also automatically forces relay_only=true when compat is enabled — peers will route to it via the beacon's relay path instead of trying direct UDP, which would fail anyway.

How it works

The compat-mode daemon opens outbound connections to only TCP/443 — multiplexed by SNI through a single nginx listener on the rendezvous host:

nginx pre-reads the TLS ClientHello's SNI field and routes registry traffic to its TLS terminator (which proxies plain bytes to the existing registry server), while beacon traffic terminates on the existing WSS-aware vhost. No code change on the registry side; the daemon's -registry-trust=system path verifies the public Let's Encrypt cert.

After the TLS handshake, the daemon completes an Ed25519 challenge so the beacon can authenticate it against the registry's stored pubkey. From that point on, every Pilot UDP packet the daemon would have sent becomes one binary WS frame; every inbound binary WS frame becomes one Pilot packet returned by Recv.

The beacon transparently bridges between UDP peers and WSS peers. From a specialist's point of view, a compat-mode daemon looks identical to a symmetric-NAT peer — the beacon's existing relay logic delivers packets without any change to the specialist code.

End-to-end Ed25519 trust is unchanged. TLS provides the encrypted channel between daemon and beacon; Ed25519 still protects peer-to-peer identity and payload integrity, exactly as in UDP mode.

TLS trust + corp proxies

The public beacon at beacon.pilotprotocol.network currently presents a Let's Encrypt certificate (terminated by nginx on the rendezvous host). With -tls-trust=system (the default), the daemon verifies that cert against the OS trust store — the same way browsers do — and connects normally. The daemon logs a clear startup warning that this trust mode does not protect against TLS-intercepting proxies on the path.

A future release will ship the daemon binary with the Pilot Protocol root CA cert embedded. At that point the default flips to -tls-trust=pinned, which verifies the beacon's leaf cert against only this root — no public CA bug, DNS hijack, or Let's Encrypt issuance mistake can MITM your daemon. The escape hatch for that future state (for daemons behind TLS-intercepting corp proxies like Fortinet, Zscaler, BlueCoat, Palo Alto, Cisco Umbrella) will be to pass -tls-trust=system explicitly.

End-to-end Ed25519 protects peer identity and payload integrity in both trust modes. A TLS-intercepting proxy can read or censor relay traffic on the wire but cannot forge a specialist's signed reply.

Limits

For the full design — transport matrix, PKI, wire format, rollout plan — see docs/SPEC-compat-mode.md in the repo.