Skip to content

jpcshka/matrix-compose

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

47 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Matrix Server based on Synapse

A ready-to-use configuration for deploying a Matrix homeserver via Docker Compose.

Also available in: Русский

Table of Contents

  1. Stack
  2. Repository Structure
  3. Requirements
  4. DNS Setup
  5. Quick Start
  6. Components
  7. Operations

Stack

  • Matrix Synapse: The main homeserver, developed by Element Creations Ltd in Python.
  • Caddy: Reverse proxy server, issues and manages Let's Encrypt certificates. Developed by Matt Holt in Go.
  • LiveKit: Media server for MatrixRTC, written in Go by LiveKit Inc.
  • lk-jwt-service: Authorization service for MatrixRTC, developed by Element Creations Ltd in Go.
  • Prometheus: Metrics collection service, developed by Cloud Native Computing Foundation in Go.
  • Grafana OSS: Observability and data visualization platform, developed by Grafana Labs in Go.
  • Node Exporter: System metrics exporter, developed by Cloud Native Computing Foundation in Go.

Repository Structure

.
├── caddy/              # Caddy configuration (Caddyfile)
├── livekit/            # LiveKit configuration example (livekit.yaml.example)
├── prometheus/         # Prometheus configuration (prometheus.yml)
├── static/             # Static files for the placeholder page (html, css, js)
├── synapse/            # Synapse with S3 support (Dockerfile)
├── .env.example        # Environment variables example
└── compose.yaml        # Main compose file

Requirements

  • Linux server (Debian 13 recommended)
  • A domain name
  • Open ports:
    • 80/tcp
    • 443/tcp
    • 443/udp
    • 7881/tcp (optional)
    • 50100-50101/udp (optional)

The list of required ports depends on your MatrixRTC (LiveKit) configuration.

Recommended Server Configuration

Resource Recommendation
CPU 2-4 vCPU
RAM 2-8 GB
Disk 20+ GB
Network Public IPv4

At least 4 GB RAM is recommended for MatrixRTC.


DNS Setup

Create A records for your Matrix homeserver and MatrixRTC domains pointing to your server's IP address.

example.com          A    203.0.113.1
matrix.example.com   A    203.0.113.1
livekit.example.com  A    203.0.113.1
grafana.example.com  A    203.0.113.1

All services run on the same server, so all DNS records should point to the same IP address.


Quick Start

  1. Copy and fill in the environment variables:
cp .env.example .env
  1. Read the Components section and configure each service according to the documentation.

  2. Start:

docker compose up -d

Make sure your DNS records are configured and ports are open before starting — Caddy won't issue certificates without external access.


Components

Synapse

Matrix homeserver based on the official matrixdotorg/synapse image with the synapse-s3-storage-provider module added for storing media in S3-compatible storage.

Configuration files, keys, and media are stored in /var/lib/matrix-compose/data.

Create the directory:

mkdir -p /var/lib/matrix-compose/data

Generate configuration files:

docker run -it --rm \
    --mount type=bind,src=/var/lib/matrix-compose/data,dst=/data \
    -e SYNAPSE_SERVER_NAME=example.com \
    -e SYNAPSE_REPORT_STATS=no \
    matrixdotorg/synapse:latest generate

Add the following line to homeserver.yaml:

public_baseurl: "https://matrix.example.com/"

You also need to configure the Postgres connection:

database:
  name: psycopg2
  args:
    user: synapse_user
    password: your_strong_password
    dbname: synapse
    host: 1.2.3.4
    port: 5432
    cp_min: 5
    cp_max: 10
    keepalives_idle: 10
    keepalives_interval: 10
    keepalives_count: 3

To enable MatrixRTC calls, you need to enable federation or openid:

listeners:
  - port: 8008
    resources:
    - compress: false
      names:
      - client
#      - federation
      - openid # <---
    tls: false
    type: http
    x_forwarded: true

You also need to enable MSCs (Matrix spec proposals) and specify the LiveKit server domain:

experimental_features:
  msc4222_enabled: true
  msc4354_enabled: true

max_event_delay_duration: 24h
rc_message:
  per_second: 0.5
  burst_count: 30
rc_delayed_event_mgmt:
  per_second: 1
  burst_count: 20

matrix_rtc:
  transports:
  - type: livekit
    livekit_service_url: https://livekit.example.com/livekit/jwt

To enable S3 storage, configure the storage provider:

media_storage_providers:
- module: s3_storage_provider.S3StorageProviderBackend
  store_local: True
  store_remote: True
  store_synchronous: True
  config:
    bucket: <S3_BUCKET_NAME>
    region_name: <S3_REGION_NAME>
    endpoint_url: <S3_LIKE_SERVICE_ENDPOINT_URL>
    access_key_id: <S3_ACCESS_KEY_ID>
    secret_access_key: <S3_SECRET_ACCESS_KEY>
    session_token: <S3_SESSION_TOKEN>

