Self-host deployment
This guide walks through the recommended run order for a community deployment: Postgres → control-plane → relay-manager → WebUI → relay-daemon.
Prerequisites
- Docker + Docker Compose
- Go 1.22+
- Yarn
- WireGuard tooling (
wg,wg-quick) on Linux hosts
1) Postgres (Docker)
Use the bundled Compose file to start Postgres locally.
docker compose -f deploy/docker-compose.yml up -d db
Default credentials (update in deploy/docker-compose.yml if needed):
POSTGRES_DB=nanamiPOSTGRES_USER=nanamiPOSTGRES_PASSWORD=nanami
2) Control-plane (Go)
export DATABASE_URL=postgres://nanami:nanami@localhost:5432/nanami?sslmode=disable
export JWT_SECRET=change_me
export APP_ENV=dev
export APP_MODE=community
go run ./apps/control-plane/cmd
The API starts on http://localhost:8080.
3) Relay-manager (Go)
Create a join key with scope relay_manager in the WebUI or via API, then run:
export CONTROL_PLANE_URL=http://localhost:8080
export JOIN_KEY=your_join_key
export TENANT_SLUG=your-tenant-slug
export NODE_JOIN_KEY=node-secret-key
go run ./apps/relay-manager/cmd
The manager listens on http://localhost:8081 and expects relay-daemons to use the
same NODE_JOIN_KEY.
4) WebUI (Next.js)
cd apps/webui
yarn install
CONTROL_PLANE_URL=http://localhost:8080 yarn dev
Open http://localhost:3000 and complete bootstrap (create the first admin).
5) Relay-daemon (Docker, Linux, macOS)
Docker (recommended for dev)
Build and run the relay-daemon container (requires NET_ADMIN):
docker compose -f deploy/docker-compose.yml --profile relay up -d relay-daemon
Required env vars (see compose file):
CONTROL_PLANE_URLandRELAY_DAEMON_JOIN_KEY(registration)RELAY_MANAGER_URLandNODE_JOIN_KEY(heartbeat to relay-manager)NODE_ENDPOINT(optional public endpoint for WG)
Linux (host)
export RELAY_MANAGER_URL=http://localhost:8081
export NODE_JOIN_KEY=node-secret-key
export CONTROL_PLANE_URL=http://localhost:8080
export RELAY_DAEMON_JOIN_KEY=your_relay_join_key
export NODE_ENDPOINT=public-ip:51820
go run ./apps/relay/cmd/relay-daemon
macOS (observed-state only)
macOS runtime reports observed-state but WireGuard apply is pending:
export RELAY_MANAGER_URL=http://localhost:8081
export NODE_JOIN_KEY=node-secret-key
export CONTROL_PLANE_URL=http://localhost:8080
export RELAY_DAEMON_JOIN_KEY=your_relay_join_key
go run ./apps/relay/cmd/relay-daemon
Known limitations
- macOS/Windows WG runtime is pending (status shows "WG runtime pending").
- Relay-daemon in Docker requires host WireGuard support.
- External endpoints behind NAT must be configured manually.