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
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>
358 lines
16 KiB
Plaintext
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
|