feat(ess-pro/compose): deploy Element Server Suite Pro via Compose
initial commit of the converted role from helm charts for qubernetis to compose ansible role
This commit is contained in:
parent
c11f019aae
commit
32eca6b923
33 changed files with 1906 additions and 0 deletions
304
roles/ess_pro_compose/templates/compose.yml.j2
Normal file
304
roles/ess_pro_compose/templates/compose.yml.j2
Normal file
|
|
@ -0,0 +1,304 @@
|
|||
# {{ ansible_managed }}
|
||||
# ESS Pro v{{ ess_chart_version }} on docker compose — rendered by ess_pro_compose.
|
||||
# Topology mirrors the Helm chart: HAProxy fronts all Synapse traffic,
|
||||
# synapse-main is the Python homeserver, synapse-fed-reader is the Rust Pro
|
||||
# worker handling federation reads, MAS handles all auth, LiveKit + lk-jwt
|
||||
# serve Element Call.
|
||||
|
||||
name: {{ ess_compose_project_name }}
|
||||
|
||||
networks:
|
||||
{{ ess_compose_traefik_network }}:
|
||||
external: true
|
||||
{{ ess_compose_internal_network }}:
|
||||
driver: bridge
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
synapse_media:
|
||||
|
||||
services:
|
||||
|
||||
# ===========================================================================
|
||||
# Data plane
|
||||
# ===========================================================================
|
||||
|
||||
postgres:
|
||||
image: {{ ess_images.postgres }}
|
||||
container_name: postgres
|
||||
restart: unless-stopped
|
||||
networks: [ {{ ess_compose_internal_network }} ]
|
||||
environment:
|
||||
LC_COLLATE: "C"
|
||||
LC_CTYPE: "C"
|
||||
PGDATA: /var/lib/postgresql/data/pgdata
|
||||
POSTGRES_INITDB_ARGS: "-E UTF8"
|
||||
POSTGRES_PASSWORD_FILE: /secrets/ess-generated/POSTGRES_ADMIN_PASSWORD
|
||||
command:
|
||||
- postgres
|
||||
- "-c"
|
||||
- "max_connections={{ ess_postgres_max_connections }}"
|
||||
- "-c"
|
||||
- "shared_buffers={{ ess_postgres_shared_buffers }}"
|
||||
- "-c"
|
||||
- "effective_cache_size={{ ess_postgres_effective_cache_size }}"
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
- {{ ess_compose_secrets_dir }}:/secrets/ess-generated:ro
|
||||
- {{ ess_compose_conf_dir }}/postgres/configure-dbs.sh:/docker-entrypoint-initdb.d/init-ess-dbs.sh:ro
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U postgres"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
|
||||
redis:
|
||||
image: {{ ess_images.redis }}
|
||||
container_name: redis
|
||||
restart: unless-stopped
|
||||
networks: [ {{ ess_compose_internal_network }} ]
|
||||
command: ["/usr/local/etc/redis/redis.conf"]
|
||||
volumes:
|
||||
- {{ ess_compose_conf_dir }}/redis/redis.conf:/usr/local/etc/redis/redis.conf:ro
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 10s
|
||||
timeout: 3s
|
||||
retries: 5
|
||||
|
||||
# ===========================================================================
|
||||
# Synapse (Python main + Rust federation-reader worker)
|
||||
# ===========================================================================
|
||||
|
||||
synapse-main:
|
||||
image: {{ ess_images.synapse }}
|
||||
container_name: synapse-main
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
postgres: { condition: service_healthy }
|
||||
redis: { condition: service_healthy }
|
||||
networks: [ {{ ess_compose_internal_network }} ]
|
||||
command: ["python3", "-m", "synapse.app.homeserver", "-c", "/conf/homeserver.yaml"]
|
||||
volumes:
|
||||
- {{ ess_compose_conf_dir }}/synapse/homeserver.yaml:/conf/homeserver.yaml:ro
|
||||
- {{ ess_compose_conf_dir }}/synapse/log_config.yaml:/conf/log_config.yaml:ro
|
||||
- {{ ess_compose_secrets_dir }}:/secrets/ess-generated:ro
|
||||
- synapse_media:/media
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-fsS", "http://localhost:8080/health"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 30
|
||||
start_period: 60s
|
||||
|
||||
{% for i in range(ess_synapse_fed_reader_replicas | int) %}
|
||||
synapse-fed-reader-{{ i }}:
|
||||
image: {{ ess_images.synapse_pro_worker }}
|
||||
container_name: synapse-fed-reader-{{ i }}
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
synapse-main: { condition: service_healthy }
|
||||
networks: [ {{ ess_compose_internal_network }} ]
|
||||
environment:
|
||||
APP_CONFIG_FILEPATH: /conf/federation-reader.yaml
|
||||
volumes:
|
||||
- {{ ess_compose_conf_dir }}/synapse/federation-reader.yaml:/conf/federation-reader.yaml:ro
|
||||
- {{ ess_compose_secrets_dir }}:/secrets/ess-generated:ro
|
||||
|
||||
{% endfor %}
|
||||
# ===========================================================================
|
||||
# Matrix Authentication Service (4 listeners)
|
||||
# ===========================================================================
|
||||
|
||||
mas:
|
||||
image: {{ ess_images.mas }}
|
||||
container_name: mas
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
postgres: { condition: service_healthy }
|
||||
networks:
|
||||
- {{ ess_compose_internal_network }}
|
||||
- {{ ess_compose_traefik_network }}
|
||||
environment:
|
||||
MAS_CONFIG: /conf/mas-config.yaml
|
||||
command: ["server", "--no-migrate"]
|
||||
volumes:
|
||||
- {{ ess_compose_conf_dir }}/mas/config.yaml:/conf/mas-config.yaml:ro
|
||||
- {{ ess_compose_secrets_dir }}:/secrets/ess-generated:ro
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-fsS", "http://localhost:8081/health"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 20
|
||||
start_period: 30s
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network={{ ess_compose_traefik_network }}"
|
||||
- "traefik.http.routers.ess-mas.rule=Host(`{{ ess_hostnames.mas }}`)"
|
||||
- "traefik.http.routers.ess-mas.entrypoints={{ ess_compose_traefik_entrypoint }}"
|
||||
- "traefik.http.routers.ess-mas.tls=true"
|
||||
{% if ess_compose_traefik_certresolver | length > 0 %}
|
||||
- "traefik.http.routers.ess-mas.tls.certresolver={{ ess_compose_traefik_certresolver }}"
|
||||
{% endif %}
|
||||
- "traefik.http.services.ess-mas.loadbalancer.server.port=8080"
|
||||
|
||||
# MAS root listener (port 8082) is mounted as a separate Traefik router so
|
||||
# /.well-known/openid-configuration on the apex of the mas host is reachable.
|
||||
# We attach a second router on the same service via a path rule.
|
||||
|
||||
# ===========================================================================
|
||||
# HAProxy — fronts all Synapse + well-known traffic
|
||||
# ===========================================================================
|
||||
|
||||
haproxy:
|
||||
image: {{ ess_images.haproxy }}
|
||||
container_name: haproxy
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
synapse-main: { condition: service_healthy }
|
||||
networks:
|
||||
- {{ ess_compose_internal_network }}
|
||||
- {{ ess_compose_traefik_network }}
|
||||
command: ["-f", "/usr/local/etc/haproxy/haproxy.cfg", "-dW"]
|
||||
volumes:
|
||||
- {{ ess_compose_conf_dir }}/haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
|
||||
- {{ ess_compose_conf_dir }}/haproxy/path_map_file:/synapse/path_map_file:ro
|
||||
- {{ ess_compose_conf_dir }}/haproxy/path_map_file_get:/synapse/path_map_file_get:ro
|
||||
- {{ ess_compose_conf_dir }}/haproxy/429.http:/synapse/429.http:ro
|
||||
- {{ ess_compose_conf_dir }}/haproxy/admin-allow-ips.lst:/synapse/admin-allow-ips.lst:ro
|
||||
- {{ ess_compose_conf_dir }}/haproxy/well-known/server:/well-known/server:ro
|
||||
- {{ ess_compose_conf_dir }}/haproxy/well-known/client:/well-known/client:ro
|
||||
- {{ ess_compose_conf_dir }}/haproxy/well-known/support:/well-known/support:ro
|
||||
- {{ ess_compose_conf_dir }}/haproxy/well-known/element.json:/well-known/element.json:ro
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "-q", "-O-", "http://localhost:8406/synapse_ready"]
|
||||
interval: 15s
|
||||
timeout: 5s
|
||||
retries: 20
|
||||
start_period: 90s
|
||||
labels:
|
||||
# matrix.<server> -> HAProxy frontend synapse-http-in (port 8008)
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network={{ ess_compose_traefik_network }}"
|
||||
- "traefik.http.routers.ess-synapse.rule=Host(`{{ ess_hostnames.synapse }}`)"
|
||||
- "traefik.http.routers.ess-synapse.entrypoints={{ ess_compose_traefik_entrypoint }}"
|
||||
- "traefik.http.routers.ess-synapse.tls=true"
|
||||
{% if ess_compose_traefik_certresolver | length > 0 %}
|
||||
- "traefik.http.routers.ess-synapse.tls.certresolver={{ ess_compose_traefik_certresolver }}"
|
||||
{% endif %}
|
||||
- "traefik.http.routers.ess-synapse.service=ess-synapse"
|
||||
- "traefik.http.services.ess-synapse.loadbalancer.server.port=8008"
|
||||
# <server>/.well-known/matrix -> HAProxy well-known-in (port 8010)
|
||||
- "traefik.http.routers.ess-wellknown.rule=Host(`{{ ess_server_name }}`) && PathPrefix(`/.well-known/matrix`)"
|
||||
- "traefik.http.routers.ess-wellknown.entrypoints={{ ess_compose_traefik_entrypoint }}"
|
||||
- "traefik.http.routers.ess-wellknown.tls=true"
|
||||
{% if ess_compose_traefik_certresolver | length > 0 %}
|
||||
- "traefik.http.routers.ess-wellknown.tls.certresolver={{ ess_compose_traefik_certresolver }}"
|
||||
{% endif %}
|
||||
- "traefik.http.routers.ess-wellknown.service=ess-wellknown"
|
||||
- "traefik.http.services.ess-wellknown.loadbalancer.server.port=8010"
|
||||
|
||||
# ===========================================================================
|
||||
# Element Web (browser client)
|
||||
# ===========================================================================
|
||||
|
||||
element-web:
|
||||
image: {{ ess_images.element_web }}
|
||||
container_name: element-web
|
||||
restart: unless-stopped
|
||||
networks: [ {{ ess_compose_traefik_network }} ]
|
||||
volumes:
|
||||
- {{ ess_compose_conf_dir }}/element-web/config.json:/app/config.json:ro
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network={{ ess_compose_traefik_network }}"
|
||||
- "traefik.http.routers.ess-element-web.rule=Host(`{{ ess_hostnames.element_web }}`)"
|
||||
- "traefik.http.routers.ess-element-web.entrypoints={{ ess_compose_traefik_entrypoint }}"
|
||||
- "traefik.http.routers.ess-element-web.tls=true"
|
||||
{% if ess_compose_traefik_certresolver | length > 0 %}
|
||||
- "traefik.http.routers.ess-element-web.tls.certresolver={{ ess_compose_traefik_certresolver }}"
|
||||
{% endif %}
|
||||
- "traefik.http.services.ess-element-web.loadbalancer.server.port=8080"
|
||||
|
||||
# ===========================================================================
|
||||
# Element Admin (admin panel)
|
||||
# ===========================================================================
|
||||
|
||||
element-admin:
|
||||
image: {{ ess_images.element_admin }}
|
||||
container_name: element-admin
|
||||
restart: unless-stopped
|
||||
networks: [ {{ ess_compose_traefik_network }} ]
|
||||
environment:
|
||||
SERVER_NAME: "{{ ess_server_name }}"
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network={{ ess_compose_traefik_network }}"
|
||||
- "traefik.http.routers.ess-element-admin.rule=Host(`{{ ess_hostnames.element_admin }}`)"
|
||||
- "traefik.http.routers.ess-element-admin.entrypoints={{ ess_compose_traefik_entrypoint }}"
|
||||
- "traefik.http.routers.ess-element-admin.tls=true"
|
||||
{% if ess_compose_traefik_certresolver | length > 0 %}
|
||||
- "traefik.http.routers.ess-element-admin.tls.certresolver={{ ess_compose_traefik_certresolver }}"
|
||||
{% endif %}
|
||||
- "traefik.http.services.ess-element-admin.loadbalancer.server.port=8080"
|
||||
|
||||
# ===========================================================================
|
||||
# Matrix RTC / Element Call (LiveKit SFU + lk-jwt)
|
||||
# ===========================================================================
|
||||
|
||||
matrix-rtc-sfu:
|
||||
image: {{ ess_images.livekit }}
|
||||
container_name: matrix-rtc-sfu
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- {{ ess_compose_internal_network }}
|
||||
- {{ ess_compose_traefik_network }}
|
||||
command: ["--config", "/conf/sfu-config.yaml"]
|
||||
volumes:
|
||||
- {{ ess_compose_conf_dir }}/sfu/config.yaml:/conf/sfu-config.yaml:ro
|
||||
# WebRTC media ports — DMZ firewall must NAT-forward these to this host.
|
||||
ports:
|
||||
- "{{ ess_rtc_tcp_port }}:{{ ess_rtc_tcp_port }}/tcp"
|
||||
- "{{ ess_rtc_udp_port }}:{{ ess_rtc_udp_port }}/udp"
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network={{ ess_compose_traefik_network }}"
|
||||
- "traefik.http.routers.ess-matrix-rtc.rule=Host(`{{ ess_hostnames.matrix_rtc }}`)"
|
||||
- "traefik.http.routers.ess-matrix-rtc.entrypoints={{ ess_compose_traefik_entrypoint }}"
|
||||
- "traefik.http.routers.ess-matrix-rtc.tls=true"
|
||||
{% if ess_compose_traefik_certresolver | length > 0 %}
|
||||
- "traefik.http.routers.ess-matrix-rtc.tls.certresolver={{ ess_compose_traefik_certresolver }}"
|
||||
{% endif %}
|
||||
- "traefik.http.routers.ess-matrix-rtc.service=ess-matrix-rtc"
|
||||
- "traefik.http.services.ess-matrix-rtc.loadbalancer.server.port=7880"
|
||||
|
||||
matrix-rtc-authorisation:
|
||||
image: {{ ess_images.lk_jwt }}
|
||||
container_name: matrix-rtc-authorisation
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
matrix-rtc-sfu: { condition: service_started }
|
||||
networks:
|
||||
- {{ ess_compose_internal_network }}
|
||||
- {{ ess_compose_traefik_network }}
|
||||
environment:
|
||||
LIVEKIT_URL: "wss://{{ ess_hostnames.matrix_rtc }}"
|
||||
LIVEKIT_KEY: "{{ ess_livekit_key }}"
|
||||
LIVEKIT_SECRET_FROM_FILE: /secrets/ess-generated/ELEMENT_CALL_LIVEKIT_SECRET
|
||||
LIVEKIT_FULL_ACCESS_HOMESERVERS: "{{ ess_server_name }}"
|
||||
volumes:
|
||||
- {{ ess_compose_secrets_dir }}:/secrets/ess-generated:ro
|
||||
labels:
|
||||
# /sfu/get is the JWT token endpoint Element Call hits to join calls.
|
||||
# It lives on the same host as the SFU but on a different backend.
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network={{ ess_compose_traefik_network }}"
|
||||
- "traefik.http.routers.ess-matrix-rtc-auth.rule=Host(`{{ ess_hostnames.matrix_rtc }}`) && PathPrefix(`/sfu/get`)"
|
||||
- "traefik.http.routers.ess-matrix-rtc-auth.entrypoints={{ ess_compose_traefik_entrypoint }}"
|
||||
- "traefik.http.routers.ess-matrix-rtc-auth.tls=true"
|
||||
- "traefik.http.routers.ess-matrix-rtc-auth.priority=200"
|
||||
{% if ess_compose_traefik_certresolver | length > 0 %}
|
||||
- "traefik.http.routers.ess-matrix-rtc-auth.tls.certresolver={{ ess_compose_traefik_certresolver }}"
|
||||
{% endif %}
|
||||
- "traefik.http.routers.ess-matrix-rtc-auth.service=ess-matrix-rtc-auth"
|
||||
- "traefik.http.services.ess-matrix-rtc-auth.loadbalancer.server.port=8080"
|
||||
Loading…
Add table
Add a link
Reference in a new issue