Install and first network
title: Install and first network description: Quickstart for community mode: install, create a network, add a node, and validate connectivity.
This quickstart gets you from zero to a working private network in community mode.
Prerequisites
- Docker + Docker Compose
- Go (version from
go.mod) - Node.js 20+ and Yarn
- Linux host or container environment with WireGuard support for gateway runtime tests
Use the repo runtime baseline before running web checks:
nvm use
corepack enable
yarn install --frozen-lockfile
YARN_IGNORE_ENGINES=1 is emergency-only for local debugging and is not part of normal workflow.
1) Start Postgres
docker compose -f deploy/docker-compose.yml up -d db
2) Start control plane
export DATABASE_URL=postgres://nanami:nanami@localhost:5432/nanami?sslmode=disable
export JWT_SECRET=change_me_super_secret
export APP_ENV=dev
export APP_MODE=community
go run ./apps/control-plane/cmd
Control plane listens on http://localhost:8080 by default.
3) Start WebUI and bootstrap admin
cd apps/webui
yarn install
CONTROL_PLANE_PROTOCOL=http CONTROL_PLANE_HOST=localhost CONTROL_PLANE_PORT=8080 yarn dev
Open http://localhost:3000 and complete bootstrap for the first admin account.
4) Create your first group and network
In WebUI:
- Go to Groups and create a group (for example,
platform). - Go to Networks and create a network (for example,
dev-eu). - Use a non-overlapping CIDR such as
10.42.0.0/16.
5) Start gateway-manager
Generate a join key with gateway_manager scope, then run:
export CONTROL_PLANE_INTERNAL_PROTOCOL=http
export CONTROL_PLANE_INTERNAL_HOST=localhost
export CONTROL_PLANE_INTERNAL_PORT=8080
export JOIN_KEY=<gateway-manager-join-key>
export TENANT_SLUG=default
export NODE_JOIN_KEY=node-secret-key
go run ./apps/gateway-manager/cmd
6) Register gateway-daemon
Generate a join key with gateway_daemon scope, then run:
export GATEWAY_MANAGER_INTERNAL_PROTOCOL=http
export GATEWAY_MANAGER_INTERNAL_HOST=localhost
export GATEWAY_MANAGER_INTERNAL_PORT=8081
export NODE_JOIN_KEY=node-secret-key
export CONTROL_PLANE_INTERNAL_PROTOCOL=http
export CONTROL_PLANE_INTERNAL_HOST=localhost
export CONTROL_PLANE_INTERNAL_PORT=8080
export GATEWAY_DAEMON_JOIN_KEY=<gateway-daemon-join-key>
export GATEWAY_HOST=<public-dns-host>
go run ./apps/gateway/cmd/gateway-daemon
For local Docker testing, you can also run the gateway profile from deploy/docker-compose.yml.
WireGuard UDP Port
In COMMUNITY mode, change the gateway WireGuard UDP port in Dashboard -> Gateways -> gateway details (WireGuard UDP Port).
Allowed pool is fixed to 51820-54000.
If wg_listen_port is unset, default base port is 51820.
Gateways run in single-interface mode by default, so one selected UDP port is active per gateway.
Community gateway-daemon uses host network mode in Docker deployments.
Forward the selected UDP port on your router/NAT to the gateway host
(example: WAN UDP 53535 -> gateway-host:53535).
If GATEWAY_HOST is DNS on Cloudflare, keep it DNS-only (proxied mode does not pass UDP).
If you use manual WireGuard configs, re-download after a gateway port change.
Manual WireGuard configs are Limited Mode: client-side AllowedIPs can be edited and are not trusted for security boundaries.
Nanami enforces tenant isolation server-side on gateways.
7) Add your first node
Two practical options:
- Use Connect in WebUI (manual WireGuard config flow).
- Call
POST /api/v1/nodes, fetchGET /api/v1/nodes/:id/wireguard/server-config, thenPOST /api/v1/nodes/:id/wireguard/public-keyfor rotate/regenerate.
Assign the node to the network you created in step 4.
8) Verify connectivity
In WebUI, confirm:
- network status is active,
- gateway and agent status is healthy,
- node appears online,
- handshake timestamps and tunnel counters update.
Then run a private-service reachability check between enrolled peers.
Tip
Roll out incrementally: validate one network and one gateway path first, then scale to additional groups and regions.
Next steps
- Read Architecture overview
- Learn Ingress and egress model
- Follow Self-hosted deployment guide