Updating to OpenTalk Controller v0.34.0
Controller v0.34 reworks the configuration file significantly. The roomserver
configuration became mandatory and now owns most of the media- and
feature-related settings that previously lived in their own top-level tables.
This guide lists every breaking change when upgrading from v0.33 to v0.34
and shows how to adapt an existing deployment. Most changes affect the
controller.toml settings file, but the CLI and exported metrics changed as
well.
Before you start, back up your current
controller.toml.
Overview of breaking changes
- The
[roomserver]section is now required. - The
[roomserver]section gained a mandatorykindfield (externalorinternal). - The roomserver
urlkey was renamed toservice_url. - Media and feature settings moved under
[roomserver.modules.*]:[livekit]→[roomserver.modules.livekit][etherpad]→[roomserver.modules.meeting_notes][spacedeck]→[roomserver.modules.whiteboard][subroom_audio]→[roomserver.modules.subroom_audio]
- The
[livekit],[etherpad],[spacedeck],[subroom_audio],[authz]and[websocket_rate_limit]top-level tables were removed. service_api_keysunder[http]is now required (the roomserver uses it).- The
aclandfix-aclCLI subcommands were removed. - The
kustos_enforce_execution_time_secandkustos_load_policy_execution_timemetrics were removed. - The signaling metrics are now provided by the roomserver and some of the metrics have changed.
1. Add the mandatory [roomserver] section
In v0.33 the roomserver was optional and only used when running an external
roomserver service. In v0.34 it is mandatory and defines how signaling and
media are handled.
Set kind to external if you run a separate roomserver service (this matches
the previous behavior), or internal to run the roomserver embedded in the
controller process.
Previous (v0.33)
#[roomserver]
#url = "http://localhost:11333"
#api_key = { id = "roomserver", secret = "secret" }
New (v0.34) — external roomserver only
[roomserver]
# Whether the roomserver runs embedded in the controller (internal) or as an external service.
kind = "external"
# The URL the controller uses for requests to the roomserver.
# (previously named `url`)
service_url = "http://localhost:11333"
# The roomservers API key id and secret.
api_key = { id = "roomserver", secret = "secret" }
Note the rename from
urltoservice_url.
If you choose kind = "internal", the additional optional sections
[roomserver.conference], [roomserver.defaults] and
[roomserver.reports.typst] become relevant. See the example config for
details.
2. Add the mandatory service_api_keys under [http]
The roomserver authenticates against the controller using these keys, so the
value is now required. Uncomment (or add) it under [http]:
[http]
service_api_keys = [{ "id" = "controller", "secret" = "secret" }]
Generate a random secret with:
openssl rand -hex 32
3. Move media/feature settings into [roomserver.modules.*]
A module is enabled by adding its [roomserver.modules.<module>] table. Some
modules need extra fields, others are enabled by adding their (otherwise empty)
table. Omit the table to keep a module disabled.
The livekit and echo modules are required for a video conference and should
not be deactivated.
LiveKit
[livekit] → [roomserver.modules.livekit]
Previous:
[livekit]
api_key = "your-livekit-api-key"
api_secret = "your-livekit-api-secret"
public_url = "wss://url.to.your.livekit.server"
service_url = "https://localhost:7880"
New:
[roomserver.modules.livekit]
api_key = "your-livekit-api-key"
api_secret = "your-livekit-api-secret"
public_url = "wss://url.to.your.livekit.server"
service_url = "https://localhost:7880"
Meeting notes (formerly Etherpad)
[etherpad] → [roomserver.modules.meeting_notes], and url → base_url.
Previous:
[etherpad]
url = "http://localhost:9001"
api_key = "secret"
New:
[roomserver.modules.meeting_notes]
base_url = "http://localhost:9001"
api_key = "secret"
Whiteboard (formerly Spacedeck)
[spacedeck] → [roomserver.modules.whiteboard], and url → base_url.
Previous:
[spacedeck]
url = "http://localhost:9666"
api_key = "secret"
New:
[roomserver.modules.whiteboard]
base_url = "http://localhost:9666"
api_key = "secret"
Subroom audio
[subroom_audio] → [roomserver.modules.subroom_audio]. The old
enable_whisper flag no longer exists; the module is enabled simply by adding
its table.
Previous:
[subroom_audio]
enable_whisper = true
New:
[roomserver.modules.subroom_audio]
Enable the mandatory echo module
[roomserver.modules.echo]
Other modules
The following modules are now configured under [roomserver.modules.*] as well.
Add the table to enable a module (omit to keep it disabled):
[roomserver.modules.automod][roomserver.modules.chat](with optional[roomserver.modules.chat.rate_limit])[roomserver.modules.e2ee][roomserver.modules.legal_vote][roomserver.modules.meeting_report][roomserver.modules.moderation][roomserver.modules.recording][roomserver.modules.polls][roomserver.modules.reaction][roomserver.modules.shared_folder][roomserver.modules.timer][roomserver.modules.training_participation_report][roomserver.modules.transcription][roomserver.modules.raise_hands][roomserver.modules.excalidraw]
4. Replace the removed [websocket_rate_limit] table
The top-level [websocket_rate_limit] table was removed. Websocket rate
limiting is now configured on the roomserver via
[roomserver.websocket_rate_limit], and chat rate limiting via
[roomserver.modules.chat.rate_limit].
Previous:
[websocket_rate_limit]
disabled = false
tokens_per_second = 10
token_bucket_size = 30
New (optional, defaults shown):
#[roomserver.websocket_rate_limit]
#disabled = false
#tokens_per_second = 10
#token_bucket_size = 30
Note that the chat rate limit defaults also changed
(tokens_per_second 3 → 10, token_bucket_size 10 → 30) and a new
slow_down_threshold (default 0.8) was added under
[roomserver.modules.chat.rate_limit].
5. Removed [authz] table
Access control is not configurable. Earlier controller releases exposed an
[authz] (later [authorization]) section with a synchronize_controllers
option; this section is no longer read and can be removed.
6. Removed CLI subcommands
The following opentalk-controller subcommands used to manage the in-memory
ACL and have been removed:
opentalk-controller aclopentalk-controller fix-acl
Neither is necessary any more, because the authorization middleware derives its decisions directly from the tables that already model the authoritative state (users, rooms, events, invites and tariffs).
7. Removed metrics
The following metrics were tied to the removed ACL enforcement and no longer exist. Remove any dashboards or alerts that reference them:
kustos_enforce_execution_time_seckustos_load_policy_execution_time
8. Signaling metrics are provided by the roomserver
Before v0.34.0, the OpenTalk controller ran signaling in-process and
exposed signaling_* metrics on its own /metrics endpoint. v0.34.0 removed
the built-in signaling in favor of the RoomServer, and
those metrics disappeared from the controller's endpoint. Starting with
v0.34.6, the equivalent metrics are emitted by the roomserver and are
observable again, but the endpoint that serves them and the set of metric
names have changed.
Where to scrape
roomserver.kind |
Scrape target for signaling metrics |
|---|---|
internal |
The controller's /metrics endpoint (unchanged host/port). |
external |
The roomserver's /metrics endpoint (separate process, default port 11412). The roomserver's own [metrics] allowlist must include your Prometheus host; by default the endpoint refuses all connections. |
Metric mapping
The otel_scope_name label on the signaling metrics changes value from
ot-controller to ot-roomserver.
Old metric (pre-v0.34.0) |
Replacement | Notes |
|---|---|---|
signaling_created_rooms_count |
signaling_created_rooms_count |
Breakout rooms are now counted separately by signaling_created_breakout_rooms_count. |
signaling_destroyed_rooms_count |
signaling_destroyed_rooms_count |
Breakout rooms are now counted separately by signaling_destroyed_breakout_rooms_count. |
signaling_participants_count |
signaling_connection_count |
Renamed "participants" to "connections". The participation_kind label gains the values recorder, transcription, call_in, and registered_call_in. |
signaling_participants_per_room |
signaling_connections_per_room |
Implemented as a set of gauges keyed by a bucket label (2, 10, 25, 50, 100, 200, 300), not a histogram. Queries using histogram_quantile no longer apply. |
signaling_room_life_time |
signaling_room_life_time |
Bucket boundaries come from the roomserver; re-tune alert thresholds if you had customized them. |
signaling_participant_meeting_time |
signaling_connection_meeting_time |
Renamed. Bucket boundaries come from the roomserver. |
signaling_runner_startup_time_seconds |
removed | The in-process runner no longer exists. |
signaling_runner_destroy_time_seconds |
removed | The in-process runner no longer exists. |
signaling_participants_with_audio_count and signaling_participants_with_video_count
were defined on the old signaling metrics but had no emitters after the Janus
Media Server was removed in v0.26.0; they are gone with the rest of the
old signaling metrics and have no replacement.
The following metrics are new and have no pre-v0.34.0 equivalent:
| Metric | Type | Description |
|---|---|---|
signaling_created_breakout_rooms_count |
counter | Number of breakout rooms created. Previously folded into signaling_created_rooms_count; now tracked separately. |
signaling_destroyed_breakout_rooms_count |
counter | Number of breakout rooms destroyed. Previously folded into signaling_destroyed_rooms_count; now tracked separately. |
signaling_congested_connections |
counter | Number of connections the roomserver disconnected due to congestion. Useful as an indicator of client- or network-side backpressure. |
See the metrics documentation for the full list of metrics currently exposed by the controller.
9. New optional settings (no action required)
These were added in v0.34 and are optional:
[roomserver]gainedroom_idle_timeout(seconds after which an empty room is closed, default60).- The
[minio]table gainedforce_path_styleandregionforce_path_style: Use path-style bucket URLs (host/bucket) instead of virtual-hosted style; set totruefor S3-compatible servers that don't support virtual-hosted addressingregion: the AWS region