docker.recipes

Matrix Synapse Server

advanced

Self-hosted Matrix homeserver with Synapse, Element web client, and PostgreSQL.

Overview

Matrix Synapse is the reference homeserver implementation of the Matrix protocol, an open-source real-time communication system designed for decentralized messaging, voice, and video. Developed by the Matrix.org Foundation, Synapse enables organizations and individuals to host their own communication server while maintaining the ability to federate with other Matrix homeservers across the internet, creating a distributed network similar to email but for modern chat applications. This stack combines Synapse with Element Web (the flagship Matrix web client), PostgreSQL for robust data persistence, and NGINX for reverse proxy and SSL termination. PostgreSQL provides ACID-compliant storage for chat history, user accounts, and room state data, while NGINX handles client connections, federation traffic on port 8448, and serves the Element web interface. The configuration supports full Matrix federation, allowing users to communicate with anyone on the Matrix network while maintaining complete control over their data. This deployment suits organizations seeking data sovereignty in their communications, privacy-conscious teams wanting end-to-end encrypted chat, or homelab enthusiasts building self-hosted alternatives to Slack or Discord. The combination provides enterprise-grade messaging capabilities with the flexibility to customize features, implement custom authentication systems, or integrate with existing infrastructure while maintaining compatibility with the broader Matrix ecosystem.

Key Features

  • Full Matrix protocol federation enabling communication with users on any Matrix homeserver worldwide
  • End-to-end encryption support with cross-device verification for secure communications
  • PostgreSQL backend with optimized schema for chat message storage and room state management
  • Element Web client integration providing modern chat interface with file sharing and voice/video calls
  • NGINX reverse proxy handling both client traffic and Matrix federation on dedicated port 8448
  • Room management with granular permissions, moderation tools, and custom power levels
  • Bridge support for connecting to IRC, Discord, Telegram, and other chat platforms
  • Application service integration allowing custom bots and Matrix protocol extensions

Common Use Cases

  • 1Corporate communication server replacing proprietary solutions like Slack or Microsoft Teams
  • 2Privacy-focused community chat for open source projects or activist organizations
  • 3Educational institution messaging platform with room-based class organization
  • 4Gaming community server with voice chat integration and custom bot development
  • 5Healthcare or legal organizations requiring HIPAA/GDPR compliant messaging with data residency
  • 6Homelab enthusiasts building personal communication infrastructure for family or friend groups
  • 7Development teams needing integrated chat with custom webhooks and CI/CD notifications

Prerequisites

  • Minimum 2GB RAM recommended for Synapse with PostgreSQL (1GB+ for PostgreSQL, 1GB+ for Synapse)
  • Valid domain name with DNS control for Matrix federation and SSL certificate setup
  • Ports 80, 443, and 8448 accessible from internet for web client and Matrix federation
  • SSL/TLS certificates configured in nginx.conf for HTTPS and federation security
  • Understanding of Matrix concepts like homeserver names, user IDs, and federation requirements
  • Basic NGINX configuration knowledge for customizing reverse proxy settings

For development & testing. Review security settings, change default credentials, and test thoroughly before production use. See Terms

docker-compose.yml

docker-compose.yml
1services:
2 synapse:
3 image: matrixdotorg/synapse:latest
4 environment:
5 SYNAPSE_SERVER_NAME: ${MATRIX_SERVER_NAME}
6 SYNAPSE_REPORT_STATS: "no"
7 volumes:
8 - synapse_data:/data
9 depends_on:
10 postgres:
11 condition: service_healthy
12 networks:
13 - matrix-net
14 restart: unless-stopped
15
16 postgres:
17 image: postgres:15-alpine
18 environment:
19 POSTGRES_USER: ${POSTGRES_USER}
20 POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
21 POSTGRES_DB: synapse
22 POSTGRES_INITDB_ARGS: "--encoding=UTF-8 --lc-collate=C --lc-ctype=C"
23 volumes:
24 - postgres_data:/var/lib/postgresql/data
25 healthcheck:
26 test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
27 interval: 10s
28 timeout: 5s
29 retries: 5
30 networks:
31 - matrix-net
32 restart: unless-stopped
33
34 element:
35 image: vectorim/element-web:latest
36 volumes:
37 - ./element-config.json:/app/config.json:ro
38 depends_on:
39 - synapse
40 networks:
41 - matrix-net
42 restart: unless-stopped
43
44 nginx:
45 image: nginx:alpine
46 ports:
47 - "80:80"
48 - "443:443"
49 - "8448:8448"
50 volumes:
51 - ./nginx.conf:/etc/nginx/nginx.conf:ro
52 - ./certs:/etc/nginx/certs:ro
53 depends_on:
54 - synapse
55 - element
56 networks:
57 - matrix-net
58 restart: unless-stopped
59
60volumes:
61 synapse_data:
62 postgres_data:
63
64networks:
65 matrix-net:
66 driver: bridge

.env Template

.env
1# Matrix Server Name
2MATRIX_SERVER_NAME=matrix.example.com
3
4# PostgreSQL
5POSTGRES_USER=synapse
6POSTGRES_PASSWORD=secure_postgres_password

