feat(talk/turn/signaling/hpb): add role for Talk with backend services

This commit is contained in:
Tobias Wüst 2026-05-22 01:10:56 +02:00
parent 78095cca1d
commit 27255a4bfa
25 changed files with 930 additions and 0 deletions

78
roles/talk/README.md Normal file
View file

@ -0,0 +1,78 @@
# talk
Deploys the Nextcloud Talk High Performance Backend (HPB) stack:
- `nextcloud-spreed-signaling` (Strukturag)
- `janus-gateway` (canyan build, WebRTC MCU)
- `nats` (internal message broker)
Designed to be paired with the `digitalboard.core.coturn` role (TURN/STUN) and registered in
Nextcloud via the new `digitalboard.core.nextcloud` `talk.yml` task.
## Required variables
| Variable | Description |
|---|---|
| `talk_domain` | Public host name (e.g. `signaling.digitalboard.ch`) |
| `talk_nextcloud_url` | Base URL of the Nextcloud instance the HPB talks back to |
| `talk_janus_public_ip` | Public IP used by Janus for ICE candidate gathering (nat_1_1_mapping) |
| `talk_backend_secret` | HMAC secret shared with Nextcloud Talk; loaded from `secrets/{host}/talk_backend_secret` |
| `talk_turn_secret` | Shared secret with coturn; loaded from `secrets/{host}/talk_turn_secret` (must equal `coturn_static_auth_secret`) |
| `talk_session_hashkey` | 32-byte hex; loaded from `secrets/{host}/talk_session_hashkey` |
| `talk_session_blockkey` | 32-byte hex; loaded from `secrets/{host}/talk_session_blockkey` |
## Important variables
| Variable | Default | Description |
|---|---|---|
| `talk_internal_domain` | `""` | Optional split-horizon FQDN (matches the second SAN on the coturn cert) |
| `talk_turn_servers` | `turns:.../443?transport=tcp,turn:.../443` | Comma-separated TURN URI list passed to the signaling server |
| `talk_turn_realm` | `stun.example.test` | Realm advertised to clients |
| `talk_janus_stun_server` | `stun.int.example.test` | STUN endpoint Janus uses for its own ICE; default points at the internal coturn name |
| `talk_janus_rtp_port_min/max` | `20000`/`21000` | UDP/TCP relay range opened on the Janus container |
| `talk_nextcloud_extra_host_ip` | `""` | Optional pin: bind the Nextcloud FQDN to a specific backend IP (bypasses hairpin/SNI) |
| `talk_signaling_image` | `strukturag/nextcloud-spreed-signaling:1.3.4` | Pinned |
| `talk_janus_image` | `canyan/janus-gateway:1.2.4` | Pinned |
| `talk_nats_image` | `nats:2.10-alpine` | Pinned |
All defaults can be overridden per host_vars. The configurable image variables exist explicitly because
this stack is still under active development upstream and you may want to roll forward independently.
## Secrets
The role expects these files under `playbooks/secrets/{{ inventory_hostname }}/`, mode 0600:
```
talk_backend_secret # shared with Nextcloud Talk app (HPB shared secret)
talk_turn_secret # = coturn_static_auth_secret on the TURN host
talk_session_hashkey # 32-byte hex (openssl rand -hex 32)
talk_session_blockkey # 32-byte hex (openssl rand -hex 32)
```
If you prefer a different secret store, override the variables directly in host_vars.
## What gets registered in Nextcloud
The matching `digitalboard.core.nextcloud` task `talk.yml` runs:
- `php occ talk:signaling:add <talk_domain> <talk_backend_secret>` — register HPB
- `php occ talk:turn:add` for each entry in `nextcloud_talk_turn_servers` — register TURN
That part lives in the **nextcloud** role and runs when `nextcloud_enable_talk: true`.
## Traefik
The role assumes a `digitalboard.core.traefik` instance in `backend` mode runs on the same host
(picks up Docker container labels). The public `talk_domain` then needs to be exposed via the
**DMZ Traefik**, by adding an entry to `traefik_dmz_exposed_services` in the signaling host's
`host_vars`:
```yaml
traefik_dmz_exposed_services:
- name: signaling
domain: signaling.digitalboard.ch
port: 443
protocol: https
```
(The DMZ proxy aggregates exposed services from all `backend_servers` host_vars.)