Files
ess-docker-compose/compose-variants/docker-compose.local.yml
T
wmair 4e43a6f713 Add custom Docker registry and hardened image support
All image references in docker-compose.yml and docker-compose.local.yml
are replaced with ${IMAGE_VAR:-default} env var syntax, so compose files
work standalone without .env while deploy.sh writes resolved image paths.

deploy.sh gains two new prompts:
- Custom registry prefix (prepended to all image names)
- Hardened images from dhi.io for Redis/PostgreSQL/Caddy (takes priority
  over custom registry for those three)

Compared to PR #10: interactive prompts instead of hardcoded vars,
no sed-based compose file mutation, all 14 images covered (PR #10 missed
element-admin, element-call, lk-jwt-service, and all 3 bridges), and
standalone compose usage is preserved via :-default fallbacks.

SETUP.md and README.md document the feature including a note on
pull-through cache registries (Harbor/Artifactory/Nexus) that require
the full docker.io/ path prefix in image names.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 09:55:18 +01:00

245 lines
6.5 KiB
YAML

services:
# PostgreSQL Database
postgres:
image: ${POSTGRES_IMAGE:-postgres:16-alpine}
container_name: matrix-postgres
restart: unless-stopped
environment:
POSTGRES_DB: synapse
POSTGRES_USER: synapse
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-changeme}
POSTGRES_INITDB_ARGS: --encoding=UTF-8 --lc-collate=C --lc-ctype=C
volumes:
- ./postgres/data:/var/lib/postgresql/data
- ./postgres/init:/docker-entrypoint-initdb.d
networks:
- matrix-network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U synapse"]
interval: 10s
timeout: 5s
retries: 5
# Matrix Synapse Server
synapse:
image: ${SYNAPSE_IMAGE:-matrixdotorg/synapse:latest}
container_name: matrix-synapse
restart: unless-stopped
environment:
SYNAPSE_CONFIG_PATH: /data/homeserver.yaml
SSL_CERT_FILE: /certs/caddy-ca.crt
volumes:
- ./synapse/data:/data
- ./mas/certs:/certs:ro
- ./bridges:/bridges:ro
- ./appservices:/appservices:ro
# Ports exposed only to internal network - access via Caddy
expose:
- "8008"
networks:
- matrix-network
depends_on:
postgres:
condition: service_healthy
extra_hosts:
- "auth.example.test:host-gateway"
- "matrix.example.test:host-gateway"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8008/health"]
interval: 30s
timeout: 10s
retries: 3
# Element Web Client
element:
image: ${ELEMENT_IMAGE:-vectorim/element-web:latest}
container_name: matrix-element
restart: unless-stopped
volumes:
- ./element/config/config.json:/app/config.json:ro
# Accessed via Caddy
expose:
- "80"
networks:
- matrix-network
depends_on:
- synapse
# LiveKit SFU — media server for Element Call (Optional - use profile "element-call" to enable)
livekit:
profiles:
- element-call
image: ${LIVEKIT_IMAGE:-livekit/livekit-server:latest}
container_name: matrix-livekit
restart: unless-stopped
ports:
- "7881:7881/tcp"
- "50100-50200:50100-50200/udp"
expose:
- "7880"
volumes:
- ./livekit/livekit.yaml:/livekit.yaml
command: --config /livekit.yaml
networks:
- matrix-network
# LiveKit JWT Service — issues LiveKit tokens to authenticated Matrix users
lk-jwt-service:
profiles:
- element-call
image: ${LK_JWT_IMAGE:-ghcr.io/element-hq/lk-jwt-service:latest}
container_name: matrix-lk-jwt
restart: unless-stopped
expose:
- "8080"
environment:
- LIVEKIT_URL=wss://${RTC_DOMAIN}/livekit/sfu
- LIVEKIT_KEY=livekit-key
- LIVEKIT_SECRET=${LIVEKIT_SECRET}
- LIVEKIT_FULL_ACCESS_HOMESERVERS=${MATRIX_DOMAIN}
networks:
- matrix-network
depends_on:
- livekit
# Redis for Authelia session storage
redis:
profiles:
- authelia # Only started when Authelia profile is active
image: ${REDIS_IMAGE:-redis:7-alpine}
container_name: matrix-redis
restart: unless-stopped
networks:
- matrix-network
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
# Authelia SSO (Optional - use profile "authelia" to enable)
authelia:
profiles:
- authelia # Only started when Authelia profile is active
image: ${AUTHELIA_IMAGE:-authelia/authelia:latest}
container_name: matrix-authelia
restart: unless-stopped
environment:
TZ: Europe/Berlin
AUTHELIA_SESSION_SECRET: ${AUTHELIA_SESSION_SECRET}
AUTHELIA_STORAGE_ENCRYPTION_KEY: ${AUTHELIA_STORAGE_ENCRYPTION_KEY}
AUTHELIA_JWT_SECRET: ${AUTHELIA_JWT_SECRET}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- ./authelia/config:/config
# Accessed via Caddy
expose:
- "9091"
networks:
- matrix-network
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
# Matrix Authentication Service (MAS)
mas:
image: ${MAS_IMAGE:-ghcr.io/element-hq/matrix-authentication-service:latest}
container_name: matrix-mas
restart: unless-stopped
environment:
MAS_CONFIG: /config/config.yaml
SSL_CERT_FILE: /certs/caddy-ca.crt
volumes:
- ./mas/config:/config:ro
- ./mas/data:/data
- ./mas/certs:/certs:ro
# Accessed via Caddy
expose:
- "8080"
- "8081"
networks:
- matrix-network
depends_on:
postgres:
condition: service_healthy
# Note: Authelia dependency removed - works with or without Authelia
extra_hosts:
- "authelia.example.test:host-gateway" # Harmless if Authelia not running
# Healthcheck disabled: MAS uses distroless image without curl
# healthcheck:
# test: ["CMD", "curl", "-f", "http://localhost:8081/health"]
# interval: 30s
# timeout: 10s
# retries: 3
# Caddy Reverse Proxy (HTTPS termination)
caddy:
image: ${CADDY_IMAGE:-caddy:2-alpine}
container_name: matrix-caddy
restart: unless-stopped
ports:
- "443:443"
- "80:80"
- "2019:2019" # Admin API
volumes:
- ./caddy/Caddyfile:/etc/caddy/Caddyfile:ro
- ./caddy/data:/data
- ./caddy/config:/config
networks:
- matrix-network
depends_on:
- synapse
- element
- mas
# Note: Authelia dependency removed - works with or without Authelia
# mautrix-telegram Bridge
mautrix-telegram:
image: ${TELEGRAM_IMAGE:-dock.mau.dev/mautrix/telegram:latest}
container_name: matrix-bridge-telegram
restart: unless-stopped
volumes:
- ./bridges/telegram/config:/data
networks:
- matrix-network
depends_on:
synapse:
condition: service_healthy
# mautrix-whatsapp Bridge
mautrix-whatsapp:
image: ${WHATSAPP_IMAGE:-dock.mau.dev/mautrix/whatsapp:latest}
container_name: matrix-bridge-whatsapp
restart: unless-stopped
volumes:
- ./bridges/whatsapp/config:/data
networks:
- matrix-network
depends_on:
synapse:
condition: service_healthy
# mautrix-signal Bridge
mautrix-signal:
image: ${SIGNAL_IMAGE:-dock.mau.dev/mautrix/signal:latest}
container_name: matrix-bridge-signal
restart: unless-stopped
volumes:
- ./bridges/signal/config:/data
networks:
- matrix-network
depends_on:
synapse:
condition: service_healthy
networks:
matrix-network:
driver: bridge
volumes:
postgres-data:
synapse-data:
mas-data: