Collaboration & Productivity

matrix

Matrix (Element Server Suite) — Synapse homeserver, MAS auth with Keycloak OIDC, Element Web/Admin, MatrixRTC/LiveKit SFU with HA defaults

@r8s/matrix

matrixelementsynapsechatrtcoidc

Components (4)

01

MatrixSSO

import { Platform } from '@r8s/recipes'
import { Matrix } from '@r8s/matrix'

export default (
  <Platform secrets={{ backend: 'openbao', mount: 'kv', path: 'matrix' }}>
    <Matrix
      domain="example.com"
      sso={{ issuer: 'https://keycloak.example.com/realms/berget', clientId: 'matrix' }}
      database={{
        backup: {
          destinationPath: 's3://backups/matrix-cnpg',
          endpointURL: 'https://s3.example.com',
        },
      }}
      rtc={{ manualIP: '203.0.113.10' }}
      appservices={[
        {
          name: 'hookshot',
          registration: {
            id: 'hookshot',
            as_token: 'PROVIDED_VIA_GITOPS',
            hs_token: 'PROVIDED_VIA_GITOPS',
            namespaces: { users: [{ regex: '@hookshot:example.com', exclusive: true }] },
            url: 'http://hookshot:9000',
          },
        },
      ]}
    />
  </Platform>
)
issuerstringRequired

