Files
VuongKB/infrastructure/matrix-docker-deployment.md
T

9.2 KiB

created, id, keywords, links, modified, summary, tags, title
created id keywords links modified summary tags title
2026-04-11T08:13:34+00:00 4aebb788-2478-4fc7-9171-c3cbd25032a3
matrix
synapse
element
docker
docker compose
chat protocol
federation
homeserver
postgresql
decentralized communication
end-to-end encryption
bridges
well-known
matrix.org
element-hq
2026-04-11T08:13:34+00:00 Comprehensive reference covering the Matrix messaging protocol, key concepts (homeservers, federation, rooms, bridges), Synapse configuration, and a full Docker Compose deployment guide including PostgreSQL, Element Web, federation setup, TLS/reverse proxy notes, and backup procedures.
infrastructure
matrix
docker
self-hosted
communication
reference
Matrix — Overview & Docker Deployment Reference

Matrix — Overview & Docker Deployment Reference

What is Matrix?

Matrix is an open standard and communication protocol for real-time, decentralized communication. It provides end-to-end encryption, federation between servers (similar to email), and rich features like voice/video calls, bridging to other platforms (Slack, Discord, Telegram, WhatsApp, Signal, IRC, etc.), and rich media sharing.

  • Official site: https://matrix.org
  • Specification: https://spec.matrix.org/latest/
  • License: Apache 2.0 (per-server implementations vary)
  • Note: As of Synapse v1.99, Synapse is now maintained by Element (github.com/element-hq/synapse) rather than the Matrix.org Foundation, under a new licence.

Key Concepts

Concept Description
Homeserver Stores communication history and account data for its users. The reference implementation is Synapse (Python/Twisted). Alternatives include Dendrite (Go) and Conduit (Rust).
Client Apps that connect to a homeserver. The most popular is Element (web, desktop, mobile). Others include Cinny, FluffyChat, Hydrogen, SchildiChat.
Federation Homeservers sync data with each other, allowing users on different servers to communicate (like email). Requires proper DNS and TLS configuration.
Room A virtual space for communication. Events (messages, state changes) are emitted in the context of rooms.
User ID format @username:server_name (e.g., @alice:example.com)
Bridges Services that connect Matrix rooms to external platforms (Discord, Slack, Telegram, WhatsApp, IRC, etc.)

Synapse (Reference Homeserver)

  • Language: Python/Twisted
  • Database: SQLite (testing only), PostgreSQL (recommended for production)
  • RAM: At least 1GB free RAM; 2GB+ recommended
  • Ports: 8008 (Client & Federation HTTP API), 8448 (Federation HTTPS — typically via reverse proxy)
  • Official Docker image: matrixdotorg/synapse (Docker Hub) or ghcr.io/matrix-org/synapse (GHCR)
  • GitHub: https://github.com/matrix-org/synapse (historical) → https://github.com/element-hq/synapse (current)

Docker Deployment Guide

Prerequisites

  • Docker Engine 20.10+
  • Docker Compose v2
  • A domain name (required for federation)
  • At least 2GB RAM
  • Ports 80, 443, and 8448 available

Step 1: Generate Synapse Configuration

mkdir matrix-docker && cd matrix-docker

docker run -it --rm \
  -v $(pwd)/synapse-data:/data \
  -e SYNAPSE_SERVER_NAME=yourdomain.com \
  -e SYNAPSE_REPORT_STATS=no \
  matrixdotorg/synapse:latest generate

This creates homeserver.yaml in the synapse-data/ directory.

Step 2: Configure PostgreSQL in homeserver.yaml

Edit synapse-data/homeserver.yaml:

server_name: "yourdomain.com"

listeners:
  - port: 8008
    tls: false
    type: http
    x_forwarded: true
    resources:
      - names: [client, federation]
        compress: false

database:
  name: psycopg2
  args:
    user: synapse
    password: synapse_db_pass
    database: synapse
    host: postgres
    port: 5432
    cp_min: 5
    cp_max: 10

media_store_path: /data/media_store
max_upload_size: 50M

enable_registration: false
report_stats: false

Step 3: Docker Compose File

version: "3.8"

services:
  synapse:
    image: matrixdotorg/synapse:latest
    container_name: synapse
    volumes:
      - synapse-data:/data
    environment:
      SYNAPSE_CONFIG_DIR: /data
      SYNAPSE_CONFIG_PATH: /data/homeserver.yaml
      TZ: "UTC"
    depends_on:
      postgres:
        condition: service_healthy
    ports:
      - "8008:8008"
      - "8448:8448"
    networks:
      - matrix-network
    restart: unless-stopped

  postgres:
    image: postgres:16-alpine
    container_name: synapse-postgres
    environment:
      POSTGRES_DB: synapse
      POSTGRES_USER: synapse
      POSTGRES_PASSWORD: synapse_db_pass
      POSTGRES_INITDB_ARGS: "--encoding=UTF-8 --lc-collate=C --lc-ctype=C"
    volumes:
      - postgres-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U synapse"]
      interval: 5s
      timeout: 5s
      retries: 10
    networks:
      - matrix-network
    restart: unless-stopped

  element:
    image: vectorim/element-web:latest
    container_name: element-web
    volumes:
      - ./element-config.json:/app/config.json:ro
    ports:
      - "8080:80"
    networks:
      - matrix-network
    restart: unless-stopped

volumes:
  synapse-data:
  postgres-data:

networks:
  matrix-network:
    driver: bridge

Step 4: Element Configuration

Create element-config.json:

{
  "default_server_config": {
    "m.homeserver": {
      "base_url": "https://matrix.yourdomain.com",
      "server_name": "yourdomain.com"
    },
    "m.identity_server": {
      "base_url": "https://vector.im"
    }
  },
  "brand": "Element",
  "room_directory": {
    "servers": ["yourdomain.com", "matrix.org"]
  }
}

Step 5: Federation — .well-known Files

mkdir -p well-known/matrix

# well-known/matrix/server
{"m.server": "matrix.yourdomain.com:443"}

# well-known/matrix/client
{"m.homeserver": {"base_url": "https://matrix.yourdomain.com"}}

Step 6: DNS Records

matrix.yourdomain.com    A    YOUR_SERVER_IP
element.yourdomain.com   A    YOUR_SERVER_IP

Step 7: Start Services

docker compose up -d postgres
docker compose up -d synapse
docker compose up -d element

Step 8: Create Admin User

docker exec -it synapse register_new_matrix_user \
  http://localhost:8008 \
  -c /data/homeserver.yaml \
  -u admin \
  -p SECURE_PASSWORD \
  --admin

TLS / Reverse Proxy

For production, put Nginx or Traefik in front of Synapse with TLS termination. Key points:

  • Port 443: Client-Server API and Federation (with x_forwarded: true in Synapse)
  • Port 8448: Dedicated Federation port (required for some federation scenarios)
  • Client max body size: at least 50M for media uploads
  • .well-known/matrix/server and .well-known/matrix/client must be served with Access-Control-Allow-Origin: *

Alternative Homeservers

Homeserver Language Notes
Synapse Python/Twisted Reference implementation, most feature-complete, heaviest resource usage
Dendrite Go Second-generation, lighter weight, not all features implemented
Conduit Rust Very lightweight, good for small deployments, still maturing

Community Ansible Playbook (Advanced)

For a comprehensive, production-ready setup with many services pre-configured:

  • Repository: https://github.com/spantaleev/matrix-docker-ansible-deploy
  • Includes: Synapse/Dendrite/Conduit, Element, PostgreSQL, Traefik, Let's Encrypt, coturn (STUN/TURN), email, 20+ bridges (Discord, Slack, Telegram, WhatsApp, Signal, IRC, etc.), bots (Mjolnir, Draupnir, reminder bot), monitoring (Prometheus/Grafana), backups (Borg), and more
  • Support room: #matrix-docker-ansible-deploy:devture.com

Useful Admin API Commands

# Get server version
curl -s "https://matrix.yourdomain.com/_synapse/admin/v1/server_version" \
  -H "Authorization: Bearer TOKEN"

# List users
curl -s "https://matrix.yourdomain.com/_synapse/admin/v2/users?from=0&limit=10" \
  -H "Authorization: Bearer TOKEN"

# Deactivate a user
curl -X POST "https://matrix.yourdomain.com/_synapse/admin/v1/deactivate/@user:yourdomain.com" \
  -H "Authorization: Bearer TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"erase": false}'

Backup & Update

# Backup database
docker compose exec postgres pg_dump -U synapse synapse > backup.sql

# Backup media
docker cp synapse:/data/media_store ./media-backup

# Update
docker compose pull
docker compose up -d

Sources

(Date of research: April 2026)