WireGuard mesh
A single Pier server is self-contained, but once you add remote servers you usually want them to talk over a private, encrypted network rather than the public internet. Pier builds that network as a host-level WireGuard overlay: every server gets a stable private IP, and traffic between them rides an encrypted tunnel.
Mesh management is Owner-only. Every endpoint described here lives behind the global Owner role gate.
How the overlay is built
Section titled “How the overlay is built”The mesh is assembled in deliberate, reviewable steps so a mistake stalls the wizard rather than breaking a live tunnel:
| Step | Endpoint | What happens |
|---|---|---|
| Configure | PUT /api/v1/network/mesh | Set the subnet, listen port and keepalive. Only allowed while the mesh is disabled. |
| Preflight | GET /api/v1/network/mesh/preflight | Checks every server for a reachable pier-net-helper before you commit. |
| Enable | POST /api/v1/network/mesh/enable | Allocates a private IP to every server and flips the mesh on. |
| Configure (apply) | POST /api/v1/network/mesh/configure | Installs WireGuard, mints a keypair per node, writes wg0.conf and brings each tunnel up. |
| Disable | POST /api/v1/network/mesh/disable | Brings every interface down and clears the peer rows. |
The subnet must be a /30 or larger prefix — /31 and /32 leave no usable hosts and are rejected. The local core is always assigned the first host address, so you can hard-code it in env files and runbooks.
The configure pass is sequenced so a partial failure stops early and leaves a recoverable state. A peer that errors is flagged with the helper’s message; you clear it by disabling and re-enabling, then re-running configure.
The pier-net-helper
Section titled “The pier-net-helper”Pier never runs privileged WireGuard commands from the core or agent process. Each server runs a small root daemon, pier-net-helper, that listens on a Unix socket — /run/pier/net.sock by default, overridable with the PIER_NET_HELPER_SOCKET environment variable. The core talks to the local helper directly over that socket; for remote servers it routes the same operations through the agent’s mesh proxy over the pinned HTTPS channel.
Private keys are generated on the node and stay there. The core renders each wg0.conf without a PrivateKey line — the helper injects the node-local key when it writes the file.
The mesh preflight check exists because of this split: it fans out a status probe to every server and refuses to start the Enable wizard if any node is missing a reachable helper, so you can run the retrofit installer up front instead of discovering the gap mid-provision.
Core-to-core peer mesh
Section titled “Core-to-core peer mesh”The steps above connect a core to the servers it manages directly (the local node and its agents). To connect two independent cores, you pair their meshes:
POST /api/v1/network/mesh/pair/{id}— pair this core’s mesh with a registered peer core.POST /api/v1/network/mesh/peer/{id}/unpair— tear the pairing down on both sides.
Pairing is owner-allocated: the initiating core allocates mesh IPs for the remote core’s nodes from its own subnet, ships the plan over the peer-token channel, and stores the remote nodes as external peers so its own wg0.conf gains [Peer] blocks for them. In this version both cores must have already registered each other as peers, and the target core’s mesh must be disabled before pairing.
Service DNS
Section titled “Service DNS”On top of the overlay, you can register logical service names that resolve to whichever node currently hosts a service. A name like db becomes db.mesh, injected as an extra_hosts entry into every stack on deploy, so consumer services connect to a stable name instead of an IP.
Manage these mappings (Owner-only) at:
GET / POST /api/v1/network/service-dnsPUT / DELETE /api/v1/network/service-dns/{name}
Names follow tightened RFC 1123 label rules — lowercase letters, digits and hyphens, starting and ending alphanumeric, up to 31 characters — and cannot collide with an existing server name. Adding or changing a mapping queues a background redeploy so running stacks pick up the new extra_hosts entry.
Next steps
Section titled “Next steps”- Servers & agents — add the remote servers that join the mesh.
- Database clusters — cross-server clusters that rely on the overlay.
- Networking — the per-host
pier-netDocker network.