See also:


Caddy

Reverse proxy based on the official caddy image. Issues and manages TLS certificates for each subdomain, serves .well-known endpoints for Matrix, redirects all other requests to example.com, and serves static files.

By default, Caddy does not set a limit on request body size. An explicit limit of 300MB is configured:

request_body {
  max_size 300MB
}

The limit must match the limit in homeserver.yaml:

max_upload_size: 300M

For QUIC (HTTP/3) and LiveKit WebRTC traffic to work correctly, you need to increase the UDP buffers at the kernel level.

Apply immediately (until reboot):

sudo sysctl -w net.core.rmem_max=7500000
sudo sysctl -w net.core.wmem_max=7500000

To persist after reboot, add to /etc/sysctl.conf:

net.core.rmem_max=7500000
net.core.wmem_max=7500000

The value 7500000 is recommended by the quic-go library used internally by Caddy.

See also:


LiveKit

Media server for MatrixRTC. LiveKit does not support environment variables for most configuration parameters, so all settings are defined directly in livekit/livekit.yaml. Copy the example and fill it in:

cp livekit/livekit.yaml.example livekit/livekit.yaml

Instead of opening dozens of ports, UDP mux is used. The number of ports must be no less than the number of CPU cores on the server:

rtc:
  udp_port: 50100-50101

You also need to expose these ports in compose.yaml:

livekit:
  ports:
    - "50100-50101:50100-50101/udp"

If you use multiple LiveKit servers, Redis is required.

See also:


lk-jwt-service

Authorization service for MatrixRTC based on the official image. Acts as middleware between the client and LiveKit: issues JWT tokens that authorize participation in a call. All parameters are passed via environment variables in .env — no separate configuration file is required.


Prometheus & Grafana

Monitoring stack based on official images: Prometheus collects metrics from all services, node-exporter — host metrics, Grafana — visualization.

To enable Synapse metrics, add to homeserver.yaml:

enable_metrics: true
listeners:
  # beginning of the new metrics listener
  - port: 9000
    type: metrics
    bind_addresses: ['0.0.0.0']

To enable LiveKit metrics, add to livekit/livekit.yaml:

prometheus_port: 6789

Caddy exposes metrics on port 2019 — this is already configured in Caddyfile and prometheus/prometheus.yml, no additional steps required.

Grafana is available via Caddy with basic_auth. To generate a password hash (argon2id):

docker compose exec -it caddy sh
caddy hash-password --algorithm argon2id --plaintext 'yourpassword'

See also:


Operations

Automated Deployment

Use GitHub Actions for automated deployment. Copy .github/workflows/deploy.yml into your repository — deployment will trigger automatically on a v*.*.* tag push or manually.

  1. Create a user on the server
sudo useradd -m -s /bin/bash gh-deploy
sudo mkdir -p /home/gh-deploy/.ssh
sudo chmod 700 /home/gh-deploy/.ssh
  1. Create the deploy script

Create the script and make it executable:

sudo touch /path/to/deploy.sh
sudo chmod +x /path/to/deploy.sh

Example script:

#!/bin/bash
set -e

cd /path/to/matrix-compose

git pull origin main --ff-only
docker compose pull
docker compose up -d
  1. Grant sudo privileges
echo "gh-deploy ALL=(root) NOPASSWD: /path/to/deploy.sh" | sudo tee /etc/sudoers.d/gh-deploy
  1. Configure SSH access

Generate an SSH key for GitHub Actions and add the public key to /home/gh-deploy/.ssh/authorized_keys with a forced script execution on connection:

command="sudo /path/to/deploy.sh",no-pty,no-port-forwarding,no-X11-forwarding,no-agent-forwarding ssh-ed25519 AAAA...
sudo chmod 600 /home/gh-deploy/.ssh/authorized_keys
sudo chown -R gh-deploy:gh-deploy /home/gh-deploy/.ssh
  1. Add secrets to the repository

Settings → Secrets and variables → Actions → New repository secret

Get the server's public key for SSH_KNOWN_HOSTS:

ssh-keyscan -t ed25519 example.com
Secret Description
SSH_PRIVATE_KEY Private SSH key for connecting to the server
SSH_KNOWN_HOSTS Server public key (output of ssh-keyscan)
SSH_USER User on the server (gh-deploy)
SSH_HOST Server IP address or domain

About

Ready-to-deploy Matrix homeserver stack with Synapse, Caddy, and LiveKit. Includes S3 storage support through a custom synapse-s3 Docker image published to GHCR.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors