Nextcloud Talk is the audio, video, and chat app built into Nextcloud, used by hospitals, governments, universities, and self-hosters who want full control over their communication stack. Out of the box, Talk works fine on a single LAN, but the first time a user joins from a hotel, a hospital network, or a phone on cellular data, the call mysteriously fails to connect. The fix is the same as for every WebRTC application: a properly configured TURN server. This guide walks through exactly how to wire TURN into Nextcloud Talk, both with and without the High Performance Backend, and how to verify that the relay path actually works.

What Is Nextcloud Talk?

Nextcloud Talk is a self-hosted real-time communication app that runs as part of a Nextcloud installation. It uses WebRTC for media, the Nextcloud user database for identity, and Nextcloud's own server for chat persistence. A standard Talk installation has three pieces that matter when configuring TURN:

  • The Talk app: The Nextcloud app itself, which provides the web UI, chat, and signaling for small calls.
  • STUN server: Used by clients to discover their public IP and port behind NAT.
  • TURN server: Relays media when peers cannot reach each other directly because of firewalls, symmetric NAT, or blocked UDP.

For deployments expecting calls with three or more participants, there is a fourth piece: the High Performance Backend (HPB), a separate signaling server and WebRTC media gateway developed by Struktur AG and open-sourced as the nextcloud-spreed-signaling project. HPB is optional for small deployments and required for any reasonable scale.

Why Nextcloud Talk Needs a TURN Server

By default Nextcloud Talk attempts direct peer-to-peer connections between participants. That works fine on a single LAN or between users on permissive home connections. It breaks in the situations every WebRTC deployment eventually encounters:

  • Carrier-grade NAT (CGNAT): Most mobile carriers run symmetric NAT, where the public address one peer discovers via STUN is useless to a different peer.
  • Corporate firewalls: Many enterprise networks block outbound UDP entirely.
  • Public Wi-Fi: Hotels, hospitals, and conference venues frequently block everything except HTTP and HTTPS.
  • Restrictive guest networks: Locked-down networks often allow only port 443 outbound.

Without a TURN server, all of these users get a call that rings forever and never connects. Nextcloud's own documentation puts it plainly: a TURN server is needed so people can join calls from limited networks and mobile networks. Industry estimates put the share of WebRTC connections that need TURN at roughly 10 to 25 percent.

STUN vs TURN in Nextcloud Talk

The Talk admin panel separates STUN and TURN into two distinct settings, and it is worth understanding why:

  • STUN is a lightweight protocol that returns a client's public IP and port. It is free to run and the cost is essentially zero. Talk uses STUN to help peers discover routable addresses for direct connections.
  • TURN is a relay. The media flows through a TURN server, which means real bandwidth cost and the need for a server with a public IP. Talk falls back to TURN only when direct connections cannot be established.

You want both configured. STUN handles the easy cases for free; TURN rescues the hard ones.

Configuring TURN via the Admin UI

The standard way to configure TURN for Nextcloud Talk is through the Nextcloud admin web interface. No occ commands or direct config.php edits are needed.

Step 1: Open Talk admin settings

Log in as an admin user, then navigate to:

Admin settings → Talk

You will see sections for STUN servers, TURN servers, and (if installed) High Performance Backend.

Step 2: Add a STUN server

In the STUN servers field, add an entry in the bare host:port format. Do not include any stun:// prefix.

stun.expressturn.com:3478

Click the plus sign to add the entry. You can list multiple STUN servers for redundancy; starting with Talk 12, all listed STUN and TURN servers are returned to the client.

Step 3: Add a TURN server

Below the STUN section, click to add a TURN server. There are several fields:

  • Schemes: Dropdown for turn:, turns:, or both. Choose turn: and turns: so clients can use either plain or TLS-wrapped TURN depending on the network.
  • Server URL: The bare host:port for your TURN endpoint, without any protocol prefix. Example: free.expressturn.com:3478 for the standard UDP/TCP port.
  • TURN secret: The shared secret used to generate time-limited credentials. This is the same static-auth-secret value your TURN server uses for the REST API authentication scheme.
  • Protocols: Dropdown for UDP, TCP, or both. Choose UDP and TCP so ICE can pick the working transport.

Click the checkmark to save. Nextcloud Talk does not store long-term username and password credentials directly in the admin UI; it expects a shared-secret TURN server that supports the time-limited REST API authentication scheme (specified in draft-uberti-behave-turn-rest). Most managed TURN providers including ExpressTURN support this scheme alongside long-term credentials.

Step 4: Use the built-in test button

Starting with recent Talk versions, each TURN entry has a Test this server button. Click it. A green checkmark confirms the server is reachable and the credentials are valid. A red error means the URL, port, or secret is wrong, or that your TURN provider does not support the shared-secret scheme.

Configuring TURN with the High Performance Backend

If your deployment runs the High Performance Backend (HPB), you have a second place where TURN settings live: the HPB's own configuration. HPB needs to know about TURN so that the SFU can hand out relay candidates to clients during signaling.

In most setups, HPB reads its TURN configuration from a config file (typically server.conf) in a [turn] section:

[turn]
apikey = your-api-key
secret = YOUR_TURN_SHARED_SECRET
servers = turn:free.expressturn.com:3478?transport=udp,turn:free.expressturn.com:3478?transport=tcp

The secret here is the same shared secret you used in the Nextcloud admin UI. The servers list should match what the admin UI knows about. Keeping the two aligned avoids the confusing failure mode where clients see one set of TURN URLs and the SFU expects another.