Usage Notes

  1. 1Generate config: docker run --rm -v ./synapse_data:/data matrixdotorg/synapse:latest generate
  2. 2Element web at https://chat.example.com
  3. 3Federation port 8448 must be accessible
  4. 4Register users: docker exec synapse register_new_matrix_user

Individual Services(4 services)

Copy individual services to mix and match with your existing compose files.

synapse
synapse:
  image: matrixdotorg/synapse:latest
  environment:
    SYNAPSE_SERVER_NAME: ${MATRIX_SERVER_NAME}
    SYNAPSE_REPORT_STATS: "no"
  volumes:
    - synapse_data:/data
  depends_on:
    postgres:
      condition: service_healthy
  networks:
    - matrix-net
  restart: unless-stopped
postgres
postgres:
  image: postgres:15-alpine
  environment:
    POSTGRES_USER: ${POSTGRES_USER}
    POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    POSTGRES_DB: synapse
    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 ${POSTGRES_USER}
    interval: 10s
    timeout: 5s
    retries: 5
  networks:
    - matrix-net
  restart: unless-stopped
element
element:
  image: vectorim/element-web:latest
  volumes:
    - ./element-config.json:/app/config.json:ro
  depends_on:
    - synapse
  networks:
    - matrix-net
  restart: unless-stopped
nginx
nginx:
  image: nginx:alpine
  ports:
    - "80:80"
    - "443:443"
    - "8448:8448"
  volumes:
    - ./nginx.conf:/etc/nginx/nginx.conf:ro
    - ./certs:/etc/nginx/certs:ro
  depends_on:
    - synapse
    - element
  networks:
    - matrix-net
  restart: unless-stopped

Quick Start

terminal
1# 1. Create the compose file
2cat > docker-compose.yml << 'EOF'
3services:
4 synapse:
5 image: matrixdotorg/synapse:latest
6 environment:
7 SYNAPSE_SERVER_NAME: ${MATRIX_SERVER_NAME}
8 SYNAPSE_REPORT_STATS: "no"
9 volumes:
10 - synapse_data:/data
11 depends_on:
12 postgres:
13 condition: service_healthy
14 networks:
15 - matrix-net
16 restart: unless-stopped
17
18 postgres:
19 image: postgres:15-alpine
20 environment:
21 POSTGRES_USER: ${POSTGRES_USER}
22 POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
23 POSTGRES_DB: synapse
24 POSTGRES_INITDB_ARGS: "--encoding=UTF-8 --lc-collate=C --lc-ctype=C"
25 volumes:
26 - postgres_data:/var/lib/postgresql/data
27 healthcheck:
28 test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
29 interval: 10s
30 timeout: 5s
31 retries: 5
32 networks:
33 - matrix-net
34 restart: unless-stopped
35
36 element:
37 image: vectorim/element-web:latest
38 volumes:
39 - ./element-config.json:/app/config.json:ro
40 depends_on:
41 - synapse
42 networks:
43 - matrix-net
44 restart: unless-stopped
45
46 nginx:
47 image: nginx:alpine
48 ports:
49 - "80:80"
50 - "443:443"
51 - "8448:8448"
52 volumes:
53 - ./nginx.conf:/etc/nginx/nginx.conf:ro
54 - ./certs:/etc/nginx/certs:ro
55 depends_on:
56 - synapse
57 - element
58 networks:
59 - matrix-net
60 restart: unless-stopped
61
62volumes:
63 synapse_data:
64 postgres_data:
65
66networks:
67 matrix-net:
68 driver: bridge
69EOF
70
71# 2. Create the .env file
72cat > .env << 'EOF'
73# Matrix Server Name
74MATRIX_SERVER_NAME=matrix.example.com
75
76# PostgreSQL
77POSTGRES_USER=synapse
78POSTGRES_PASSWORD=secure_postgres_password
79EOF
80
81# 3. Start the services
82docker compose up -d
83
84# 4. View logs
85docker compose logs -f

One-Liner

Run this command to download and set up the recipe in one step:

terminal
1curl -fsSL https://docker.recipes/api/recipes/matrix-synapse-stack/run | bash

Troubleshooting

  • Federation not working with 'Host not found' errors: Ensure port 8448 is open and DNS SRV records are configured correctly for your domain
  • Synapse container failing with database connection errors: Check PostgreSQL health check passes and POSTGRES_PASSWORD environment variable matches Synapse configuration
  • Element web showing 'Failed to connect to homeserver': Verify nginx.conf properly proxies /_matrix/ endpoints to Synapse container and SSL certificates are valid
  • High memory usage from PostgreSQL: Tune shared_buffers and work_mem in postgresql.conf, consider enabling connection pooling in Synapse configuration
  • Registration failing with 'User already exists': Use register_new_matrix_user command with --admin flag for admin users, or enable open registration in homeserver.yaml
  • Slow message delivery in large rooms: Enable worker mode in Synapse configuration and consider implementing Redis for better performance scaling

Community Notes

Loading...
Loading notes...

Download Recipe Kit

Get all files in a ready-to-deploy package

Includes docker-compose.yml, .env template, README, and license

Ad Space