helm · buoy · beacon · caravel
Four components.
One controller, dumb public nodes, a stateless relay, and a mobile client that reads its profiles from interchangeable sources. Each keeps to its role; the trust boundaries do the heavy lifting.
§ helm · controller / management plane
helm
The ship's wheel — where you steer the fleet from.
helm is the PharosVPN controller. It is the source of
truth for the fleet, the admin Web UI, the certificate authority,
the account & profile-sync service, and the engine that drives
every VPN node.
Role
- Private, behind NAT — zero inbound ports. Every connection is helm-initiated outbound. The controller never appears in public DNS.
- Drives the fleet. Holds a long-lived mTLS/gRPC connection to each
buoy: pushes config and peers, receives a live event stream. - Issues credentials. Holds the in-repo CA; mints node, relay, and per-user/device certificates.
- Serves admins. Embedded SvelteKit admin UI on localhost, live-updating over WebSocket, multi-admin safe via optimistic concurrency.
- Serves users. Account login + end-to-end-encrypted profile sync, reached by clients only through a
beaconrelay (embedded by default).
Stack
§ buoy · VPN node agent
buoy
A fixed, public marker anchored out in the water — ships rely on it.
buoy is the PharosVPN node agent. It runs on every
public VPN node, runs the data plane (AmneziaWG + XRay), and
applies only the configuration the controller pushes to it over
mTLS. It is deliberately dumb: a compromised buoy
cannot compromise the fleet.
Role
- Public IP. Terminates end-user tunnels on UDP 443 (AmneziaWG) and TCP 443 (XRay / VLESS+REALITY).
- Stateless except for what
helmgave it. All config is written to disk only after the controller pushes it over a validated mTLS connection. - Control port. Listens for the controller's mTLS/gRPC connection: status, metrics, config push, live peer add/remove, service restart — and streams live events back.
- SSH is install-only.
helmreaches a node over SSH solely to install and update the agent; every operational instruction is gRPC. - Cold-start resilient. Comes up from disk every boot; controller offline ⇒ existing tunnels keep working.
Stack
§ beacon · relay
beacon
A signal relayed onward — so the lighthouse can stay hidden.
beacon is the PharosVPN relay — a stateless, public,
mTLS-terminating proxy that lets end-user clients reach a
controller that has no public presence. The controller
(helm) stays behind NAT;
beacon is the only public ingress for clients.
Role
- Public ingress for clients only. Terminates client mTLS, forwards their gRPC streams to
helm. - Stateless. No database. Every identity lookup is delegated to
helm. - Sanitizing. Strips spoofable client metadata; injects exactly one trusted value — the verified device fingerprint.
- Two transports to
helm: embedded (in-process insidehelm) or remote reverse tunnel (helmdials out to a public beacon). Identical trust either way. - Sees only ciphertext. Profile bundles cross
beaconend-to-end encrypted; a compromised remote beacon host cannot read user profiles.
Stack
§ caravel · mobile client
caravel
The small, agile ship that crossed unknown oceans.
caravel is the PharosVPN mobile client — the app
end-users actually run. It establishes the VPN tunnel and
acquires its profiles from whichever source fits the user: a
synced account, a QR scan, a file, or enterprise MDM.
Role
- The VPN client. Runs the actual tunnel — multi-node, multi-protocol (AmneziaWG + XRay/REALITY).
- Profile sources, not modes. A VPN engine reads a local profile store; profiles enter that store from interchangeable sources — account sync, QR, file import, MDM managed config, deep link. "Synced vs unsynced" is just which sources are enabled, not a different app.
- Posture-aware. Personal: account login + QR + file import, with an admin section if the logged-in account is an admin. Managed (MDM config present): account login and admin hidden, profiles locked. One app, one store listing.
- Offline-resilient. Connects from cached local profiles when the account service is unreachable.