If you are running the official AIO (All-in-One) image for HPB, the TURN secret is passed at container start as an environment variable:

docker run \
  --name=nextcloud-talk-hpb \
  --restart=always \
  --detach \
  -e NC_DOMAIN=nextcloud.example.com \
  -e TALK_PORT=3478 \
  -e TURN_SECRET=YOUR_TURN_SHARED_SECRET \
  -e SIGNALING_SECRET=YOUR_SIGNALING_SECRET \
  -e INTERNAL_SECRET=YOUR_INTERNAL_SECRET \
  -p 8080:8081 \
  ghcr.io/nextcloud-releases/aio-talk:latest

Reload HPB after any config change and confirm there are no errors in the logs.

Routing TURN Through Port 443

Default TURN ports are 3478 (UDP and TCP) and 5349 (TLS). Some restrictive networks block everything except 443. To reach those users, you want a TURN endpoint reachable on port 443 over TLS.

The simplest way is to use a managed TURN provider that already exposes a TLS endpoint on port 443, and list it in the Nextcloud admin UI as a separate TURN entry with the turns: scheme. (The ExpressTURN free tier serves plain turn: on port 3478 only; a 443 TLS endpoint requires self-hosting coturn as described below or a provider that offers one.)

If you are self-hosting coturn on the same machine that runs Nextcloud, the Nextcloud Talk documentation recommends configuring coturn to listen on port 443 directly, on a separate IP address from the Nextcloud web server (since both need port 443). The same rule applies if you are running the High Performance Backend on the same host: HPB uses media ports 20000 to 40000 by default and needs its own IP address or its own server when colocated with TURN. For installations where giving each service its own IP is not possible, an nginx stream module with SNI-based routing can fan port 443 traffic between the web UI and the TURN endpoint.

Testing Your TURN Configuration

Three ways to verify TURN is actually being used, in order of effort:

1. The admin UI Test button

Click Test this server next to each TURN entry. Confirms reachability and credentials.

2. turnutils_uclient from the command line

If you have coturn's client utilities installed, run a direct TURN allocation test:

turnutils_uclient -p 3478 -W YOUR_TURN_SHARED_SECRET -v -y free.expressturn.com

A successful run prints allocation messages and a relayed address. A failure prints an authentication or connectivity error. Add the -t flag to test the TCP transport instead of the default UDP:

turnutils_uclient -t -p 3478 -W YOUR_TURN_SHARED_SECRET -v -y free.expressturn.com

3. chrome://webrtc-internals during a call

Start a Talk call. In another Chrome tab, open chrome://webrtc-internals. Find the active RTCPeerConnection and look at the selected candidate pair. With direct connectivity, you will see host or srflx. When TURN is used, the type is relay. If you want to confirm TURN works end to end, force-relay one of two ways:

Via the browser console (no config edit, but only lasts for the current page):

OCA.Talk.SimpleWebRTC.webrtc.config.peerConnectionConfig.iceTransportPolicy = 'relay'

Paste this into the browser's DevTools console after opening Talk but before joining a call. Every connection in this session is forced through TURN.

Via config.php (persistent, for staging environments):

'talk_force_turn' => true

This is a config.php key recognized by Talk that forces every connection through the relay for all users. Remove it after testing.

Bandwidth Considerations

Nextcloud Talk's bandwidth profile depends on whether the High Performance Backend is in use:

  • A 2-person 720p P2P call relayed: roughly 675 MB per relayed hour, combined both directions.
  • An audio-only Opus call: roughly 30 MB per relayed hour.
  • An HPB-bridged 4-person call where one participant needs TURN: roughly 1 to 2 GB per relayed hour, since HPB pushes a combined stream to that participant.

For a small organization running Talk for a few hundred meeting-hours per month, total TURN bandwidth typically lands in the tens of gigabytes. The free tier on most managed TURN services covers that comfortably. Once you cross 1 TB of relayed traffic per month, flat-pricing providers like ExpressTURN ($9/month for 5 TB) start beating metered providers by a significant margin.

Best Practices for Nextcloud Talk TURN

  • Always configure both STUN and TURN: STUN handles the easy cases cheaply, TURN handles the hard ones.
  • List multiple TURN protocols: Choose UDP and TCP and turn: and turns: so ICE can pick whichever works on each user's network.
  • Use a port 443 TLS TURN endpoint: Required to rescue users on locked-down corporate, hospital, and hotel networks.
  • Keep HPB and admin UI TURN config aligned: If both are configured, they should reference the same TURN servers and shared secret.
  • Test from a real mobile network: Wi-Fi will not reproduce CGNAT. Cellular testing is the only way to confirm your TURN setup actually works for the users who need it most.
  • Use the built-in test button: The admin UI's Test this server button is the fastest sanity check whenever you change TURN settings.
  • Monitor TURN bandwidth: Unexpected spikes can indicate broken signaling, a misconfigured HPB, or unusual user patterns.

Wrapping Up

A default Nextcloud Talk install works on a LAN and breaks for a meaningful percentage of remote users. Configuring STUN and TURN through the admin UI takes a few minutes, fixes the problem for nearly everyone, and is the single highest-impact change you can make to a Talk deployment that serves users outside your office network. List both STUN and TURN, list multiple transports, expose a port 443 TLS endpoint, and verify with the built-in test button before users do the verification for you.