digitalboard.core/roles/talk
Simon Bärlocher 51919829e3
fix(talk,coturn): correct vars file header (was 'httpbin')
Both new roles had 'vars file for httpbin' as the header comment in
vars/main.yml — copy-paste artefact from the httpbin role template.
Files are otherwise empty. Reviewer flagged both inline (PR review
comments 229 and 230).
2026-05-26 15:03:04 +02:00
..
defaults feat(talk/turn/signaling/hpb): add role for Talk with backend services 2026-05-22 01:10:56 +02:00
handlers feat(talk/turn/signaling/hpb): add role for Talk with backend services 2026-05-22 01:10:56 +02:00
meta feat(talk/turn/signaling/hpb): add role for Talk with backend services 2026-05-22 01:10:56 +02:00
tasks feat(talk/turn/signaling/hpb): add role for Talk with backend services 2026-05-22 01:10:56 +02:00
templates feat(talk/turn/signaling/hpb): add role for Talk with backend services 2026-05-22 01:10:56 +02:00
tests feat(talk/turn/signaling/hpb): add role for Talk with backend services 2026-05-22 01:10:56 +02:00
vars fix(talk,coturn): correct vars file header (was 'httpbin') 2026-05-26 15:03:04 +02:00
README.md feat(talk/turn/signaling/hpb): add role for Talk with backend services 2026-05-22 01:10:56 +02:00

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:

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.)