Self-hosting
Install wave-mesh
A wave consists of a control server with relay and database, which you run in your own Kubernetes cluster, and the client on every device. This guide walks through both.
Not public yet
The wave-mesh source code, container images and client binaries are not public yet. Write to us if you want to run wave-mesh yourself, and we will give you access.
Request accessRequirements
A Kubernetes cluster; a single server with k3s is enough. The cluster needs an ingress controller with TLS and a public IP address that accepts UDP on port
3478for STUN.Two names for the control server and the relay, for example
control.example.comandrelay.example.com.Optionally a DNS zone you own, for device names and certificates. Cloudflare, Hetzner, IONOS and INWX are supported; without credentials it still works, and you add TXT records yourself.
Control server, relay and database
Copy the
prodoverlay and adjust three places that belong together: the names iningress.yaml,WAVE_BASE_URLand the STUN address inWAVE_RELAYS. Login links and redirects are built fromWAVE_BASE_URL, so the name must match the ingress.secret.envholds the database password and connection address. If the container images are private, adockerconfig.jsonwith read access to GHCR goes next to it. Both files stay out of Git.$ cp -r deployment/server/overlays/prod deployment/server/overlays/mywave$ cd deployment/server/overlays/mywave$ cp secret.env.example secret.env # fill in, mode 600$ kubectl apply -k .Set the STUN address
The STUN address in
WAVE_RELAYSmust be an IP address, not a name. It is known once the relay's service has a public address. Enter it and apply the overlay again.$ kubectl -n wave-mesh get svc wave-relay-stunCreate the first account
There is deliberately no sign-up page: the operator creates accounts. The command asks for the password twice, at least twelve characters.
$ kubectl -n wave-mesh exec -it deploy/wave-control -- \bun apps/control/src/admin.ts set-password you@example.comInstall the client
The client is a single binary for Linux, macOS and Windows, each on amd64 and arm64.
installcopies it to/usr/local/bin, creates the groupwaveand starts the service and tray icon. Day-to-day use needs nosudoafter that.On Windows, extract the ZIP archive and run
wave.exe installin a console with administrator rights.$ tar xzf wave-linux-amd64.tar.gz$ sudo ./wave installLog in and connect
wave loginnames your control server and prints a link to log in. Thenwave upconnects, andwave statusshows live which path reaches each device. A device can join as many waves as you like.$ wave login https://control.example.com$ wave up$ wave statusNames and certificatesoptional
Give a wave a DNS suffix you own, and its devices get names under it and, if you like, Let's Encrypt certificates. The provider is set once per wave; after that
wave certfetches the certificate on the device, and the service renews it on its own. The private key never leaves the device.For a provider token the server needs
WAVE_DNS_SECRET(32 bytes, base64) to store the token encrypted. The default is Let's Encrypt's staging directory; real certificates come withWAVE_ACME_DIRECTORY.With the
manualprovider this works with any host, but then every renewal also needs a person to add the TXT record.$ kubectl -n wave-mesh exec -it deploy/wave-control -- \bun apps/control/src/admin.ts set-dns-provider mywave cloudflare$ wave cert --hook 'systemctl reload caddy'Services from a Kubernetes clusteroptional
A connector brings a cluster's internal services into the wave without an inbound port. It joins with a reusable key. After that a plain Ingress with
ingressClassName: waveis enough, and every device in the wave reaches the service by its name.$ kubectl -n wave-mesh exec deploy/wave-control -- \bun apps/control/src/admin.ts auth-key mywave connector --reusable$ cd deployment/cluster/overlays/example$ cp secret.env.example secret.env # paste the key$ kubectl apply -k .Updates
The service updates itself: the control server offers new releases, the client installs only what is signed with the release key, and rolls back on its own if the new build cannot reach a server. If you don't want to wait, install right away.
$ wave version$ wave update
Rather have it set up?
We install wave-mesh in your company's cloud, connect clusters and devices and, if you like, take care of updates and operations.
See pricing