feat: Sample Matrix swarm deployment compose file (#387)
All checks were successful
ci/woodpecker/push/infra Pipeline was successful
All checks were successful
ci/woodpecker/push/infra Pipeline was successful
Standalone Synapse + Element Web deployment for Docker Swarm/Portainer. Separate infrastructure from Mosaic Stack (same pattern as Authentik). Includes: Synapse, Element Web, dedicated PostgreSQL, optional coturn. Traefik labels match existing Stack conventions. Refs #387 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
206
docker/docker-compose.sample.matrix.yml
Normal file
206
docker/docker-compose.sample.matrix.yml
Normal file
@@ -0,0 +1,206 @@
|
||||
# ==============================================
|
||||
# Matrix (Synapse + Element) - Sample Swarm Deployment
|
||||
# ==============================================
|
||||
#
|
||||
# Standalone Matrix homeserver deployment for use with Mosaic Stack.
|
||||
# This is SEPARATE infrastructure — not part of the Mosaic Stack itself.
|
||||
# Mosaic connects to it via MATRIX_HOMESERVER_URL environment variable.
|
||||
#
|
||||
# Also serves: personal communications, GoToSocial bridges, other projects.
|
||||
#
|
||||
# Usage (Docker Swarm via Portainer):
|
||||
# 1. Create a new stack in Portainer
|
||||
# 2. Paste this file or point to the repo
|
||||
# 3. Set environment variables in Portainer's env var section
|
||||
# 4. Deploy the stack
|
||||
#
|
||||
# Usage (Docker Swarm CLI):
|
||||
# 1. cp docker-compose.sample.matrix.env .env
|
||||
# 2. nano .env # Configure
|
||||
# 3. docker stack deploy -c docker-compose.sample.matrix.yml matrix
|
||||
#
|
||||
# Post-Deploy Setup:
|
||||
# 1. Generate Synapse config (first run only):
|
||||
# docker exec <synapse_container> python -m synapse.app.homeserver \
|
||||
# --server-name ${MATRIX_DOMAIN} --report-stats no \
|
||||
# --generate-config --config-path /data/homeserver.yaml
|
||||
#
|
||||
# 2. Create admin account:
|
||||
# docker exec -it <synapse_container> register_new_matrix_user \
|
||||
# -u admin -a -c /data/homeserver.yaml http://localhost:8008
|
||||
#
|
||||
# 3. Create Mosaic bot account:
|
||||
# docker exec -it <synapse_container> register_new_matrix_user \
|
||||
# -u mosaic-bot -c /data/homeserver.yaml http://localhost:8008
|
||||
#
|
||||
# 4. Generate bot access token:
|
||||
# curl -X POST http://localhost:8008/_matrix/client/v3/login \
|
||||
# -d '{"type":"m.login.password","user":"mosaic-bot","password":"<password>"}'
|
||||
#
|
||||
# 5. Set MATRIX_ACCESS_TOKEN in Mosaic Stack .env
|
||||
#
|
||||
# Required Environment Variables:
|
||||
# MATRIX_DOMAIN=matrix.example.com # Synapse server name (permanent!)
|
||||
# ELEMENT_DOMAIN=chat.example.com # Element Web domain
|
||||
# POSTGRES_PASSWORD=<strong-password> # Synapse database password
|
||||
#
|
||||
# Optional Environment Variables:
|
||||
# SYNAPSE_IMAGE_TAG=latest # Synapse version
|
||||
# ELEMENT_IMAGE_TAG=latest # Element Web version
|
||||
# POSTGRES_IMAGE_TAG=16-alpine # PostgreSQL version
|
||||
# TRAEFIK_ENTRYPOINT=websecure # Traefik entrypoint name
|
||||
# TRAEFIK_CERTRESOLVER=letsencrypt # Traefik cert resolver
|
||||
# TRAEFIK_DOCKER_NETWORK=traefik-public # Traefik network name
|
||||
# SYNAPSE_ENABLE_REGISTRATION=false # Public registration
|
||||
# SYNAPSE_REPORT_STATS=no # Anonymous stats reporting
|
||||
# SYNAPSE_MAX_UPLOAD_SIZE=50M # Max file upload size
|
||||
#
|
||||
# Connecting to Mosaic Stack:
|
||||
# Add to your Mosaic Stack .env:
|
||||
# MATRIX_HOMESERVER_URL=http://synapse:8008 (if same Docker network)
|
||||
# MATRIX_HOMESERVER_URL=https://matrix.example.com (if external)
|
||||
# MATRIX_ACCESS_TOKEN=<bot access token from step 4>
|
||||
# MATRIX_BOT_USER_ID=@mosaic-bot:matrix.example.com
|
||||
#
|
||||
# ==============================================
|
||||
|
||||
services:
|
||||
# ======================
|
||||
# Synapse (Matrix Homeserver)
|
||||
# ======================
|
||||
synapse:
|
||||
image: matrixdotorg/synapse:${SYNAPSE_IMAGE_TAG:-latest}
|
||||
environment:
|
||||
SYNAPSE_SERVER_NAME: ${MATRIX_DOMAIN}
|
||||
SYNAPSE_REPORT_STATS: ${SYNAPSE_REPORT_STATS:-no}
|
||||
SYNAPSE_CONFIG_DIR: /data
|
||||
SYNAPSE_DATA_DIR: /data
|
||||
SYNAPSE_LOG_LEVEL: ${SYNAPSE_LOG_LEVEL:-WARNING}
|
||||
# Database connection (external PostgreSQL or bundled)
|
||||
POSTGRES_HOST: synapse-postgres
|
||||
POSTGRES_PORT: 5432
|
||||
POSTGRES_DB: ${SYNAPSE_POSTGRES_DB:-synapse}
|
||||
POSTGRES_USER: ${SYNAPSE_POSTGRES_USER:-synapse}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
||||
volumes:
|
||||
- synapse-data:/data
|
||||
- synapse-media:/data/media_store
|
||||
depends_on:
|
||||
synapse-postgres:
|
||||
condition: service_healthy
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "curl -fSs http://localhost:8008/health || exit 1"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 30s
|
||||
networks:
|
||||
- internal
|
||||
- traefik-public
|
||||
deploy:
|
||||
restart_policy:
|
||||
condition: on-failure
|
||||
delay: 10s
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.matrix.rule=Host(`${MATRIX_DOMAIN}`)"
|
||||
- "traefik.http.routers.matrix.entrypoints=${TRAEFIK_ENTRYPOINT:-websecure}"
|
||||
- "traefik.http.routers.matrix.tls=${TRAEFIK_TLS_ENABLED:-true}"
|
||||
- "traefik.http.routers.matrix.tls.certresolver=${TRAEFIK_CERTRESOLVER:-}"
|
||||
- "traefik.http.services.matrix.loadbalancer.server.port=8008"
|
||||
- "traefik.docker.network=${TRAEFIK_DOCKER_NETWORK:-traefik-public}"
|
||||
# Well-known delegation (optional — for .well-known/matrix/server)
|
||||
# - "traefik.http.routers.matrix-wellknown.rule=Host(`${MATRIX_DOMAIN}`) && PathPrefix(`/.well-known/matrix`)"
|
||||
|
||||
# ======================
|
||||
# Element Web (Matrix Client)
|
||||
# ======================
|
||||
element-web:
|
||||
image: vectorim/element-web:${ELEMENT_IMAGE_TAG:-latest}
|
||||
volumes:
|
||||
- element-config:/app/config
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:80 || exit 1"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
networks:
|
||||
- internal
|
||||
- traefik-public
|
||||
deploy:
|
||||
restart_policy:
|
||||
condition: on-failure
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.element.rule=Host(`${ELEMENT_DOMAIN}`)"
|
||||
- "traefik.http.routers.element.entrypoints=${TRAEFIK_ENTRYPOINT:-websecure}"
|
||||
- "traefik.http.routers.element.tls=${TRAEFIK_TLS_ENABLED:-true}"
|
||||
- "traefik.http.routers.element.tls.certresolver=${TRAEFIK_CERTRESOLVER:-}"
|
||||
- "traefik.http.services.element.loadbalancer.server.port=80"
|
||||
- "traefik.docker.network=${TRAEFIK_DOCKER_NETWORK:-traefik-public}"
|
||||
|
||||
# ======================
|
||||
# PostgreSQL (Synapse Database)
|
||||
# ======================
|
||||
# Separate from Mosaic's PostgreSQL — Synapse manages its own schema.
|
||||
# If you prefer a shared PostgreSQL instance, remove this service and
|
||||
# point POSTGRES_HOST to your existing PostgreSQL with a separate database.
|
||||
synapse-postgres:
|
||||
image: postgres:${POSTGRES_IMAGE_TAG:-16-alpine}
|
||||
environment:
|
||||
POSTGRES_DB: ${SYNAPSE_POSTGRES_DB:-synapse}
|
||||
POSTGRES_USER: ${SYNAPSE_POSTGRES_USER:-synapse}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
||||
POSTGRES_INITDB_ARGS: "--encoding=UTF-8 --lc-collate=C --lc-ctype=C"
|
||||
volumes:
|
||||
- synapse-postgres-data:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test:
|
||||
[
|
||||
"CMD-SHELL",
|
||||
"pg_isready -U ${SYNAPSE_POSTGRES_USER:-synapse} -d ${SYNAPSE_POSTGRES_DB:-synapse}",
|
||||
]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
networks:
|
||||
- internal
|
||||
deploy:
|
||||
restart_policy:
|
||||
condition: on-failure
|
||||
|
||||
# ======================
|
||||
# coturn (TURN/STUN for VoIP) - Optional
|
||||
# ======================
|
||||
# Uncomment if you need voice/video calls through NAT.
|
||||
# Requires additional DNS and port configuration.
|
||||
#
|
||||
# coturn:
|
||||
# image: coturn/coturn:latest
|
||||
# environment:
|
||||
# TURN_REALM: ${MATRIX_DOMAIN}
|
||||
# TURN_SECRET: ${COTURN_SECRET}
|
||||
# ports:
|
||||
# - "3478:3478/tcp"
|
||||
# - "3478:3478/udp"
|
||||
# - "5349:5349/tcp"
|
||||
# - "5349:5349/udp"
|
||||
# - "49152-49200:49152-49200/udp"
|
||||
# networks:
|
||||
# - internal
|
||||
# deploy:
|
||||
# restart_policy:
|
||||
# condition: on-failure
|
||||
|
||||
volumes:
|
||||
synapse-data:
|
||||
synapse-media:
|
||||
synapse-postgres-data:
|
||||
element-config:
|
||||
|
||||
networks:
|
||||
internal:
|
||||
driver: overlay
|
||||
traefik-public:
|
||||
external: true
|
||||
name: ${TRAEFIK_DOCKER_NETWORK:-traefik-public}
|
||||
Reference in New Issue
Block a user