feat(ess_pro): deploy Element Server Suite Pro via K3s + Helm

Adds k3s and ess_pro roles to replace the planned Nextcloud Talk
stack. Integrates with existing Keycloak (OIDC), Garage (S3 media)
and OpenBao (secrets). Hostnames under digitalboard.ch.
This commit is contained in:
Tobias Wüst 2026-05-27 23:46:37 +02:00
parent c11f019aae
commit 01fd12d75c
18 changed files with 1098 additions and 0 deletions

View file

@ -0,0 +1,208 @@
---
# =============================================================================
# Element Server Suite Pro — values.yaml
# Rendered by Ansible role `ess-pro` for {{ inventory_hostname }}.
# DO NOT EDIT MANUALLY — re-run the playbook instead.
# =============================================================================
serverName: {{ ess_pro_server_name }}
imagePullSecrets:
- name: {{ ess_pro_image_pull_secret_name }}
# -----------------------------------------------------------------------------
# Synapse (Matrix homeserver)
# -----------------------------------------------------------------------------
synapse:
enabled: true
ingress:
host: {{ ess_pro_hostnames.synapse }}
{% if ess_pro_tls_terminate_externally %}
tlsSecret: ""
annotations:
# DMZ Traefik in front handles TLS termination. Inside K3s the workloads
# serve plain HTTP. Traefik (if used as IngressClass) will then route on
# host header only.
traefik.ingress.kubernetes.io/router.entrypoints: web
{% else %}
ingressClassName: {{ ess_pro_ingress_class }}
{% endif %}
{% if ess_pro_postgres_external %}
postgres:
host: {{ ess_pro_postgres_host }}
port: {{ ess_pro_postgres_port }}
sslMode: {{ ess_pro_postgres_sslmode }}
database: {{ ess_pro_postgres_synapse_db }}
user: {{ ess_pro_postgres_synapse_user }}
password:
value: {{ ess_pro_postgres_synapse_password }}
{% endif %}
additional:
digitalboard-config:
config: |
# Trust X-Forwarded-Proto from the upstream DMZ Traefik so Synapse
# generates HTTPS URLs (well-known, federation) correctly.
x_forwarded: true
admin_contact: "mailto:admin@{{ ess_pro_server_name }}"
# Registration is disabled by default in ESS Pro — keep it that way
# and provision users via Keycloak / mas-cli.
enable_registration: false
{% if ess_pro_s3_media_enabled %}
media_storage_providers:
- module: s3_storage_provider.S3StorageProviderBackend
store_local: true
store_remote: true
store_synchronous: true
config:
bucket: {{ ess_pro_s3_bucket }}
region_name: {{ ess_pro_s3_region }}
endpoint_url: {{ ess_pro_s3_endpoint }}
access_key_id: {{ ess_pro_s3_access_key }}
secret_access_key: {{ ess_pro_s3_secret_key }}
{% endif %}
# -----------------------------------------------------------------------------
# Matrix Authentication Service (MAS) — handles all login
# -----------------------------------------------------------------------------
matrixAuthenticationService:
enabled: true
ingress:
host: {{ ess_pro_hostnames.mas }}
{% if ess_pro_tls_terminate_externally %}
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: web
{% else %}
ingressClassName: {{ ess_pro_ingress_class }}
{% endif %}
{% if ess_pro_postgres_external %}
postgres:
host: {{ ess_pro_postgres_host }}
port: {{ ess_pro_postgres_port }}
sslMode: {{ ess_pro_postgres_sslmode }}
database: {{ ess_pro_postgres_mas_db }}
user: {{ ess_pro_postgres_mas_user }}
password:
value: {{ ess_pro_postgres_mas_password }}
{% endif %}
{% if ess_pro_oidc_enabled %}
additional:
digitalboard-oidc:
config: |
# Delegate login to Keycloak via OIDC. MAS becomes a thin RP that
# imports users on first login. Local accounts (localadmin) keep
# working alongside.
upstream_oauth2:
providers:
- id: "01J0KCK0DNNNDIGITALBOARDKC01"
human_name: "{{ ess_pro_oidc_provider_name }}"
issuer: "{{ ess_pro_oidc_issuer }}"
client_id: "{{ ess_pro_oidc_client_id }}"
client_secret: "{{ ess_pro_oidc_client_secret }}"
token_endpoint_auth_method: "client_secret_basic"
scope: "{{ ess_pro_oidc_scopes | join(' ') }}"
claims_imports:
subject:
template: "{% raw %}{{ user.sub }}{% endraw %}"
localpart:
action: require
template: "{% raw %}{{ user.preferred_username }}{% endraw %}"
displayname:
action: suggest
template: "{% raw %}{{ user.name }}{% endraw %}"
email:
action: suggest
template: "{% raw %}{{ user.email }}{% endraw %}"
set_email_verification: always
{% endif %}
# -----------------------------------------------------------------------------
# Element Web (web client)
# -----------------------------------------------------------------------------
elementWeb:
enabled: true
ingress:
host: {{ ess_pro_hostnames.element_web }}
{% if ess_pro_tls_terminate_externally %}
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: web
{% else %}
ingressClassName: {{ ess_pro_ingress_class }}
{% endif %}
# -----------------------------------------------------------------------------
# Element Admin (ESS Pro admin panel)
# -----------------------------------------------------------------------------
elementAdmin:
enabled: true
ingress:
host: {{ ess_pro_hostnames.element_admin }}
{% if ess_pro_tls_terminate_externally %}
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: web
{% else %}
ingressClassName: {{ ess_pro_ingress_class }}
{% endif %}
# -----------------------------------------------------------------------------
# Matrix RTC Backend (Element Call → LiveKit SFU + lk-jwt-service)
# This replaces the previous coturn + spreed-signaling + Janus stack.
# -----------------------------------------------------------------------------
matrixRTC:
enabled: {{ ess_pro_rtc_enabled | bool }}
ingress:
host: {{ ess_pro_hostnames.matrix_rtc }}
{% if ess_pro_tls_terminate_externally %}
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: web
{% else %}
ingressClassName: {{ ess_pro_ingress_class }}
{% endif %}
{% if ess_pro_rtc_enabled %}
sfu:
additional: |
# LiveKit configuration. UDP range must be opened on the DMZ firewall
# and forwarded to the K3s node IP.
rtc:
port_range_start: {{ ess_pro_rtc_udp_port_range_start }}
port_range_end: {{ ess_pro_rtc_udp_port_range_end }}
use_external_ip: false
{% if ess_pro_rtc_external_ip %}
node_ip: {{ ess_pro_rtc_external_ip }}
{% endif %}
tcp_port: 7881
{% endif %}
# -----------------------------------------------------------------------------
# Well-known delegation — exposes /.well-known/matrix/{client,server}
# This is what makes federation and client discovery work for
# @user:{{ ess_pro_server_name }} when the homeserver lives on a subdomain.
# -----------------------------------------------------------------------------
wellKnownDelegation:
enabled: true
ingress:
host: {{ ess_pro_server_name }}
{% if ess_pro_tls_terminate_externally %}
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: web
{% else %}
ingressClassName: {{ ess_pro_ingress_class }}
{% endif %}
# -----------------------------------------------------------------------------
# Internal Postgres (only used when ess_pro_postgres_external is false)
# -----------------------------------------------------------------------------
{% if not ess_pro_postgres_external %}
postgres:
enabled: true
# Demo-grade DB. Move to an external Postgres before going live.
{% else %}
postgres:
enabled: false
{% endif %}
# -----------------------------------------------------------------------------
# Initial admin (ESS chart creates @localadmin:{{ ess_pro_server_name }})
# Password is in Secret "{{ ess_pro_release_name }}-generated", key ADMIN_USER_PASSWORD.
# -----------------------------------------------------------------------------
initSecrets:
enabled: true