Voice chat setup

Turning voice on for a self-hosted server: the two transports, the HTTPS requirement, the media port, the announced address behind NAT or Docker, a voice domain and Cloudflare, the STUN and TURN broker for mesh, and the rules you can switch on per campaign.

Server

Voice runs on the server itself: no third-party service, no account, no audio leaving your network unless the relays through . It is off by default on a self-hosted server. Two things are easy to miss: browsers need for the microphone, and the built-in needs one open port that cannot go through your .

Turn it on

Admin, Server settings, Voice chat, Enable, or VOICE_ENABLED=1. Then pick the transport.

Two transports

(SFU)
How it worksThe server receives every microphone and forwards to every listener, in process.Browsers connect to each other; the server only referees.
PortsOne port, UDP and TCP, default 44444, open straight to the host.None. Works through a .
Enforced rulesFloor enforcement, side rooms, speaking indicator, proximity gains applied by the server.Proximity gains applied by each listener; no speaking indicator, floor enforcement or side rooms.
ScaleAny table.Small tables; each device sends to every other.
Best forA server with a public address and a firewall you control.A tunnel-hosted server, or a home server where opening a port is not an option.

Worlds hosted from the desktop and Android apps use mesh and manage this for you.

HTTPS

Browsers grant microphone access only on or on localhost. A single machine playing on localhost works as-is; anyone else needs the server behind a with a certificate. The apps count as a secure context, so a table entirely on the desktop and Android apps can use voice on a plain-http LAN server. See Reverse proxy and HTTPS.

The media port

  • Open 44444 (or VOICE_RTC_PORT) for both UDP and TCP on the host firewall and, behind a router, forward it to the host. It is one port, not a range, however many tables run. TCP on the same port is the fallback for networks that block UDP.
  • Audio is not HTTP: the port cannot be proxied by or Caddy and cannot go through Cloudflare's proxy or .
  • publishes the port for both protocols in the compose file already.

The announced address

Behind NAT or inside , the server must be told what address to hand to clients, or it announces its private one and every call "connects to silence". Set in the or VOICE_ANNOUNCED_IP to your public IP, or Voice domain / VOICE_DOMAIN to a hostname, which wins when set. A voice domain must be a plain DNS record: a Cloudflare-proxied (orange cloud) name resolves to Cloudflare, which does not carry UDP. The announced address is visible to players in their browser's WebRTC internals; that is inherent to the transport.

Mesh: STUN and TURN

calls need to find each other and, on strict networks, a TURN relay. By default the server points clients at the project's , which hands out Cloudflare STUN always and short-lived TURN credentials within a monthly budget. Set ODM_ICE_BROKER_URL=off to use public STUN only, or point it at your own broker.

Per-campaign rules

All in the , all off by default except turn-taking shown: turn-taking (ignored, shown, enforced), proximity with 30 feet of hearing, a 5-foot and a 120-foot shout, walls that muffle, downed characters going deaf, and side rooms the Dungeon Master runs. The Dungeon Master is never muted. A member the has muted is silent on the call too. A raised hand is a request only. A server restart ends every call; players rejoin from the dock.

Checking

SymptomCause
Microphone button does nothing in a browserPlain http. or localhost only.
Everyone joins, nobody hears anything ()The is closed, or the is unset or wrong.
Works on the LAN, silent from outsideThe port is not forwarded at the router, or the voice domain is Cloudflare-proxied.
call fails for one player on mobile data was not available; check the setting, and that the budget is not exhausted.

Checked against desktop and Android app 0.17.2 and server 0.26.2 on 2026-10-11. Something wrong or missing? Open an issue.

Download · v0.17.2
Server app · v0.26.2

Optional. Runs the table for a whole group on one machine that stays on. Everyone else just installs the app.

Free & open source · MIT licensed · served from GitHub releases