Keycloak/OIDC issuer URL (e.g. https://keycloak.example.com/realms/berget)

clientIdstringRequired

OIDC client id registered in the realm

clientSecretRefstringOptional

Name of an existing Secret containing key clientSecret. Required unless a secrets backend (openbao/vault) is configured on the surrounding Platform — the backend then provisions ${name}-keycloak-oidc.

humanNamestringOptional

Display name on the MAS login button (default: 'SSO')

scopestringOptional

OIDC scope (default: 'openid email profile')

02

MatrixDatabase

import { Platform } from '@r8s/recipes'
import { Matrix } from '@r8s/matrix'

export default (
  <Platform secrets={{ backend: 'openbao', mount: 'kv', path: 'matrix' }}>
    <Matrix
      domain="example.com"
      sso={{ issuer: 'https://keycloak.example.com/realms/berget', clientId: 'matrix' }}
      database={{
        backup: {
          destinationPath: 's3://backups/matrix-cnpg',
          endpointURL: 'https://s3.example.com',
        },
      }}
      rtc={{ manualIP: '203.0.113.10' }}
      appservices={[
        {
          name: 'hookshot',
          registration: {
            id: 'hookshot',
            as_token: 'PROVIDED_VIA_GITOPS',
            hs_token: 'PROVIDED_VIA_GITOPS',
            namespaces: { users: [{ regex: '@hookshot:example.com', exclusive: true }] },
            url: 'http://hookshot:9000',
          },
        },
      ]}
    />
  </Platform>
)
replicasnumberOptional

CNPG instances (default: 2)

storagestringOptional

Storage size per database (default: '20Gi')

storageClassstringOptional

StorageClass name (default: cluster default)

backup{ destinationPath: string, endpointURL: string, credentialsSecret?: string, retention?: string, schedule?: string } | nullOptional

Backup configuration — barman object store + scheduled full backups. Set to false to disable. Defaults to off unless specified (explicit opt-in so you can't forget: a disk-full WAL incident is exactly what this prevents).

03

MatrixRTC

import { Platform } from '@r8s/recipes'
import { Matrix } from '@r8s/matrix'

export default (
  <Platform secrets={{ backend: 'openbao', mount: 'kv', path: 'matrix' }}>
    <Matrix
      domain="example.com"
      sso={{ issuer: 'https://keycloak.example.com/realms/berget', clientId: 'matrix' }}
      database={{
        backup: {
          destinationPath: 's3://backups/matrix-cnpg',
          endpointURL: 'https://s3.example.com',
        },
      }}
      rtc={{ manualIP: '203.0.113.10' }}
      appservices={[
        {
          name: 'hookshot',
          registration: {
            id: 'hookshot',
            as_token: 'PROVIDED_VIA_GITOPS',
            hs_token: 'PROVIDED_VIA_GITOPS',
            namespaces: { users: [{ regex: '@hookshot:example.com', exclusive: true }] },
            url: 'http://hookshot:9000',
          },
        },
      ]}
    />
  </Platform>
)
enabledbooleanOptional

Enable MatrixRTC / LiveKit SFU (default: true)

manualIPstringOptional

External IP for the SFU LoadBalancer — LiveKit needs a real IP (not DNS) for ICE. Leave unset to rely on STUN discovery.

turnPortnumberOptional

TURN server port on the combined LoadBalancer (default: 30004, 0 disables)

stunServersstring[]Optional

Extra STUN servers for client NAT traversal

sfuVersionstringOptional

LiveKit image tag (default: v1.10.1 — pinned for the IPv6 ICE URL regression)

04

Matrix

Matrix — full Element Server Suite: Synapse homeserver, MAS with Keycloak OIDC, Element Web + Admin, MatrixRTC/LiveKit SFU.

import { Platform } from '@r8s/recipes'
import { Matrix } from '@r8s/matrix'

export default (
  <Platform secrets={{ backend: 'openbao', mount: 'kv', path: 'matrix' }}>
    <Matrix
      domain="example.com"
      sso={{ issuer: 'https://keycloak.example.com/realms/berget', clientId: 'matrix' }}
      database={{
        backup: {
          destinationPath: 's3://backups/matrix-cnpg',
          endpointURL: 'https://s3.example.com',
        },
      }}
      rtc={{ manualIP: '203.0.113.10' }}
      appservices={[
        {
          name: 'hookshot',
          registration: {
            id: 'hookshot',
            as_token: 'PROVIDED_VIA_GITOPS',
            hs_token: 'PROVIDED_VIA_GITOPS',
            namespaces: { users: [{ regex: '@hookshot:example.com', exclusive: true }] },
            url: 'http://hookshot:9000',
          },
        },
      ]}
    />
  </Platform>
)
namestringOptional

Resource name (defaults to 'matrix')

namespacestringOptional

Kubernetes namespace (inherited from Platform context when omitted)

domainstringRequired

Base domain — derives the five public hosts (see hosts)

hostsPartialOptional

Host overrides. Defaults: web: element.<domain>, synapse: matrix.<domain>, admin: element-admin.<domain>, account: matrix-account.<domain>, rtc: matrix-rtc.<domain>

replicasnumberOptional

Replicas for the stateless web/admin/mas/haproxy-ish layers (default: 2; synapse and SFU stay at 1 until federation workers land)

serverNamestringOptional

Matrix server name — becomes part of user IDs (@user:serverName). Defaults to domain.

ssoMatrixSSOPropsOptional

SSO/OIDC upstream for MAS (Keycloak). Password login disabled when set.

databaseMatrixDatabasePropsOptional

Per-database sizing + backup for synapse-db and mas-db

rtcMatrixRTCPropsOptional

MatrixRTC / LiveKit SFU (Element Call backend)

appservices( | { name: string; registration: Record<string, unknown>; secretRef?: never; key?: never } | { name: string; secretRef: string; key?: string; registration?: never } )[]Optional

Appservice registrations (hookshot, bots…). Each mounts one registration.yaml into Synapse's appservice directory. Two modes per entry: - registration: inline YAML data rendered as a Secret (never a ConfigMap — registrations carry as_token/hs_token). Use placeholders for the tokens and let GitOps fill them, or expect the noPlaintextSecrets guardrail to flag live token values. - secretRef: name of an existing Secret holding registration.yaml (key override via key). Nothing rendered — the preferred mode when the file lives in the secrets backend.

version{ synapse?: string, mas?: string, web?: string, admin?: string, sfu?: string }Optional

Version pinning per component (production: pin these — the defaults are already pinned for known upstream regressions): web: v1.12.15 (MSC4143 Authorization header fix), sfu: v1.10.1 (IPv6 ICE URL fix)

urlPreviewbooleanOptional

Disable the URL-preview SSRF blacklist preset (default: enabled, hardened)