Initial commit: Matrix stack (Synapse + Synapse-Admin + Element Web) behind Traefik

Fully dockerized deployment with automatic Let's Encrypt certificates via
Traefik's static file provider (no docker.sock needed), bind-mounted data
folders instead of named volumes, and domain/secrets kept out of git via
.env + rendered templates.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
snoopy
2026-09-04 16:40:59 +02:00
commit 708312c80c
13 changed files with 456 additions and 0 deletions

103
docker-compose.yml Normal file
View File

@@ -0,0 +1,103 @@
networks:
web:
name: matrix_web
internal:
name: matrix_internal
services:
traefik:
image: traefik:v3.5
container_name: matrix-traefik
restart: unless-stopped
security_opt:
- no-new-privileges:true
networks:
- web
ports:
- "80:80"
- "443:443"
environment:
- TRAEFIK_DASHBOARD_AUTH=${TRAEFIK_DASHBOARD_AUTH}
command:
- --api.dashboard=true
- --providers.file.directory=/etc/traefik/dynamic
- --providers.file.watch=true
- --entrypoints.web.address=:80
- --entrypoints.web.http.redirections.entrypoint.to=websecure
- --entrypoints.web.http.redirections.entrypoint.scheme=https
- --entrypoints.web.http.redirections.entrypoint.permanent=true
- --entrypoints.websecure.address=:443
- --certificatesresolvers.letsencrypt.acme.email=${ACME_EMAIL}
- --certificatesresolvers.letsencrypt.acme.storage=/etc/traefik/acme/acme.json
- --certificatesresolvers.letsencrypt.acme.httpchallenge=true
- --certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web
- --log.level=INFO
- --accesslog=true
volumes:
- ./traefik/dynamic:/etc/traefik/dynamic:ro
- ./traefik/acme:/etc/traefik/acme
postgres:
image: postgres:16-alpine
container_name: matrix-postgres
restart: unless-stopped
security_opt:
- no-new-privileges:true
networks:
- internal
environment:
- POSTGRES_DB=${POSTGRES_DB}
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_INITDB_ARGS=--encoding=UTF8 --locale=C
- PGDATA=/var/lib/postgresql/data/pgdata
volumes:
- ./postgres/data:/var/lib/postgresql/data
synapse:
image: matrixdotorg/synapse:latest
container_name: matrix-synapse
restart: unless-stopped
security_opt:
- no-new-privileges:true
depends_on:
- postgres
networks:
- web
- internal
volumes:
- ./synapse/data:/data
element:
image: vectorim/element-web:latest
container_name: matrix-element
restart: unless-stopped
security_opt:
- no-new-privileges:true
networks:
- web
volumes:
- ./element/config/config.json:/app/config.json:ro
synapse-admin:
image: awesometechnologies/synapse-admin:latest
container_name: matrix-synapse-admin
restart: unless-stopped
security_opt:
- no-new-privileges:true
networks:
- web
volumes:
- ./synapse-admin/config/config.json:/app/config.json:ro
wellknown:
image: nginx:1.27-alpine
container_name: matrix-wellknown
restart: unless-stopped
security_opt:
- no-new-privileges:true
networks:
- web
volumes:
- ./wellknown/html:/usr/share/nginx/html:ro
- ./wellknown/nginx.conf:/etc/nginx/conf.d/default.conf:ro