diff --git a/docker/docker-compose.sample.matrix.yml b/docker/docker-compose.sample.matrix.yml new file mode 100644 index 0000000..5f71d48 --- /dev/null +++ b/docker/docker-compose.sample.matrix.yml @@ -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 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 register_new_matrix_user \ +# -u admin -a -c /data/homeserver.yaml http://localhost:8008 +# +# 3. Create Mosaic bot account: +# docker exec -it 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":""}' +# +# 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= # 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= +# 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}