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 transport compat-transport=compat compat+proxy — needs HTTPS_PROXY (tracked on GitHub) wrong runtime — no daemon

Container hosting / PaaS

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

Render compat

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

Railway udp

Default-allow egress on both protocols.

Fly.io Machines compat

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

Heroku compat

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

DigitalOcean App Platform compat

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

Northflank udp

UDP + TCP both first-class.

Coolify / CapRover udp

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 Lambda wrong runtime

15-min hard timeout kills the tunnel. Use the SDK in the handler, not the daemon.

Google Cloud Run compat

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

Vercel / Netlify / GCP Functions wrong runtime

Ephemeral execution — no persistent process model.

Cloudflare Workers wrong 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 VM udp

Open UDP/4000 in security group.

DO Droplets / Hetzner / Linode udp

Same model — managed VMs with full firewall control.

Bare metal udp

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 / AKS udp

Default CNI allows UDP egress; no special config needed.

k3s / k0s / OpenShift / kind udp

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 Agents allowlist

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

Replit Agent compat+proxy

Docker AI Sandbox — raw TCP/UDP blocked. HTTPS_PROXY support tracked on GitHub.

Devin (Cognition) compat+proxy

Same Docker AI Sandbox model.

Modal Sandboxes udp

Default-allow. Long timeout for persistent run.

E2B Sandboxes udp

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

Daytona Sandboxes udp

Default-allow; iptables-based.

GitHub Codespaces udp

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

Gitpod udp

Configure .gitpod.yml task.

Coder (workspaces) udp

Inherits underlying provider (EC2 / k8s / Docker).

Manus Sandbox udp

Default-allow with configurable egress rules.

Lovable / v0 / Bolt.new wrong 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.daemon.plist auto-loaded.

Linux (systemd) udp

sudo install enables the system unit + auto-updater.

tmux / screen udp

Ad-hoc dev only — no auto-restart.

Windows not shipped

No Windows binary in v1.10.3.

Browser / WASM

Use the JS/Python SDK from your app; the daemon needs a POSIX runtime.

Browser tab wrong runtime

No raw sockets — use the JS SDK over WSS instead.

WASM runtime wrong 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
~ WSS dial honors HTTPS_PROXY; registry TLS dial does not
tracked on GitHub — registry over HTTPS_PROXY
Transparent TLS interception
Zscaler, Fortinet, Palo Alto, BlueCoat, Netskope
✓ Works with -tls-trust=system (corp CA in OS store — v1.10.3 default)
already supported
HTTP-proxy-only sandbox
Replit Agent, Devin, Docker AI Sandbox
✗ Blocked — daemon needs raw TCP to :443
tracked on GitHub — HTTPS_PROXY via CONNECT
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
v1.10.3

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 | \
    sh -s -- --email [email protected]
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. If you want Pilot-from-Lambda, call the registry directly via the JS or Python SDK over HTTPS during the handler invocation; don't try to run the daemon.

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 | \
          sh -s -- --email [email protected] &&
          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 | \
  sh -s -- --email [email protected]

Installer writes ~/Library/LaunchAgents/network.pilotprotocol.daemon.plist and loads it. Defaults to -transport=udp; flip to compat only if your network blocks UDP/4000.

Forced-compat systemd unit — locked-down corp Linux

sudo curl -fsSL https://pilotprotocol.network/install.sh | \
  sudo PILOT_ALLOW_ROOT=1 sh -s -- --email [email protected]
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.