Self-hosted prialo control plane: the three ports and backups
A self-hosted prialo control plane runs as three Docker Compose containers on one Linux VPS and publishes three ports: UDP 3478 for STUN, TCP 50051 for gRPC and TCP 4430 for the relay. 2 vCPU and 2 GB of RAM are enough for hundreds of nodes. Back up the PostgreSQL database and the server keys.
The three ports a self-hosted prialo control plane publishes
The coordination server listens on TCP 50051 for gRPC and on UDP 3478 for STUN, and the relay listens on TCP 4430. Those are the only ports the VPS firewall needs to publish. The devices in the mesh open nothing: no port is forwarded on any office or home router.
| Port | Service | Who connects to it | Published to the Internet |
|---|---|---|---|
| UDP 3478 | STUN on the coordination server | Every node, to negotiate the direct path | Yes |
| TCP 50051 | gRPC with TLS pinned by SPKI fingerprint | Every node, for control traffic | Yes |
| TCP 4430 | Relay forwarding packets it cannot decrypt | Nodes whose direct path fails | Yes |
| TCP 8080 | Admin API and dashboard | Only the administrator, through an SSH tunnel | No, never |
The admin API on port 8080 is never published to the Internet. To reach the dashboard, open an SSH tunnel to the VPS and use the forwarded local port. Anyone scanning the server sees only gRPC behind TLS, STUN and a relay that forwards end-to-end encrypted packets.
Why prialo's gRPC on port 50051 uses a pinned key rather than a certificate authority
Every node is installed with the SPKI fingerprint of the server's TLS key, written as sha256:..., and refuses any server that does not present exactly that key. No certificate authority is part of the trust model, so the server needs no public certificate. The operational consequence is plain: whoever loses that key loses the identity every node trusts.
VPS sizing for the prialo control plane: 2 vCPU and 2 GB of RAM
2 vCPU and 2 GB of RAM are enough for hundreds of nodes. The package runs three containers with Docker Compose (coordination server, relay and PostgreSQL) on Linux x86_64 or arm64, with Docker Engine 24 or newer and Compose v2, so a small ARM instance works as well as an x86 one.
Relay CPU is rarely the limit: forwarding one frame takes about 23 ns, and that cost does not depend on how many clients are connected. Bandwidth is what deserves attention. Traffic only goes through the relay when the direct path fails, typically behind carrier CGNAT, symmetric NAT or another VPN in front; the guide to CGNAT for branches step by step covers those cases.
A relayed SSH session uses well under 1 MB per hour; remote desktop or screen sharing uses 0.5 to 1 GB per hour. To keep the VPS transfer allowance in check, PRIALO_MESH_QUOTA_BYTES caps relayed egress per mesh per month. Past the cap, the relay drops and counts that mesh's frames without disconnecting anyone.
The two things to back up on a self-hosted prialo server
The customer keeps the keys and the database on their own server, and those are the two things that need a copy off the VPS.
- The PostgreSQL database: it holds device names, their fixed addresses inside 100.64.0.0/10, policies, enrolment keys, approvals and the audit log of every administrative event. Without it, the mesh is rebuilt by hand.
- The server keys: above all the TLS key whose fingerprint every node has pinned. Restored on a new VPS, nodes reconnect; lost, every node refuses the replacement and has to be joined again with a new --tls-pin.
Device private keys are not on that list: each device holds its own WireGuard key pair, and there is no username or password on the data path. Sinergia does not host or access the instance, so there is no other copy to recover from; backups are the operator's job.
Joining the first Linux or macOS node to a self-hosted prialo server
- Create an enrolment key in the dashboard, reached through the SSH tunnel; keys expire, can be single-use or reusable and can be revoked.
- Run the install as root on the node, giving the server, the relay and the pinned fingerprint:
sudo PRIALO_AUTH_KEY='<enrolment key>' prialo install --server=control.example.com:50051 --relay=control.example.com:4430 --tls-pin=sha256:<fingerprint>
Then prialo status must show 'Control: tls, pinned' and an IP inside 100.64.0.0/10. prialo peers lists the other devices and prialo ping <host-or-ip> tests a path. If the node should give access to a LAN, it advertises it with prialo up --advertise-routes=192.168.50.0/24; nothing is routed until an administrator approves it and each client opts in with --accept-routes.
What the self-hosted prialo package can and cannot run today
On 17 October 2026 the self-hosted package and the command-line client for Linux and macOS work; Windows is an early build without installer or signature. The Mac and iPhone apps are in Apple's review queue and cannot be downloaded yet, and Android is in preparation. Only Linux can act as a subnet router.
A team that already uses the Tailscale clients and wants its own coordination server may be better served by Headscale, an open-source implementation of that server; NetBird also publishes its management server as open source. The Tailscale alternatives comparison table sets the architectures side by side. prialo is made by Sinergia, a Barcelona company, and the package is on the self-hosted server download section with checksums.
Frequently asked questions
Which ports does a self-hosted prialo server need open?
A self-hosted prialo server publishes UDP 3478 for STUN, TCP 50051 for gRPC with a pinned TLS key and TCP 4430 for the relay. The admin API on port 8080 stays closed to the Internet and the dashboard is reached through an SSH tunnel. Devices open no ports at all.
How big a VPS does the prialo control plane need?
The prialo control plane runs on 2 vCPU and 2 GB of RAM for hundreds of nodes, on Linux x86_64 or arm64 with Docker Engine 24 or newer and Compose v2. Relayed bandwidth matters more than CPU, and PRIALO_MESH_QUOTA_BYTES caps it per mesh each month.
What happens if the prialo server's TLS key is lost?
If the TLS key of a self-hosted prialo server is lost, nodes refuse any replacement server, because each one pinned that key's SPKI fingerprint and no certificate authority can vouch for another. Every node would have to be joined again, which is why that key belongs in the backup.
Can Sinergia recover a self-hosted prialo instance?
No. With the self-hosted package, the customer keeps the keys and the PostgreSQL database on their own server, and Sinergia does not host or access that instance. Restoring a broken prialo server depends entirely on the operator's own copies of the database and the server keys.
Would you rather run your own server? Guide to the self-hosted prialo package