Your own nodes (BYOC)
Run media nodes on your machines — bare metal, your cloud account, a LAN event — with Aurix Cloud as the control plane for $39 per node per month.
What runs where#
| On your machine | Aurix Cloud |
|---|---|
aurix-server media node as your own voice cell: its own Postgres and Redis (Docker), Caddy for TLS, Opus, TURN relay, the node agent | Registry, projects, keys, tokens, routing, usage, console, webhooks, the ladder |
Audio, sessions and channel state never leave your machines. The control plane reaches your cell over its public HTTPS endpoint (to create the project's app there, mint tokens and read usage); the node itself only makes outbound calls (heartbeat, updates). Nothing is opened on our side for you and nothing of ours — no database, no cache — is exposed to your node.
Requirements#
- Linux x86_64 or arm64 (Ubuntu 22.04+, Debian 12+, Rocky 9+), systemd, root for the install, 2 vCPU / 2 GB RAM minimum. Docker is installed by the installer if missing.
- A public IP. Inbound TCP 80 and 443 (TLS certificate, API and WebSocket signalling), UDP 10000 media, optionally UDP/TCP 3478 + UDP 49160–49200 for TURN.
- Outbound HTTPS to the control plane, GitHub releases and Docker Hub (images), Let's Encrypt.
- Optional: your own DNS name pointing at the machine. Without one the node gets
<node-id>.<region>.cell.aurix.run(for exampleabe1adfa.eu-central.cell.aurix.run) — the record is created when the node joins and removed with the node, nothing to set up.
Connect a node#
In the console open Nodes (first item after Live; a your-infrastructure project shows the connect screen there until a node runs). Pick the region — any of the nine (US East/West, EU Central/West, Asia Pacific, South America, Australia, Middle East, Africa); players of that region are routed to your node; the machine can be anywhere — and, if you have one, the hostname. You get a one-time command:
curl -fsSL https://aurix.run/install/node.sh | sudo AURIX_CLOUD_NODE_ID=… AURIX_CLOUD_JOIN_TOKEN=… bash
# with your own DNS name:
curl -fsSL https://aurix.run/install/node.sh | sudo AURIX_CLOUD_NODE_ID=… AURIX_CLOUD_JOIN_TOKEN=… AURIX_NODE_HOSTNAME=voice.example.com bashWhat it does, in order: downloads the current aurix-server release (checksum-verified) and the node agent; starts aurix-postgres and aurix-redis containers bound to loopback; starts aurix-caddy (host network) which obtains the Let's Encrypt certificate for the hostname and proxies https://<host> → API and wss://<host>/ws → signalling; writes /etc/aurix/server.env with generated secrets and systemd units; starts aurix-server (migrations run on first start); creates the operator account the control plane uses; waits until https://<host>/health answers; reports the cell to the control plane. The control plane verifies the endpoint and credentials, registers the cell for the region, creates the project's app on it and marks the node running. The Nodes page follows the states live: provisioning (command not run yet) → joining (machine reported in) → running. Two to three minutes on a fresh box; the token works once and the window is one hour.
If the command was lost or the attempt failed, Nodes → ⋯ → Show install command issues a fresh token for the same node; Forget node removes an attempt that never joined.
Generated secrets live in /etc/aurix/standalone.json (0600) and are reused when the command is re-run on the same machine, so the database survives a reinstall.
Updates#
Nothing is pinned by default: the control plane follows the latest Aurix release (GitHub aurix-voice/aurix, checked every 15 minutes) — a fresh node installs the current server and running agents are told to update; updates drain the node, swap the binary and rejoin. Operators of the control plane can freeze a release with agent.pin_version.
Removing a node#
Drain it under Nodes (players move off, nobody is disconnected), the agent stops the media node and reports stopped; billing is pro-rated to the hour. When the last node of a region is gone the project's app on that cell is forgotten too — the next node you connect in that region re-creates it, with new SDK keys for that region.
What is billed#
$39 per node per month, accrued hourly while the node is running — nothing else from us. Your hosting bill is yours, and so is everything that runs on your machine: traffic and TURN are not metered, recording storage and speech-to-text are included. See What you pay for.
Sizing your machines#
The media node is CPU-bound only when it mixes or denoises. For plain forwarding a 2 vCPU machine carries roughly what our Small node does (500 participants); scale with the numbers in Large servers & scale: ~1.5 % of a core per server-denoised uplink, one decoder per speaker and one encoder per mixed downlink for server mixing. Network matters more than CPU — budget 1 Mbit/s per 10 participants each way. Postgres and Redis on the same box need well under a core at this scale.
Ports and firewall#
| Port | Protocol | Purpose | Must be public |
|---|---|---|---|
| 80, 443 | TCP | Let's Encrypt validation; HTTPS API and WebSocket signalling (Caddy) | yes |
| 10000 | UDP | native media (AURX over UDP / QUIC) | yes |
| 4443 | UDP | WebTransport for browsers (hash-pinned certificate, no DNS needed) | yes, if enabled |
| 3478 | UDP + TCP | TURN / STUN | yes, if enabled |
| 49160–49200 | UDP | TURN relay range | yes, if enabled |
| 5432, 6379 | TCP | Postgres, Redis of the region's first node (password-protected) | only from your other nodes — firewall them (see Several nodes) |
| 8080, 8081, 9464 | TCP | API, WebSocket, metrics behind Caddy | no — loopback / internal |
Outbound: HTTPS to the control plane, GitHub, Docker Hub and Let's Encrypt. Nothing inbound from us is required; the agent polls.
Several nodes#
Add as many machines per region as you like — Nodes → Connect another node, same flow. The first node of a region holds the cell's Postgres and Redis; further nodes of that region receive their addresses from the control plane at install and join the same cell automatically (shared sessions, mirrors and failover between your nodes). Each node still terminates its own TLS and serves players directly. Nodes in different regions are independent cells; channels of one project may span them through cascade. Mixed fleets (your nodes plus Cloud nodes) are allowed in one project.
Because the first node's database is reachable by the others, its ports 5432/6379 TCP are published with strong generated passwords (SCRAM for Postgres, requirepass for Redis). Restrict them to the IPs of your own nodes in the machine's firewall or security group.
Monitoring#
Each node exposes Prometheus metrics (aurix_sessions, aurix_channels, aurix_media_bytes_total, aurix_turn_bytes_total, aurix_mixer_cpu_seconds_total, …) on port 9464 and ships the same counters to the control plane with its heartbeat, so the Usage page is identical for your nodes and ours. Logs are journald (journalctl -u aurix-server -u aurix-node-agent), size-limited by the agent; docker logs aurix-caddy for certificate issues.
Troubleshooting#
- Stuck in
joining, agent prints "waiting for the TLS certificate" — the hostname does not resolve to this machine or TCP 80/443 are blocked.docker logs aurix-caddyshows the ACME error. aurix-serverrestarts —journalctl -u aurix-server -n 50;docker psshould listaurix-postgres(healthy) andaurix-redis.failed: did not join within 60 minutes— re-run with a fresh command (Nodes → Show install command); the machine keeps its database.
When to prefer BYOC#
- You need a jurisdiction or provider we do not offer, or data must stay on your infrastructure.
- LAN or offline events — the node works without the control plane for existing tokens; it needs it back only to mint new ones.
- You already pay for idle servers next to your game servers; voice on the same rack means one hop.