Files
Warp/warp.yaml.example
tajniak81andClaude Opus 5.5 76dfc98a86
CI / Test (ubuntu-latest) (push) Canceled after 0s
CI / Test (windows-latest) (push) Canceled after 0s
CI / Storage tests on PostgreSQL (push) Canceled after 0s
CI / Complement (federation off) (push) Canceled after 0s
CI / golangci-lint (push) Canceled after 0s
CI / Smoke test the binary (push) Canceled after 0s
CI / Admin panel (push) Canceled after 0s
CI / Web client (push) Canceled after 0s
Group voice and video calls with MatrixRTC and LiveKit
Every call in the web client now goes through MatrixRTC with a LiveKit
SFU, the model Element Call and Element X use; the legacy 1:1 m.call.*
calls are gone. In a room of two the other person is rung and can answer
or decline; in a bigger room a banner offers to join the call. Calls show
a grid of participant tiles with mute, camera, screen sharing and leave,
and media is end-to-end encrypted in encrypted rooms.

Server:
- MSC4140 delayed events (send/state with a delay, plus the
  delayed_events list/restart/cancel/send API), stored and scheduled, so
  a member whose client drops off is taken out of the call.
- POST /user/{userId}/openid/request_token, which lk-jwt-service uses to
  hand out LiveKit tokens.
- org.matrix.msc4143.rtc_foci in /.well-known/matrix/client, configured
  under client_api.rtc.
- Room presets let members send call membership state.
- Migration 0014 for both SQL dialects.

Deploy: LiveKit and lk-jwt-service in compose (calls.yml) and the helm
chart. Docs: docs/calls.md, configuration and deployment.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 19:33:29 +02:00

358 lines
16 KiB
Plaintext

# Warp homeserver configuration.
#
# Copy to warp.yaml and edit. Every field below is optional except
# global.server_name; the values shown are the defaults.
#
# Any field can also be set from the environment, which wins over this
# file. The variable name is on the right of each line below, e.g.
# WARP_SERVER_NAME=warp.example WARP_FEDERATION_ENABLED=true warp serve
# List values are comma-separated; a single "-" clears a list.
version: 1
global:
# The Matrix server name. It appears in every user, room and event ID
# and CANNOT be changed after the first event is written. WARP_SERVER_NAME
server_name: warp.example
# ed25519 signing key, created by `warp generate-keys`. WARP_PRIVATE_KEY
private_key: ./keys/signing.key
well_known:
# Advertised to clients as m.homeserver.base_url.
# Defaults to https://<server_name>. WARP_WELL_KNOWN_CLIENT_BASE_URL
client_base_url: ""
# Optional identity server. WARP_WELL_KNOWN_IDENTITY_SERVER_BASE_URL
identity_server_base_url: ""
# Advertised to other homeservers as m.server, e.g. "warp.example:8448".
# Only served while federation is enabled; empty means other servers
# fall back to SRV/A resolution. WARP_WELL_KNOWN_SERVER_ADDRESS
server_address: ""
listen:
address: ":8008" # WARP_LISTEN_ADDRESS
read_header_timeout: 10s # WARP_READ_HEADER_TIMEOUT
read_timeout: 60s # WARP_READ_TIMEOUT
write_timeout: 120s # WARP_WRITE_TIMEOUT
idle_timeout: 120s # WARP_IDLE_TIMEOUT
max_header_bytes: 1048576 # WARP_MAX_HEADER_BYTES
shutdown_timeout: 30s # WARP_SHUTDOWN_TIMEOUT
# A second listener serving the same API over TLS, for other servers.
# 8448 is the port they try when nothing delegates them elsewhere. Leave
# it empty behind a reverse proxy that terminates TLS, and point
# global.well_known.server_address at the proxy instead.
# WARP_LISTEN_FEDERATION_ADDRESS
federation_address: ""
tls_cert_file: "" # WARP_TLS_CERT_FILE (PEM chain)
tls_key_file: "" # WARP_TLS_KEY_FILE
database:
# sqlite (dev, single user), postgres (production) or pocketbase
# (appliance: sqlite inside an embedded PocketBase, media on its
# filesystem, local or S3). WARP_DB_DRIVER
driver: sqlite
# sqlite: file:warp.db?_pragma=journal_mode(WAL)
# postgres: postgres://warp:secret@localhost/warp?sslmode=disable
# pocketbase: the data directory, e.g. ./pb_data
# WARP_DB_CONNECTION_STRING
connection_string: "file:warp.db?_pragma=journal_mode(WAL)&_pragma=busy_timeout(10000)&_pragma=foreign_keys(1)"
max_open_conns: 10 # WARP_DB_MAX_OPEN_CONNS (ignored by sqlite:
max_idle_conns: 5 # WARP_DB_MAX_IDLE_CONNS one writer only)
conn_max_lifetime: 1h # WARP_DB_CONN_MAX_LIFETIME
# Apply pending migrations on startup. Set false to gate schema changes
# behind an explicit `warp migrate`. WARP_DB_AUTO_MIGRATE
auto_migrate: true
# The pocketbase driver only. With S3 on, media content goes to the
# bucket instead of <data directory>/storage; media.base_path is not
# used by this driver either way.
pocketbase:
s3:
enabled: false # WARP_PB_S3_ENABLED
bucket: "" # WARP_PB_S3_BUCKET
region: "" # WARP_PB_S3_REGION
endpoint: "" # WARP_PB_S3_ENDPOINT, e.g. https://s3.eu-central-1.amazonaws.com
access_key: "" # WARP_PB_S3_ACCESS_KEY
secret: "" # WARP_PB_S3_SECRET
force_path_style: false # WARP_PB_S3_FORCE_PATH_STYLE (MinIO)
client_api:
# The Matrix spec expects a homeserver to allow any origin. Narrow this
# if only your own web client talks to it. WARP_CORS_ALLOWED_ORIGINS
cors_allowed_origins: ["*"]
# Take the client address from X-Forwarded-For instead of the socket.
# Turn this on ONLY behind a reverse proxy that overwrites the header:
# anyone can send it, and the rate limiter keys on the result.
# WARP_TRUST_X_FORWARDED_FOR
trust_x_forwarded_for: false
# Expire access tokens after this long. 0 (the default) issues tokens
# that never expire, which is what clients without refresh-token
# support need. With a lifetime set, clients that ask for
# refresh_token on login get one. WARP_ACCESS_TOKEN_LIFETIME
access_token_lifetime: 0s
# How long a refresh token may be exchanged for a new access token.
# 0 means no expiry. WARP_REFRESH_TOKEN_LIFETIME
refresh_token_lifetime: 0s
# Relay servers for Matrix 1:1 VoIP, handed to clients by
# GET /voip/turnServer. Warp's web client doesn't use them: its calls go
# through LiveKit (rtc below), which needs no TURN of its own here. This
# is for other Matrix clients that still place legacy 1:1 calls; with no
# uris, theirs only connect where the two can reach each other directly.
#
# With shared_secret (coturn's `use-auth-secret` + `static-auth-secret`)
# every user gets credentials that expire after user_lifetime. username
# and password are static credentials for servers that cannot do that.
turn:
uris: [] # WARP_TURN_URIS
# - "turn:turn.example.org:3478?transport=udp"
# - "turn:turn.example.org:3478?transport=tcp"
# - "turns:turn.example.org:5349?transport=tcp"
shared_secret: "" # WARP_TURN_SHARED_SECRET
user_lifetime: 1h # WARP_TURN_USER_LIFETIME
username: "" # WARP_TURN_USERNAME
password: "" # WARP_TURN_PASSWORD
# Group calls (MatrixRTC). Warp carries no call media itself: clients
# publish to a LiveKit SFU and get a token for it from the LiveKit JWT
# service (lk-jwt-service), which checks who they are with an OpenID
# token from this server. Its URL is advertised to clients in
# /.well-known/matrix/client; leave it empty for no group calls.
# See docs/calls.md.
rtc:
livekit_service_url: "" # WARP_RTC_LIVEKIT_SERVICE_URL
# e.g. "https://livekit-jwt.example.org"
# Delayed events (MSC4140): events a client schedules now for the server
# to send later unless it pushes them back. A group call member's "left
# the call" is one, so someone whose browser crashes still leaves.
# max_delay 0 turns them off.
delayed_events:
max_delay: 24h # WARP_DELAYED_EVENTS_MAX_DELAY
max_per_user: 100 # WARP_DELAYED_EVENTS_MAX_PER_USER
# Per-endpoint rate limiting. Each bucket allows `burst` requests back
# to back and returns one slot every `interval`, per client address.
# Login and registration get their own, tighter, buckets because they
# are the two endpoints worth brute-forcing.
#
# Only `enabled` has an environment override (the three buckets share a
# type, so per-bucket variables would collide): set
# WARP_RATE_LIMIT_ENABLED=false to turn the whole thing off, which is
# what a test harness such as Complement wants.
rate_limit:
enabled: true # WARP_RATE_LIMIT_ENABLED
default:
burst: 30
interval: 100ms
login:
burst: 10
interval: 1s
register:
burst: 5
interval: 2s
# Creating a room writes a dozen events and joining one writes a
# membership event that everybody in the room then sees, so both are
# deliberately slower than a read.
room_create:
burst: 10
interval: 1s
join:
burst: 10
interval: 1s
# /sync and the chatty writes behind it: typing, receipts, to-device
# messages and presence. The loosest bucket of the lot on purpose — a
# client lives in /sync, and a long poll that is refused leaves it
# reconnecting in a loop, which is the one case where rate limiting
# makes the load worse rather than better.
sync:
burst: 100
interval: 20ms
# Media downloads and thumbnails. A client opening a room asks for
# every member's avatar at once, so this is as loose as sync. Uploads
# are in the default bucket.
media:
burst: 100
interval: 20ms
sync:
# Presence — who is online, and the status message they set. Off by
# default: it is the noisiest thing in Matrix, because every user's
# state change is published to everybody they share a room with, and a
# private homeserver gains little from it. With it off, the presence
# endpoints answer M_FORBIDDEN and a sync's presence section is empty.
# WARP_SYNC_PRESENCE
presence: false
# How long a typing notification lasts without being renewed, and the
# cap on what a client may ask for. A notification that outlived its
# sender's session would leave a room claiming somebody was typing.
# WARP_SYNC_TYPING_TIMEOUT
typing_timeout: 30s
# The cap on a /sync's ?timeout=, whatever the client asks for. Holding
# a connection open longer buys nothing — a blocked sync is woken the
# moment anything happens — so this only decides how often an idle
# client re-establishes its request.
# WARP_SYNC_LONG_POLL_TIMEOUT
long_poll_timeout: 30s
federation:
# Off by default: a new install is a private homeserver until you say
# otherwise. WARP_FEDERATION_ENABLED
enabled: false
# Non-empty = federate ONLY with these servers.
# WARP_FEDERATION_ALLOWLIST
allowlist: []
# Always blocked, even if listed above. WARP_FEDERATION_DENYLIST
denylist: []
# Let the admin API flip `enabled` without a restart. When true, the
# stored setting overrides the value above on boot.
# WARP_FEDERATION_ALLOW_RUNTIME_TOGGLE
allow_runtime_toggle: true
# Notaries asked for another server's signing key when that server
# cannot be reached directly, e.g. [matrix.org]. Empty: keys are only
# fetched from their own server. WARP_FEDERATION_TRUSTED_KEY_SERVERS
trusted_key_servers: []
# How long other servers may cache this server's key. At most 168h.
# WARP_FEDERATION_KEY_VALIDITY_PERIOD
key_validity_period: 24h
# Extra CA certificates (PEM) trusted for outbound federation, for a
# private federation with an internal CA. WARP_FEDERATION_TLS_CA_FILE
tls_ca_file: ""
media:
# Where uploaded files, and files fetched from other servers, are kept.
# Created on the first upload. WARP_MEDIA_BASE_PATH
base_path: ./media_store
# The largest upload, and the largest file fetched from another server
# (50 MiB). Clients are told this in /media/config.
# WARP_MEDIA_MAX_UPLOAD_BYTES
max_upload_bytes: 52428800
# The most one user may have uploaded in all; 0 = no limit. The admin
# API can give a user a quota of their own.
# WARP_MEDIA_MAX_USER_STORAGE_BYTES
max_user_storage_bytes: 0
# The largest image, in pixels, decoded to make a thumbnail. Decoding
# costs four bytes a pixel however small the file is.
# WARP_MEDIA_MAX_THUMBNAIL_PIXELS
max_thumbnail_pixels: 32000000
# The thumbnails this server makes. A request gets the smallest size here
# that is at least as large as what it asked for. "crop" fills the box
# exactly; "scale" fits inside it and keeps the aspect ratio.
thumbnail_sizes:
- {width: 32, height: 32, method: crop}
- {width: 96, height: 96, method: crop}
- {width: 320, height: 240, method: scale}
- {width: 640, height: 480, method: scale}
- {width: 800, height: 600, method: scale}
# How long an ID reserved with POST /media/v1/create waits for its
# content, and how many of those one user may hold.
pending_upload_expiry: 24h # WARP_MEDIA_PENDING_UPLOAD_EXPIRY
max_pending_uploads: 10 # WARP_MEDIA_MAX_PENDING_UPLOADS
# Keep the deprecated /_matrix/media/v3/download and /thumbnail
# endpoints, which need no access token: anybody who learns an mxc://
# URI can read the file through them. Only for clients older than
# Matrix 1.11. WARP_MEDIA_LEGACY_UNAUTHENTICATED_DOWNLOADS
legacy_unauthenticated_downloads: false
push:
# Send pushes to the push gateways of users' pushers — what wakes a
# phone for a new message. Off, notifications are still counted (unread
# badges come from the counts, not from pushes) and nothing leaves the
# server. WARP_PUSH_ENABLED
enabled: true
# Put the event's content into a push. Off, a push says who sent what
# kind of event in which room and nothing of what it said, for when
# message text should not pass through a third-party push service.
# WARP_PUSH_INCLUDE_CONTENT
include_content: true
# One request to a push gateway. WARP_PUSH_GATEWAY_TIMEOUT
gateway_timeout: 10s
# How long a notification that has been read is kept for GET
# /notifications. Unread ones are kept until read.
# WARP_PUSH_NOTIFICATION_RETENTION
notification_retention: 720h
registration:
# Off by default. Make the first account with
# `warp create-account --username you --admin`, then turn registration
# on from the admin API if you want others to sign up.
enabled: false # WARP_REGISTRATION_ENABLED
allow_runtime_toggle: true # WARP_REGISTRATION_ALLOW_RUNTIME_TOGGLE
# Non-empty = registration also requires a token, as the
# m.login.registration_token stage of the sign-up flow. These never run
# out; tokens with a use limit or an expiry are made through the admin
# API (POST /_warp/admin/v1/registration_tokens), and both kinds are
# accepted. WARP_REGISTRATION_TOKENS
tokens: []
# Ask for a token even with none listed above, for a server whose
# tokens all come from the admin API. WARP_REGISTRATION_REQUIRE_TOKEN
require_token: false
appservice:
# Application service registration files: the YAML every bridge
# writes. Read at startup; a bad one stops the server. See
# docs/appservices.md. WARP_APPSERVICE_CONFIG_FILES
config_files: []
# One request to a service: a transaction, a query or a ping.
# WARP_APPSERVICE_TIMEOUT
timeout: 30s
server_notices:
# Messages from the server to its users, sent through the admin API
# (POST /_warp/admin/v1/server_notices). Needs a signing key.
# WARP_SERVER_NOTICES_ENABLED
enabled: false
# The user notices come from, created at startup if it does not exist —
# pick a name no real user has. WARP_SERVER_NOTICES_LOCALPART
localpart: server-notices
display_name: Server Notices # WARP_SERVER_NOTICES_DISPLAY_NAME
room_name: Server Notices # WARP_SERVER_NOTICES_ROOM_NAME
logging:
level: info # debug, info, warn, error WARP_LOG_LEVEL
format: text # text or json WARP_LOG_FORMAT
add_source: false # WARP_LOG_ADD_SOURCE
metrics:
enabled: true # WARP_METRICS_ENABLED
path: /metrics # WARP_METRICS_PATH
# OpenTelemetry tracing, exported over OTLP/HTTP to a collector, Jaeger,
# Tempo or anything else that speaks it. See docs/deployment.md.
tracing:
enabled: false # WARP_TRACING_ENABLED
# Empty falls back to OTEL_EXPORTER_OTLP_ENDPOINT, then localhost:4318.
endpoint: "" # WARP_TRACING_ENDPOINT, e.g. http://localhost:4318
sample_ratio: 1 # WARP_TRACING_SAMPLE_RATIO, 0 to 1
service_name: warp # WARP_TRACING_SERVICE_NAME