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 one flag, on pilotctl daemon start or on the pilot-daemon binary itself:

pilotctl daemon start --transport compat   # always compat
pilotctl daemon start --transport auto     # UDP when the beacon answers over UDP, else compat on TCP 443
pilot-daemon -transport=compat               # the daemon binary directly

You can also set it once with pilotctl config --set transport=compat (config.json transport) or $PILOT_TRANSPORT. Precedence is the flag, then $PILOT_TRANSPORT, then config.json. With none of them set, pilotctl daemon start asks the daemon for auto; pilot-daemon run directly defaults to udp.

That's it — every other flag has a working default. As of v1.10.3 the daemon uses a single outbound port — TCP/443 for everything: the beacon WSS bridge AND the registry (one long-lived WSS connection to the beacon, plus a small TLS connection pool to the registry, all on 443). 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.

Proxy-only egress (no direct TCP)

Some sandboxes go further than blocking UDP: DNS for *.pilotprotocol.network returns blackhole addresses, and the only way out is an HTTP proxy that accepts CONNECT to port 443. Hosted agent VMs such as Meta Muse's work this way.

Since v1.13.11 the daemon speaks HTTPS proxies itself. With compat mode and --proxy auto (the default), the registry, the WSS beacon and the daemon's HTTP clients go through $HTTPS_PROXY / $ALL_PROXY (honoring $NO_PROXY). The daemon CONNECTs by host name, so poisoned local DNS does not matter, and TLS stays end to end. Behind such a proxy with UDP blocked, a plain pilotctl daemon start picks compat by itself.

# Usually nothing to set: HTTPS_PROXY from the environment is used with compat
pilotctl daemon start

# An explicit proxy, used for every connection except loopback
pilotctl daemon start --transport compat --proxy http://proxy.internal:3128

# A proxy whose credentials rotate: a command that prints the current proxy URL
pilotctl daemon start --proxy-cmd 'printf %s "$https_proxy"'

--proxy takes auto, off, or an http(s)://[user:pass@]host:port URL (also $PILOT_PROXY and config.json proxy); a URL with credentials is passed to the daemon through its environment, never on the command line. --proxy-cmd (also $PILOT_PROXY_CMD and config.json proxy_cmd) runs with sh -c, again once 60 s have passed, and whenever the proxy rejects the credentials.

Step-by-step: Run a Pilot node through an HTTPS-only egress proxy. For Muse specifically: Install Pilot Protocol skills in Meta Muse.

Limits

For the full protocol design — transport matrix, PKI, and wire format — see the research page and technical whitepaper linked there.