# ============================================== # Matrix Dev Environment (Synapse + Element Web) # ============================================== # # Development-only overlay for testing the Matrix bridge locally. # NOT for production — use docker-compose.sample.matrix.yml for production. # # Usage: # docker compose -f docker/docker-compose.yml -f docker/docker-compose.matrix.yml up -d # # Or with Makefile: # make matrix-up # # This overlay: # - Adds Synapse homeserver (localhost:8008) using shared PostgreSQL # - Adds Element Web client (localhost:8501) # - Creates a separate 'synapse' database in the shared PostgreSQL instance # - Enables open registration for easy dev testing # # After first startup, create the bot account: # docker/matrix/scripts/setup-bot.sh # # ============================================== services: # ====================== # Synapse Database Init # ====================== # Creates the 'synapse' database and user in the shared PostgreSQL instance. # Runs once and exits — idempotent, safe to run repeatedly. synapse-db-init: image: postgres:17-alpine container_name: mosaic-synapse-db-init restart: "no" environment: PGHOST: postgres PGPORT: 5432 PGUSER: ${POSTGRES_USER:-mosaic} PGPASSWORD: ${POSTGRES_PASSWORD:-mosaic_dev_password} SYNAPSE_DB: ${SYNAPSE_POSTGRES_DB:-synapse} SYNAPSE_USER: ${SYNAPSE_POSTGRES_USER:-synapse} SYNAPSE_PASSWORD: ${SYNAPSE_POSTGRES_PASSWORD:-synapse_dev_password} entrypoint: ["sh", "-c"] command: - | until pg_isready -h postgres -p 5432 -U $${PGUSER}; do echo "Waiting for PostgreSQL..." sleep 2 done echo "PostgreSQL is ready. Creating Synapse database and user..." psql -h postgres -U $${PGUSER} -tc "SELECT 1 FROM pg_roles WHERE rolname='$${SYNAPSE_USER}'" | grep -q 1 || \ psql -h postgres -U $${PGUSER} -c "CREATE USER $${SYNAPSE_USER} WITH PASSWORD '$${SYNAPSE_PASSWORD}';" psql -h postgres -U $${PGUSER} -tc "SELECT 1 FROM pg_database WHERE datname='$${SYNAPSE_DB}'" | grep -q 1 || \ psql -h postgres -U $${PGUSER} -c "CREATE DATABASE $${SYNAPSE_DB} OWNER $${SYNAPSE_USER} ENCODING 'UTF8' LC_COLLATE='C' LC_CTYPE='C' TEMPLATE template0;" echo "Synapse database ready: $${SYNAPSE_DB}" depends_on: postgres: condition: service_healthy networks: - mosaic-internal # ====================== # Synapse (Matrix Homeserver) # ====================== synapse: image: matrixdotorg/synapse:latest container_name: mosaic-synapse restart: unless-stopped environment: SYNAPSE_CONFIG_DIR: /data SYNAPSE_CONFIG_PATH: /data/homeserver.yaml ports: - "${SYNAPSE_CLIENT_PORT:-8008}:8008" - "${SYNAPSE_FEDERATION_PORT:-8448}:8448" volumes: - /opt/mosaic/synapse/homeserver.yaml:/data/homeserver.yaml:ro - /opt/mosaic/synapse/media_store:/data/media_store - /opt/mosaic/synapse/keys:/data/keys depends_on: postgres: condition: service_healthy synapse-db-init: condition: service_completed_successfully healthcheck: test: ["CMD-SHELL", "curl -fSs http://localhost:8008/health || exit 1"] interval: 15s timeout: 5s retries: 5 start_period: 30s networks: - mosaic-internal labels: com.mosaic.service: "matrix-synapse" com.mosaic.description: "Matrix homeserver (dev)" # ====================== # Element Web (Matrix Client) # ====================== element-web: image: vectorim/element-web:latest container_name: mosaic-element-web restart: unless-stopped ports: - "${ELEMENT_PORT:-8501}:80" volumes: - /opt/mosaic/synapse/element-config.json:/app/config.json:ro depends_on: synapse: condition: service_healthy healthcheck: test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:80 || exit 1"] interval: 30s timeout: 5s retries: 3 start_period: 10s networks: - mosaic-internal labels: com.mosaic.service: "matrix-element" com.mosaic.description: "Element Web client (dev)"