Files
computer-playbook/roles/web-app-opentalk/README.md
T
kevinveenbirkenbachandClaude Opus 5.5 09b594b102 fix(web-app-opentalk): run product version 26.2.1 and follow its bundle
The web frontend, the controller and the recorder were pinned to v2.9.0,
v0.34.1 and v0.16.2, a mix of the 26.2 and the 26.1 line, and excluded
from the image updater with nocheck: docker-version. Nothing moved them.

They now sit on the set OpenTalk publishes as product version 26.2.1 in
ot-setup (v2.9.2, v0.34.5, v0.17.5), and each pin names that bundle as its
version source, so the three move together with the next product version.
The markers are gone.

Recorder v0.17 no longer reads recording jobs from RabbitMQ or logs in
with an OIDC service account. The controller starts recordings on the
recorder's REST API and both sides authenticate with API keys:
recorder.toml.j2 names the controller and the recorder's own key,
controller.toml.j2 enables roomserver.modules.recording, the secret
recorder_api_secret replaces recorder_oidc_client_secret and the Keycloak
client opentalk-recorder is no longer created.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-08 10:30:48 +02:00

7.1 KiB

OpenTalk

Description

OpenTalk is a sovereign open-source video conferencing platform developed by the Heinlein Group. It combines a Rust controller, a LiveKit-based WebRTC media server, and a React web frontend.

Overview

This role deploys the OpenTalk stack using Docker Compose and exposes the web frontend at open.talk.{{ DOMAIN_PRIMARY }} through the central reverse proxy. It runs the Rust controller, the LiveKit WebRTC media server, the React web frontend, a dedicated Redis, a dedicated MinIO bucket for controller assets, a RabbitMQ broker, and the OpenTalk recorder for meeting MP4 archives. The deployment integrates with the shared Keycloak realm via OIDC and reuses svc-db-postgres and web-svc-coturn for relational data and STUN/TURN. For identity wiring details see IAM.md and LDAP.md.

Cosmos

The diagram places OpenTalk in the Infinito.Nexus cosmos: the components it deploys (capabilities), the central services it consumes (dependencies), and its outward reach (federation and bridged external networks).

flowchart LR
    subgraph deps [Dependencies]
        dep_svc_bkp_volume_2_local["svc-bkp-volume-2-local 💻"]
        dep_svc_db_openldap["svc-db-openldap 🐳🐝"]
        dep_svc_db_postgres["svc-db-postgres 🐳🐝"]
        dep_svc_db_redis["svc-db-redis 🐳🐝"]
        dep_web_app_dashboard["web-app-dashboard 🐳🐝"]
        dep_web_app_keycloak["web-app-keycloak 🐳🐝"]
        dep_web_app_matomo["web-app-matomo 🐳🐝"]
        dep_web_app_prometheus["web-app-prometheus 🐳🐝"]
        dep_web_app_seaweedfs["web-app-seaweedfs 🐳🐝"]
        dep_web_app_stalwart["web-app-stalwart 🐳🐝"]
        dep_web_svc_coturn["web-svc-coturn 🐳🐝"]
        dep_web_svc_css["web-svc-css 💻"]
        dep_web_svc_logout["web-svc-logout 🐳🐝"]
    end
    subgraph role [web-app-opentalk 🐳🐝]
        svc_sso["sso"]
        svc_ldap["ldap ❌"]
        svc_logout["logout"]
        svc_dashboard["dashboard"]
        svc_matomo["matomo"]
        svc_email["email"]
        svc_coturn["coturn"]
        svc_postgres["postgres"]
        svc_redis["redis"]
        svc_opentalk["opentalk"]
        svc_controller["controller"]
        svc_livekit["livekit"]
        svc_minio["minio ❌"]
        svc_seaweedfs["seaweedfs"]
        svc_rabbit["rabbit"]
        svc_recorder["recorder"]
        svc_css["css"]
        svc_prometheus["prometheus"]
        svc_tor["tor ❌"]
        svc_container_backup["container_backup"]
    end
    dep_svc_bkp_volume_2_local -. "0..1" .-> svc_container_backup
    dep_svc_db_openldap -- "0..0" --> svc_ldap
    dep_svc_db_postgres -. "0..1" .-> svc_postgres
    dep_svc_db_redis -. "0..1" .-> svc_redis
    dep_web_app_dashboard -. "0..1" .-> svc_dashboard
    dep_web_app_keycloak -- "1:1" --> svc_sso
    dep_web_app_matomo -. "0..1" .-> svc_matomo
    dep_web_app_prometheus -. "0..1" .-> svc_prometheus
    dep_web_app_seaweedfs -. "0..1" .-> svc_seaweedfs
    dep_web_app_stalwart -. "0..1" .-> svc_email
    dep_web_svc_coturn -. "0..1" .-> svc_coturn
    dep_web_svc_css -. "0..1" .-> svc_css
    dep_web_svc_logout -. "0..1" .-> svc_logout
    linkStyle 1 stroke:red;

