From ba220d6cd6aade41e1bd480bd8c89c78a5f1a089 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20B=C3=A4rlocher?= Date: Mon, 15 Jun 2026 16:34:03 +0200 Subject: [PATCH] fix(ess-pro/compose): align with matrix-stack 26.6.1 and fix routing/security gaps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Verified the role against the real matrix-stack Helm chart (pulled 26.6.1) and fixed divergences found during review. Bugs: - Add MAS OIDC discovery router: /.well-known/openid-configuration must hit the MAS root listener (8082), not web (8080) — was 404, breaking OIDC login - Add Synapse ip_range_blacklist (full SSRF blocklist for all outbound federation/identity requests; previously only url-preview blacklist present) - Make federation_client_minimum_tls_version unconditional (chart sets it in shared-underrides; role only set it when federation was enabled) - Restart only rendered fed-reader replicas in the handler instead of the whole compose project (missing services: filter) Chart alignment (26.5.1 -> 26.6.1): - Bump chart version and all image tags (mas -> matrix-authentication-service -pro:1.18.0, postgres 17, synapse v1.154.0-pro.1, element-web v1.12.21, etc.) - redis maxmemory 256mb -> chart default 40mb (configurable) - Add element-web map_style_url (configurable) Hardening / hygiene: - Validate ess_rtc_external_ip is a real IP (regex, no extra collection dep) - Read admin password from the in-container secret file instead of passing it on the host process list during mas-cli register-user - apt cache_valid_time, postgres first-boot-only comment, haproxy failover note - Add meta/argument_specs.yml documenting all public variables - README: chart version, service count, OIDC discovery verification step Signed-off-by: Simon Bärlocher --- roles/ess_pro_compose/README.md | 12 +- roles/ess_pro_compose/defaults/main.yml | 43 ++-- roles/ess_pro_compose/handlers/main.yml | 5 + roles/ess_pro_compose/meta/argument_specs.yml | 197 ++++++++++++++++++ roles/ess_pro_compose/tasks/config.yml | 19 +- roles/ess_pro_compose/tasks/main.yml | 14 ++ roles/ess_pro_compose/tasks/postinstall.yml | 32 +-- roles/ess_pro_compose/tasks/prereq.yml | 1 + .../ess_pro_compose/templates/compose.yml.j2 | 19 +- .../templates/element-web/config.json.j2 | 1 + .../templates/haproxy/haproxy.cfg.j2 | 4 +- .../templates/redis/redis.conf.j2 | 2 +- .../templates/synapse/homeserver.yaml.j2 | 28 ++- 13 files changed, 331 insertions(+), 46 deletions(-) create mode 100644 roles/ess_pro_compose/meta/argument_specs.yml diff --git a/roles/ess_pro_compose/README.md b/roles/ess_pro_compose/README.md index f02e2b1..ddf633b 100644 --- a/roles/ess_pro_compose/README.md +++ b/roles/ess_pro_compose/README.md @@ -1,6 +1,6 @@ # Ansible Role: ess_pro_compose -Deploys the full **Element Server Suite Pro v26.5.1** stack as a single docker +Deploys the full **Element Server Suite Pro v26.6.1** stack as a single docker compose project, modelled 1:1 on the official `matrix-stack` Helm chart from Element. Fronted by the existing DMZ Traefik, secrets sourced from OpenBao (plus locally-generated cryptographic material), same conventions as the @@ -12,9 +12,9 @@ other `digitalboard.core` roles. ## Architecture -12 services, mirroring the chart: +10 base services (plus N federation-reader replicas), mirroring the chart: -``` +```text ┌───────────────┐ ┌──────────────────────HTTP──▶│ element-web │ │ └───────────────┘ @@ -149,6 +149,10 @@ curl -sS https://matrix.digitalboard.ch/_matrix/client/versions | jq .versions curl -sS https://digitalboard.ch/.well-known/matrix/server | jq curl -sS https://digitalboard.ch/.well-known/matrix/client | jq +# MAS OIDC discovery must resolve (served by the MAS root listener on 8082, +# routed separately from the web listener — see compose template). +curl -sS https://account.digitalboard.ch/.well-known/openid-configuration | jq .issuer + # MAS sanity docker compose -f /opt/ess/compose.yml exec mas \ mas-cli --config /conf/mas-config.yaml doctor @@ -171,7 +175,7 @@ docker compose -f /opt/ess/compose.yml exec haproxy \ ## What's faithful to the chart, what's adapted -**Faithful to chart v26.5.1:** +**Faithful to chart v26.6.1:** - All image paths from `registry.element.io` (correct repos: `synapse-onprem`, `synapse-pro-worker`, `matrix-authentication-service`, `element-web-pro`, `element-admin`, `haproxy`, `livekit-server-distroless`, `lk-jwt-service`, diff --git a/roles/ess_pro_compose/defaults/main.yml b/roles/ess_pro_compose/defaults/main.yml index ebc0b27..ae03caa 100644 --- a/roles/ess_pro_compose/defaults/main.yml +++ b/roles/ess_pro_compose/defaults/main.yml @@ -3,14 +3,14 @@ # ============================================================================= # ess_pro_compose role — defaults # ============================================================================= -# Deploys the full ESS Pro stack (matrix-stack chart v26.5.1) as a docker +# Deploys the full ESS Pro stack (matrix-stack chart v26.6.1) as a docker # compose project, including the Pro federation-reader worker. Same conventions # as the other digitalboard.core roles. Secrets are sourced from OpenBao. # ----------------------------------------------------------------------------- # Chart version we're modelling # ----------------------------------------------------------------------------- -ess_chart_version: "26.5.1" +ess_chart_version: "26.6.1" # ----------------------------------------------------------------------------- # Project layout on the target host @@ -50,23 +50,24 @@ ess_hostnames: matrix_rtc: "mrtc.{{ ess_server_name }}" # Element Call SFU + auth # ----------------------------------------------------------------------------- -# Image references (Pro images from registry.element.io, chart 26.5.1) +# Image references (Pro images from registry.element.io, chart 26.6.1) # ----------------------------------------------------------------------------- # Pin to specific tags for production. The chart bundles digests; we use # version-aligned tags so they're readable. Override individually as needed. +# Tags below are taken verbatim from matrix-stack 26.6.1 values.yaml. ess_images: - synapse: "registry.element.io/synapse-onprem:sha-63110a4" - synapse_pro_worker: "registry.element.io/synapse-pro-worker:0.4.0" - mas: "registry.element.io/matrix-authentication-service:1.17.0" - element_web: "registry.element.io/element-web-pro:1.12.18" - element_admin: "registry.element.io/element-admin:1.5.0" + synapse: "registry.element.io/synapse-onprem:v1.154.0-pro.1" + synapse_pro_worker: "registry.element.io/synapse-pro-worker:sha-63110a4" + mas: "registry.element.io/matrix-authentication-service-pro:1.18.0" + element_web: "registry.element.io/element-web-pro:v1.12.21" + element_admin: "registry.element.io/element-admin:0.1.11" haproxy: "registry.element.io/haproxy:3.2-alpine" - livekit: "registry.element.io/livekit-server-distroless:1.9.1" - lk_jwt: "registry.element.io/lk-jwt-service:0.3.0" - postgres: "registry.element.io/postgres:16-alpine" - postgres_exporter: "registry.element.io/postgres-exporter:0.18.1" - redis: "registry.element.io/redis-distroless:7.4" - matrix_tools: "registry.element.io/matrix-tools:0.17.8" + livekit: "registry.element.io/livekit-server-distroless:v1.12.0" + lk_jwt: "registry.element.io/lk-jwt-service:0.4.4" + postgres: "registry.element.io/postgres:17-alpine" + postgres_exporter: "registry.element.io/postgres-exporter:v0.18.1" + redis: "registry.element.io/redis-distroless:7.4-bookworm" + matrix_tools: "registry.element.io/matrix-tools:0.17.9" # ----------------------------------------------------------------------------- # Element registry credentials (from customer.element.io) @@ -147,3 +148,17 @@ ess_postgres_effective_cache_size: "3840MB" # ----------------------------------------------------------------------------- ess_synapse_max_upload_size: "100M" ess_synapse_url_previews_enabled: true + +# ----------------------------------------------------------------------------- +# Redis +# ----------------------------------------------------------------------------- +# Redis is pub/sub only (Synapse worker replication), no persistence. Chart +# default is 40mb; bump only if you run many workers with heavy replication. +ess_redis_maxmemory: "40mb" + +# ----------------------------------------------------------------------------- +# Element Web +# ----------------------------------------------------------------------------- +# MapTiler style URL powering in-app location sharing. The chart ships this +# shared demo key; swap for your own MapTiler key in production. +ess_element_web_map_style_url: "https://api.maptiler.com/maps/streets/style.json?key=fU3vlMsMn4Jb6dnEIFsx" diff --git a/roles/ess_pro_compose/handlers/main.yml b/roles/ess_pro_compose/handlers/main.yml index 0cdac71..39b2c6e 100644 --- a/roles/ess_pro_compose/handlers/main.yml +++ b/roles/ess_pro_compose/handlers/main.yml @@ -15,6 +15,11 @@ - name: Restart synapse-fed-reader community.docker.docker_compose_v2: project_src: "{{ ess_compose_dir }}" + # Restart only the rendered fed-reader replicas, not the whole project. + services: >- + {{ range(ess_synapse_fed_reader_replicas | int) + | map('regex_replace', '^(.*)$', 'synapse-fed-reader-\1') + | list }} state: restarted - name: Restart mas diff --git a/roles/ess_pro_compose/meta/argument_specs.yml b/roles/ess_pro_compose/meta/argument_specs.yml new file mode 100644 index 0000000..f91cdec --- /dev/null +++ b/roles/ess_pro_compose/meta/argument_specs.yml @@ -0,0 +1,197 @@ +# SPDX-License-Identifier: MIT-0 +--- +argument_specs: + main: + short_description: Deploy the full Element Server Suite Pro stack (matrix-stack v26.6.1) via Docker Compose. + description: + - Renders the complete ESS Pro topology (Synapse main + Rust Pro + federation-reader worker, MAS, HAProxy, Element Web/Admin, LiveKit + SFU + lk-jwt, Postgres, Redis) as a single Compose project, modelled + 1:1 on the official C(matrix-stack) Helm chart. + - Cryptographic secrets are generated locally on first run; registry + and OIDC credentials are sourced from OpenBao. + options: + ess_chart_version: + type: str + default: "26.6.1" + description: matrix-stack chart version this role models. Informational. + + # ---- Project layout -------------------------------------------------- + ess_compose_dir: + type: path + default: /opt/ess + description: Root project directory on the target host. + ess_compose_project_name: + type: str + default: ess + ess_compose_conf_dir: + type: path + description: Rendered config dir. Defaults to C({{ ess_compose_dir }}/conf). + ess_compose_secrets_dir: + type: path + description: Generated-secrets dir (0700). Defaults to C({{ ess_compose_dir }}/secrets). + ess_compose_data_dir: + type: path + description: Runtime data dir. Defaults to C({{ ess_compose_dir }}/data). + + # ---- Networks -------------------------------------------------------- + ess_compose_traefik_network: + type: str + default: proxy + description: External Traefik network the public services attach to. + ess_compose_traefik_entrypoint: + type: str + default: websecure + ess_compose_traefik_certresolver: + type: str + default: letsencrypt + description: Traefik certresolver. Set to empty string to skip TLS cert resolution labels. + ess_compose_internal_network: + type: str + default: ess_internal + + # ---- Matrix identity ------------------------------------------------- + ess_server_name: + type: str + required: true + description: Matrix serverName (domain part of C(@user:serverName)). Immutable after first deploy. + ess_hostnames: + type: dict + description: + - Per-component FQDNs. Defaults derive from C(ess_server_name) + (matrix./account./chat./admin./mrtc.). Override individual keys + to change prefixes. + options: + synapse: + type: str + mas: + type: str + element_web: + type: str + element_admin: + type: str + matrix_rtc: + type: str + + # ---- Images ---------------------------------------------------------- + ess_images: + type: dict + description: Container image references, version-aligned to the chart. Override individual entries to pin/upgrade. + + # ---- Registry -------------------------------------------------------- + ess_registry_url: + type: str + default: registry.element.io + ess_registry_username: + type: str + required: true + description: Element registry username (from OpenBao). + ess_registry_token: + type: str + required: true + description: Element registry token (from OpenBao). + + # ---- Federation reader ---------------------------------------------- + ess_synapse_fed_reader_replicas: + type: int + default: 1 + description: Number of Rust Pro federation-reader worker instances. + + # ---- Delegated auth (OIDC) ------------------------------------------ + ess_oidc_enabled: + type: bool + default: false + description: Enable upstream OIDC delegation in MAS. Requires issuer + client_secret. + ess_oidc_issuer: + type: str + default: "" + description: Upstream OIDC issuer URL. Required when C(ess_oidc_enabled). + ess_oidc_client_id: + type: str + default: ess-mas + ess_oidc_client_secret: + type: str + default: "" + description: Upstream OIDC client secret (from OpenBao). Required when C(ess_oidc_enabled). + ess_oidc_provider_name: + type: str + default: Digitalboard + ess_oidc_provider_ulid: + type: str + default: "01JBADAUTHENTIKDIGITALBOARD01" + ess_oidc_scopes: + type: str + default: "openid profile email" + + # ---- Matrix RTC / Element Call -------------------------------------- + ess_rtc_tcp_port: + type: int + default: 30001 + ess_rtc_udp_port: + type: int + default: 30002 + ess_rtc_external_ip: + type: str + required: true + description: Public NAT IP advertised in ICE candidates. Must be a valid IPv4/IPv6 address. + ess_livekit_key: + type: str + default: matrix-rtc + + # ---- Registration / federation -------------------------------------- + ess_enable_registration: + type: bool + default: false + ess_enable_federation: + type: bool + default: true + ess_admin_contact: + type: str + description: Defaults to C(mailto:admin@{{ ess_server_name }}). + + # ---- Initial admin user --------------------------------------------- + ess_admin_localpart: + type: str + default: localadmin + ess_create_admin_user: + type: bool + default: true + + # ---- Admin allow-list ------------------------------------------------ + ess_admin_allow_ips: + type: list + elements: str + default: + - "0.0.0.0/0" + - "::/0" + description: Source CIDRs allowed to hit C(/_synapse/admin/). Lock down for production. + + # ---- Postgres sizing ------------------------------------------------- + ess_postgres_max_connections: + type: int + default: 256 + ess_postgres_shared_buffers: + type: str + default: "1024MB" + ess_postgres_effective_cache_size: + type: str + default: "3840MB" + + # ---- Synapse media --------------------------------------------------- + ess_synapse_max_upload_size: + type: str + default: "100M" + ess_synapse_url_previews_enabled: + type: bool + default: true + + # ---- Redis ----------------------------------------------------------- + ess_redis_maxmemory: + type: str + default: "40mb" + description: Redis maxmemory limit. Chart default; pub/sub only, no persistence. + + # ---- Element Web ----------------------------------------------------- + ess_element_web_map_style_url: + type: str + description: MapTiler style URL for location sharing. Ships the chart's demo key; replace for production. diff --git a/roles/ess_pro_compose/tasks/config.yml b/roles/ess_pro_compose/tasks/config.yml index 5929f4b..d35a803 100644 --- a/roles/ess_pro_compose/tasks/config.yml +++ b/roles/ess_pro_compose/tasks/config.yml @@ -9,10 +9,10 @@ dest: "{{ ess_compose_conf_dir }}/haproxy/{{ item.dest }}" mode: "0640" loop: - - { src: haproxy/haproxy.cfg.j2, dest: haproxy.cfg } - - { src: haproxy/429.http.j2, dest: 429.http } - - { src: haproxy/path_map_file.j2, dest: path_map_file } - - { src: haproxy/path_map_file_get.j2, dest: path_map_file_get } + - { src: haproxy/haproxy.cfg.j2, dest: haproxy.cfg } + - { src: haproxy/429.http.j2, dest: 429.http } + - { src: haproxy/path_map_file.j2, dest: path_map_file } + - { src: haproxy/path_map_file_get.j2, dest: path_map_file_get } - { src: haproxy/admin-allow-ips.lst.j2, dest: admin-allow-ips.lst } notify: Restart haproxy @@ -34,8 +34,8 @@ dest: "{{ ess_compose_conf_dir }}/synapse/{{ item.dest }}" mode: "0640" loop: - - { src: synapse/homeserver.yaml.j2, dest: homeserver.yaml } - - { src: synapse/log_config.yaml.j2, dest: log_config.yaml } + - { src: synapse/homeserver.yaml.j2, dest: homeserver.yaml } + - { src: synapse/log_config.yaml.j2, dest: log_config.yaml } - { src: synapse/federation-reader.yaml.j2, dest: federation-reader.yaml } no_log: true notify: @@ -65,7 +65,12 @@ mode: "0644" notify: Restart element-web -- name: Render Postgres init script +# NOTE: This script runs only on FIRST init of an empty PGDATA volume (via +# /docker-entrypoint-initdb.d/). Re-rendering it on later runs has no effect +# on an already-initialised database — the chart's postgres-ess-updater +# sidecar that re-applies it is intentionally omitted (see README). To change +# DBs/roles after init, run the SQL manually or recreate the volume. +- name: Render Postgres init script (first-boot only) ansible.builtin.template: src: postgres/configure-dbs.sh.j2 dest: "{{ ess_compose_conf_dir }}/postgres/configure-dbs.sh" diff --git a/roles/ess_pro_compose/tasks/main.yml b/roles/ess_pro_compose/tasks/main.yml index b5cd08f..e760b5f 100644 --- a/roles/ess_pro_compose/tasks/main.yml +++ b/roles/ess_pro_compose/tasks/main.yml @@ -13,6 +13,20 @@ ess_rtc_external_ip in group_vars/ess_servers.yml. quiet: true +- name: Validate ess_rtc_external_ip looks like an IP address + ansible.builtin.assert: + that: + # IPv4 dotted-quad or IPv6 (contains a colon). Cheap sanity check that + # avoids pulling in the ansible.utils collection just for ipaddr. + - >- + ess_rtc_external_ip is match('^\d{1,3}(\.\d{1,3}){3}$') + or ':' in ess_rtc_external_ip + fail_msg: >- + ess_rtc_external_ip ({{ ess_rtc_external_ip }}) is not a valid IP + address. LiveKit advertises this verbatim in ICE candidates; a bad + value silently breaks Element Call. + quiet: true + - name: Validate OIDC variables when OIDC is enabled ansible.builtin.assert: that: diff --git a/roles/ess_pro_compose/tasks/postinstall.yml b/roles/ess_pro_compose/tasks/postinstall.yml index caa7850..d9f4d17 100644 --- a/roles/ess_pro_compose/tasks/postinstall.yml +++ b/roles/ess_pro_compose/tasks/postinstall.yml @@ -3,12 +3,6 @@ # Create @localadmin via mas-cli, using the ADMIN_USER_PASSWORD generated # by secrets.yml. Idempotent: mas-cli rejects duplicates, we ignore that. -- name: Read generated admin password - ansible.builtin.slurp: - src: "{{ ess_compose_secrets_dir }}/ADMIN_USER_PASSWORD" - register: _ess_admin_pw_slurp - no_log: true - - name: Check whether the admin user already exists ansible.builtin.command: cmd: > @@ -20,16 +14,26 @@ changed_when: false failed_when: false +# The password is read from the secrets file *inside* the mas container (it is +# already bind-mounted there read-only). Passing it as $(cat ...) inside the +# container shell keeps it off the host's process list — only the host root can +# read it anyway, but this avoids leaking it via `ps` during the exec. - name: Register admin user (mas-cli) ansible.builtin.command: - cmd: > - docker compose -f {{ _ess_compose_file }} - exec -T mas - mas-cli --config /conf/mas-config.yaml - manage register-user --yes - --password {{ (_ess_admin_pw_slurp.content | b64decode).strip() | quote }} - --admin - {{ ess_admin_localpart }} + argv: + - docker + - compose + - -f + - "{{ _ess_compose_file }}" + - exec + - -T + - mas + - sh + - -c + - >- + mas-cli --config /conf/mas-config.yaml manage register-user --yes + --password "$(cat /secrets/ess-generated/ADMIN_USER_PASSWORD)" + --admin {{ ess_admin_localpart | quote }} register: _ess_admin_create changed_when: "'created' in (_ess_admin_create.stdout + _ess_admin_create.stderr) | lower" failed_when: diff --git a/roles/ess_pro_compose/tasks/prereq.yml b/roles/ess_pro_compose/tasks/prereq.yml index 93158d0..8a2dec2 100644 --- a/roles/ess_pro_compose/tasks/prereq.yml +++ b/roles/ess_pro_compose/tasks/prereq.yml @@ -8,6 +8,7 @@ - python3-cryptography state: present update_cache: true + cache_valid_time: 3600 - name: Verify docker compose plugin is available ansible.builtin.command: docker compose version diff --git a/roles/ess_pro_compose/templates/compose.yml.j2 b/roles/ess_pro_compose/templates/compose.yml.j2 index 514341c..af11742 100644 --- a/roles/ess_pro_compose/templates/compose.yml.j2 +++ b/roles/ess_pro_compose/templates/compose.yml.j2 @@ -134,17 +134,28 @@ services: labels: - "traefik.enable=true" - "traefik.docker.network={{ ess_compose_traefik_network }}" + # Default router: everything on the MAS host hits the web listener (8080). - "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.routers.ess-mas.service=ess-mas" - "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. + # OIDC discovery router: the chart's ingress routes + # /.well-known/openid-configuration to the MAS *root* listener (8082), + # NOT the web listener (8080) — the web listener does not serve the + # `discovery` resource. Without this, OIDC clients 404 on discovery. + - "traefik.http.routers.ess-mas-discovery.rule=Host(`{{ ess_hostnames.mas }}`) && Path(`/.well-known/openid-configuration`)" + - "traefik.http.routers.ess-mas-discovery.entrypoints={{ ess_compose_traefik_entrypoint }}" + - "traefik.http.routers.ess-mas-discovery.tls=true" + - "traefik.http.routers.ess-mas-discovery.priority=200" +{% if ess_compose_traefik_certresolver | length > 0 %} + - "traefik.http.routers.ess-mas-discovery.tls.certresolver={{ ess_compose_traefik_certresolver }}" +{% endif %} + - "traefik.http.routers.ess-mas-discovery.service=ess-mas-discovery" + - "traefik.http.services.ess-mas-discovery.loadbalancer.server.port=8082" # =========================================================================== # HAProxy — fronts all Synapse + well-known traffic diff --git a/roles/ess_pro_compose/templates/element-web/config.json.j2 b/roles/ess_pro_compose/templates/element-web/config.json.j2 index 896add8..9592abf 100644 --- a/roles/ess_pro_compose/templates/element-web/config.json.j2 +++ b/roles/ess_pro_compose/templates/element-web/config.json.j2 @@ -12,6 +12,7 @@ "embedded_pages": { "login_for_welcome": true }, + "map_style_url": "{{ ess_element_web_map_style_url }}", "features": { "feature_element_call_video_rooms": true, "feature_group_calls": true, diff --git a/roles/ess_pro_compose/templates/haproxy/haproxy.cfg.j2 b/roles/ess_pro_compose/templates/haproxy/haproxy.cfg.j2 index ad8a570..948df2b 100644 --- a/roles/ess_pro_compose/templates/haproxy/haproxy.cfg.j2 +++ b/roles/ess_pro_compose/templates/haproxy/haproxy.cfg.j2 @@ -98,7 +98,9 @@ frontend synapse-http-in use_backend return_204_rendezvous if { method OPTIONS } rendezvous use_backend return_204_synapse if { method OPTIONS } - # Failover from pro-fed-reader to main if the worker is unavailable + # Failover from pro-fed-reader to main if the worker is unavailable. + # The chart cascades pro-worker -> FOSS federation worker -> main; we deploy + # no FOSS federation worker, so we fail straight over to synapse-main. acl has_failover var(req.backend) -m str "pro-federation-api-requests" acl backend_unavailable str(),concat('synapse-',req.backend),nbsrv lt 1 use_backend synapse-main-failover if has_failover backend_unavailable diff --git a/roles/ess_pro_compose/templates/redis/redis.conf.j2 b/roles/ess_pro_compose/templates/redis/redis.conf.j2 index e0dcc65..914c9fd 100644 --- a/roles/ess_pro_compose/templates/redis/redis.conf.j2 +++ b/roles/ess_pro_compose/templates/redis/redis.conf.j2 @@ -19,7 +19,7 @@ save '' # Disable persistence — Synapse uses Redis only for pub/sub between workers. appendonly no -maxmemory 256mb +maxmemory {{ ess_redis_maxmemory }} maxmemory-policy allkeys-lru hz 1 diff --git a/roles/ess_pro_compose/templates/synapse/homeserver.yaml.j2 b/roles/ess_pro_compose/templates/synapse/homeserver.yaml.j2 index de81d39..feacadc 100644 --- a/roles/ess_pro_compose/templates/synapse/homeserver.yaml.j2 +++ b/roles/ess_pro_compose/templates/synapse/homeserver.yaml.j2 @@ -18,6 +18,33 @@ log_config: "/conf/log_config.yaml" enable_metrics: true report_stats: false +# Minimum TLS for outbound federation (chart: shared-underrides, always on). +federation_client_minimum_tls_version: '1.2' + +# SSRF protection for ALL outbound requests (federation, identity, etc.). +# Distinct from url_preview_ip_range_blacklist below. Verbatim from chart +# synapse-04-homeserver-overrides. +ip_range_blacklist: + - '127.0.0.0/8' + - '10.0.0.0/8' + - '172.16.0.0/12' + - '192.168.0.0/16' + - '100.64.0.0/10' + - '192.0.0.0/24' + - '169.254.0.0/16' + - '192.88.99.0/24' + - '198.18.0.0/15' + - '192.0.2.0/24' + - '198.51.100.0/24' + - '203.0.113.0/24' + - '224.0.0.0/4' + - '::1/128' + - 'fe80::/10' + - 'fc00::/7' + - '2001:db8::/32' + - 'ff00::/8' + - 'fec0::/10' + # ---- Listeners (from 05-main.yaml) ---------------------------------------- listeners: - port: 8008 @@ -130,7 +157,6 @@ url_preview_ip_range_blacklist: # ---- Federation ----------------------------------------------------------- {% if ess_enable_federation %} send_federation: true -federation_client_minimum_tls_version: '1.2' {% else %} send_federation: false federation_domain_whitelist: []