Compatibility

Where pilot-daemon runs.
Pick the right mode.

One binary, two transports. UDP is the default — direct peer paths, lowest latency. Compat tunnels everything through a single outbound TCP/443 for environments that block UDP or restrict egress.

Two modes

UDP for direct paths.
Compat for everything else.

Per-platform

Where it runs.
What flag to set.

udp — default UDP transportcompat-transport=compatcompat+proxy — would need HTTPS_PROXY support (not yet available)wrong runtime — no daemon

These per-platform notes are our best-effort understanding of each vendor's network policy, not continuously tested guarantees — vendors change their rules, so verify against your platform's current docs and tell us if a cell is wrong.

Container hosting / PaaS

Deploy as a Dockerfile or buildpack. UDP availability varies — when in doubt, ship in compat mode.

Rendercompat

UDP blocked. Single TCP/443 works as of v1.10.3.

Railwayudp

Default-allow egress on both protocols.

Fly.io Machinescompat

UDP needs dedicated IPv4; even then app-level egress is flaky.

Herokucompat

App-UDP undocumented; daemon re-registers fine across the ~24h dyno cycle.

DigitalOcean App Platformcompat

Safer default — can't open SSH/SMTP ports.

Northflankudp

UDP + TCP both first-class.

Coolify / CapRoverudp

Self-hosted; inherits host firewall — open UDP/4000 manually.

Serverless / functions

Three out of four can't host a persistent process. Cloud Run is the exception when min-instances=1.

AWS Lambdawrong runtime

15-min hard timeout kills the tunnel; no persistent daemon. Run the daemon as a Lambda Extension only while warm.

Google Cloud Runcompat

Set min-instances=1 to keep warm. Inbound is HTTPS-only.

Vercel / Netlify / GCP Functionswrong runtime

Ephemeral execution — no persistent process model.

Cloudflare Workerswrong runtime

No long-lived sockets, no UDP, no listen().

VMs / IaaS

Full control. UDP works. Use -public to advertise a public node.

EC2 / GCE / Azure VMudp

Open UDP/4000 in security group.

DO Droplets / Hetzner / Linodeudp

Same model — managed VMs with full firewall control.

Bare metaludp

No restrictions beyond your own network policy.

Kubernetes

DaemonSet or sidecar. Default CNI allows UDP; corporate clusters with NetworkPolicy default-deny → compat.

Vanilla k8s / EKS / GKE / AKSudp

Default CNI allows UDP egress; no special config needed.

k3s / k0s / OpenShift / kindudp

Same model — sidecar pattern over /shared/pilot.sock.

Locked clusters (NetworkPolicy default-deny)compat

Allow egress to TCP/443 only; compat mode covers the rest.

Coding-agent sandboxes

A mix. Modal/E2B/Daytona/Codespaces are open; Docker-AI-Sandbox-class (Replit Agent, Devin) blocks raw TCP.

Cursor Cloud Agentsallowlist

Add *.pilotprotocol.network + 34.71.57.205 to the egress allowlist.

Replit Agentcompat+proxy

Docker AI Sandbox — raw TCP/UDP blocked. HTTPS_PROXY is not supported yet.

Devin (Cognition)compat+proxy

Same Docker AI Sandbox model.

Modal Sandboxesudp

Default-allow. Long timeout for persistent run.

E2B Sandboxesudp

IP/CIDR rules only; Pilot endpoints allowed by default.

Daytona Sandboxesudp

Default-allow; iptables-based.

GitHub Codespacesudp

IPv4 outbound works; 30-min idle stop pauses the daemon.

Gitpodudp

Configure .gitpod.yml task.

Coder (workspaces)udp

Inherits underlying provider (EC2 / k8s / Docker).

Manus Sandboxudp

Default-allow with configurable egress rules.

Lovable / v0 / Bolt.newwrong runtime

UI generators / WebContainers — no POSIX sockets.

Desktop / local

install.sh wires up the right supervisor for each OS.

macOS (LaunchAgent)udp

~/Library/LaunchAgents/network.pilotprotocol.pilot-daemon.plist written; load it with launchctl.

Linux (systemd)udp

sudo install writes the pilot-daemon + updater units; enable/start them with systemctl.

tmux / screenudp

Ad-hoc dev only — no auto-restart.

Windowsnot shipped

No Windows binary yet — use WSL2 (Linux mode).

Browser / WASM

The daemon needs a POSIX runtime; the SDKs need a local daemon over a Unix socket, so neither runs in a browser tab or WASM.

Browser tabwrong runtime

No raw sockets, and the JS SDK is Node-only (Unix-socket client of a local daemon) — neither works here.

WASM runtimewrong runtime

Same model — daemon needs POSIX.

Corporate networks

Egress models.
What works today.

Model
Examples
Today
What's needed
Open egress
home wifi, most cloud VMs, default Docker
✓ UDP works — use default
nothing
Default-deny, TCP/443 only
hotel / airport / locked corp wifi
✓ Compat works as-is — single TCP/443 outbound
-transport=compat
HTTP CONNECT proxy
corp networks with explicit proxy URL
✗ Neither the WSS dial nor the registry TLS dial honors HTTPS_PROXY today
not yet supported
Transparent TLS interception
Zscaler, Fortinet, Palo Alto, BlueCoat, Netskope
✓ Works with -tls-trust=system (corp CA in OS store — current default)
already supported
HTTP-proxy-only sandbox
Replit Agent, Devin, Docker AI Sandbox
✗ Blocked — daemon needs raw TCP to :443
not yet supported
Domain-name allowlist
Cursor Cloud Agents, Zscaler PAC
✓ Works after adding *.pilotprotocol.network + 34.71.57.205
doc-only
DPI / protocol allowlist
Great Firewall, Iran-style filters
✗ Blocked — no domain fronting / ECH today
out of scope
Single-port 443

How single-port-443 works.

Before v1.10.3, compat-mode daemons needed two outbound ports: TCP/443 for the beacon WSS bridge and TCP/9000 for the registry. That worked for most "UDP-blocked but TCP-open" environments — but blocked anyone in airport wifi or strict corporate firewalls that allow only TCP/443.

v1.10.3 migrates the registry channel to TLS on TCP/443, multiplexed by SNI on the same nginx listener as the beacon. nginx pre-reads the TLS ClientHello's SNI field and routes registry.pilotprotocol.network traffic to a TLS terminator that proxies plain bytes to the existing registry; beacon.pilotprotocol.network traffic goes to the WSS-aware vhost. A compat daemon's lsof now shows exactly one outbound port: 443.

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

Worked examples

Five deployments.

Render free-tier worker — UDP blocked

# Dockerfile
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y curl ca-certificates \
    && rm -rf /var/lib/apt/lists/*
RUN curl -fsSL https://pilotprotocol.network/install.sh | \
    PILOT_EMAIL=you@example.com PILOT_ALLOW_ROOT=1 sh
ENTRYPOINT ["/root/.pilot/bin/pilot-daemon", "-transport=compat"]

No port exposed. Render allows arbitrary outbound TCP/443. Zero UDP, zero TCP/9000.

AWS Lambda — don't

Lambda has a 15-minute hard timeout and freezes the execution environment between invocations. A Lambda Extension can host a sidecar process but only while the function is warm. Wrong runtime for pilot-daemon. The JS and Python SDKs are not a way around this — both are clients of a local pilot-daemon over a Unix socket, so they still need the daemon running. A Lambda Extension can host the daemon while the function is warm; there is no daemon-less SDK path.

Kubernetes sidecar — egress-only pod

apiVersion: v1
kind: Pod
metadata: { name: app-with-pilot }
spec:
  containers:
    - name: app
      image: your/app:latest
    - name: pilot
      image: debian:bookworm-slim
      command: ["/bin/sh", "-c"]
      args:
        - curl -fsSL https://pilotprotocol.network/install.sh | \
          PILOT_EMAIL=pilot@example.com PILOT_ALLOW_ROOT=1 sh &&
          exec /root/.pilot/bin/pilot-daemon -transport=compat \
            -socket /shared/pilot.sock
      volumeMounts: [{ name: pilot-sock, mountPath: /shared }]
  volumes: [{ name: pilot-sock, emptyDir: {} }]

Works under any NetworkPolicy that permits egress to TCP/443. App talks to daemon over /shared/pilot.sock.

macOS laptop — LaunchAgent

curl -fsSL https://pilotprotocol.network/install.sh | \
  PILOT_EMAIL=you@example.com sh

Installer writes ~/Library/LaunchAgents/network.pilotprotocol.pilot-daemon.plist and prints the launchctl load command to start it. Defaults to -transport=udp; flip to compat only if your network blocks UDP/4000.

Forced-compat systemd unit — locked-down corp Linux

curl -fsSL https://pilotprotocol.network/install.sh | \
  sudo PILOT_EMAIL=you@example.com PILOT_ALLOW_ROOT=1 sh
sudo systemctl edit pilot-daemon   # add ExecStart override with -transport=compat
sudo systemctl restart pilot-daemon

One binary. Any environment.

Install pilot-daemon, pass -transport=compat if your environment blocks UDP, and you're online. That's it.