Solid 1:1 edges are fixed relationships; dashed 0..1 edges are conditional (enabled only in matching deployments); red 0..0 edges are turned off in this role. Node markers show the role's deploy modes (💻 host, 🐳 compose, 🐝 swarm); ❌ marks a service that is explicitly turned off, and ⚙️ an Ansible role dependency declared in meta/main.yml.

Features

  • Sovereign Video Conferencing: Self-host meetings under your own domain without external SaaS dependency.
  • WebRTC Media via LiveKit: Real-time audio, video, and screen sharing through a high-performance SFU.
  • Single Sign-On: Frontend and controller share one Keycloak client and realm.
  • Federated User Lookup: Invitee search resolves through the Keycloak admin Web API, so any user federated from OpenLDAP into Keycloak becomes findable inside OpenTalk.
  • OpenCloud File Integration: Pick files from OpenCloud in a meeting without re-authenticating when web-app-opencloud is deployed alongside.
  • Meeting Recordings: The controller starts recordings on a dedicated recorder over its REST API, and the recorder stores MP4 archives in MinIO.
  • Shared Infrastructure: Reuses svc-db-postgres for relational data and web-svc-coturn for STUN and TURN.

Quick Setup

Development

Clone, set up the workstation, and deploy OpenTalk onto the local stack:

git clone https://github.com/infinito-nexus/core.git
cd core
make onboard
make compose-deploy mode=reinstall apps=web-app-opentalk full_cycle=false

Production

Run the published image to provision the inventory and deploy OpenTalk to a managed server (the mounted volume persists the inventory):

APP=web-app-opentalk
HOST=<your-server>
DOMAIN=<your-domain>
TLS_MODE=self_signed
SSH_PUBLIC_KEY="<your-ssh-public-key>"

docker run --rm -it \
  -v "$PWD/inventories:/etc/infinito.nexus/inventories" \
  -e APP="$APP" -e HOST="$HOST" -e DOMAIN="$DOMAIN" -e TLS_MODE="$TLS_MODE" -e SSH_PUBLIC_KEY="$SSH_PUBLIC_KEY" \
  ghcr.io/infinito-nexus/core/debian bash -c '
    INVENTORY=/etc/infinito.nexus/inventories/production
    infinito administration inventory provision "$INVENTORY" \
      --inventory-file "$INVENTORY/devices.yml" \
      --host "$HOST" \
      --include "$APP" \
      --vars "{\"TLS_MODE\": \"$TLS_MODE\", \"DOMAIN_PRIMARY\": \"$DOMAIN\", \"users\": {\"administrator\": {\"authorized_keys\": [\"$SSH_PUBLIC_KEY\"]}}}" &&
    infinito administration deploy dedicated "$INVENTORY/devices.yml" \
      --password-file "$INVENTORY/.password" \
      --diff -vv'

Developer Notes

See IAM.md for the OIDC and Keycloak admin Web API setup, and LDAP.md for the LDAP federation chain. Pending follow-up work is tracked in TODO.md.

Further Resources

Persona contract opt-outs

The shared biber and administrator persona helpers are declared blocked in templates/playwright.env.j2. The OpenTalk frontend is a public-client OIDC single-page app — the container env carries nothing but the issuer and the client id, there is no server-side session and no HTML login form — so the role drives it with its own redirect-racing helper keyed on LOGIN_* / BIBER_* instead of the ADMIN_* pair the shared helper expects, and the browser-side session leaves the contract's in-app logout leg without a target. Both personas' Keycloak → dashboard chain is covered by files/playwright/test-sso-login.js.

Credits

Implemented by Kevin Veen-Birkenbach. Part of the Infinito.Nexus Project and maintained by Kevin Veen-Birkenbach. Licensed under the Infinito.Nexus Community License (Non-Commercial).