Releases: wlphi/ess-docker-compose
v1.6.4
Bug Fix
- Fix Element Desktop native OIDC login: MAS was missing loopback redirect URIs for the Element Web/Desktop OIDC client. Without
http://localhostregistered, MAS rejects the authorization request when Element Desktop (≥1.11) attempts native OIDC, forcing fallback to the legacy compat SSO (login-token) flow. Addedhttp://localhostandhttp://127.0.0.1— per RFC 8252, these match any port on the loopback address.
Upgrading
Regenerate mas/config/config.yaml to pick up the new redirect URIs:
git pull
./deploy.sh # or ./quickstart.sh for single-machine deployments
docker compose restart masOr add them manually to mas/config/config.yaml under the 01HQW90Z35CMXFJWQPHC3BGZGQ client:
- 'http://localhost'
- 'http://127.0.0.1'Then: docker compose restart mas
v1.7.0
Replaces element-admin with Ketesa. Adds FluffyChat as an optional second web client (also registers it as a MAS OIDC client, which fixes the cross-signing reset "continue" button). Adds Prometheus + Grafana monitoring, Discord and Slack Go megabridges, matrix-hookshot, and a self-building synapse_auto_compressor container for continuous DB state compression.
New features
- Ketesa replaces element-admin (admin panel, user/room management)
- FluffyChat optional profile (
--profile fluffychat); MAS client registered even without self-hosting so native apps work - Prometheus + Grafana monitoring profile with pre-provisioned Synapse dashboard (ID 10046)
- Discord and Slack bridges use Go megabridge implementations
- matrix-hookshot optional profile (GitHub, GitLab, JIRA, webhooks)
- synapse_auto_compressor built from source, runs alongside Postgres for continuous DB state compression
Fixes
synapse_auto_compressor: install from GitHub (not crates.io); addmakefor jemalloc build- MAS FluffyChat client ID was 27 chars with invalid Crockford character — caused crash-loop on startup
- Telegram bridge config updated for Go bridge
database.uriformat
Testing
SKIP_DOCKER=truemode: 355 config-generation assertions pass without a live Docker daemon- Full Docker run: 424 assertions pass
v1.6.3
Bug Fixes
- Fix telegram bridge database not configured after setup:
setup-bridges.shwas targeting the old Python bridge scalar key (database: postgres://...). The Go rewrite restructured this into a block withdatabase.uri. The sed pattern now correctly targetsuri:so the postgres connection string is actually written into the config. - Add element-admin to local compose: The service was routed in the local Caddyfile but the container was missing from
compose-variants/docker-compose.local.yml, causing 502 errors in local testing. Added with healthcheck. - Add healthcheck to element-admin in both compose files (
wget -qO- http://localhost:8080/health).
Upgrading
Pull the latest and re-run bridge setup if you use the Telegram bridge:
git pull
./setup-bridges.shIf running local mode, recreate the element-admin container:
git pull
docker compose -f compose-variants/docker-compose.local.yml up -d element-adminv1.6.2
Bug Fixes
- Fix Caddy crash on startup (
matcher is defined more than once: @preflight): The@preflightnamed matcher was defined twice within the same Caddy site block — once forOPTIONS /_matrix/*and again inside the/_synapse/admin*handler. Renamed the latter to@admin_preflight. Affected local mode, production mode, and quickstart.
Upgrading
Re-run ./deploy.sh or ./quickstart.sh to regenerate the Caddyfile. Or manually rename the duplicate in caddy/Caddyfile:
Inside the handle /_synapse/admin* block, change:
@preflight method OPTIONS
respond @preflight "" 204
to:
@admin_preflight method OPTIONS
respond @admin_preflight "" 204
Then: docker compose exec caddy caddy reload --config /etc/caddy/Caddyfile
v1.6.1 — Permission regression test coverage
Test coverage
Added assertions that catch the issue #21 class of permission regressions on every test run:
mas/config/must be world-executable (mode ≥ 755) — MAS container (UID 65532) must enter itmas/config/config.yamlmust be world-readable (mode ≥ 644) — MAS must read its configmas/data/must be owned by UID 65532synapse/data/must be owned by UID 991.envmust not be world-readable (mode 600)
No functional changes. If you're on v1.6 everything is already correct — this release only adds test guards.
Upgrading
git pullNo restart needed.
v1.6 — Element Admin CORS fix, permission fixes, CORS test coverage
Bug fixes
- Element Admin CORS error (#22) — All API requests in the admin panel failed with browser CORS errors. The
/_synapse/admin/*route returned 403 with no CORS headers, blocking the browser before requests reached Synapse. Replaced with a CORS-enabled proxy scoped to your admin domain. Synapse's own admin token auth remains the security boundary. - MAS config permissions —
mas/config/was set to700andconfig.yamlto600, which prevented the MAS container (uid 65532) from reading its own config. Fixed to755/644. - quickstart.sh: Synapse image not built before start —
docker compose upcould pull a stale image if the build step hadn't run. Fixed to build explicitly before starting.
Test coverage
Added live HTTP response CORS assertions for all user-facing endpoints. Previous tests only verified Caddyfile text contained the right config strings — a Caddy syntax error could silently drop headers and tests would still pass. Now the integration suite sends an actual Origin header and checks the response:
/_synapse/admin/*— scoped to admin domain origin/_matrix/client/versions/_matrix/client/v3/login- MAS
/.well-known/openid-configuration
Upgrading from v1.5
git pull
docker compose pull
docker compose up -d⚠ Existing deployments — Element Admin CORS fix requires a manual Caddyfile edit.
docker compose up -dpulls new images but does not regenerate yourcaddy/Caddyfile. The old 403 block stays on disk until you update it.Find this block in
caddy/Caddyfileinside yourmatrix.<domain>vhost:handle /_synapse/admin* { respond "Forbidden" 403 }Replace it with:
handle /_synapse/admin* { header Access-Control-Allow-Origin "https://admin.<your-domain>" header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" header Access-Control-Allow-Headers "Authorization, Content-Type, Accept" @preflight method OPTIONS respond @preflight "" 204 reverse_proxy synapse:8008 { header_down -Access-Control-Allow-Origin } }Then reload Caddy (no restart needed):
docker compose exec caddy caddy reload --config /etc/caddy/Caddyfile
v1.5.2
Bug Fixes
- Fix MAS startup failure (
Error: missing field 'secrets'):mas/config/was set tochmod 700, blocking MAS (UID 65532) from reading its config. Changed tochmod 755/644. Also fixesmas/data/ownership which was incorrectly set to Synapse's UID (991) instead of MAS's UID (65532). - Fix Synapse image on fresh install:
quickstart.shnow runsdocker compose build synapsebefore starting the stack, so Docker builds the local image instead of trying to pullmatrix-synapse:localfrom the registry. - Guard openssl key generation:
quickstart.shnow fails immediately with a clear message ifopensslis unavailable instead of silently producing a broken MAS config.
Upgrading
git pull
chmod 755 mas/config
chmod 644 mas/config/config.yaml
sudo chown -R 65532:65532 mas/data/
docker compose restart masv1.5 — MAS config fixes, OIDC, single-server mode, security hardening
Bug fixes
- Element Admin broke on new installs (#19) —
SERVER_NAMEwas incorrectly set toMATRIX_DOMAINindocker-compose.yml. Element Admin requires the bare server name (e.g.example.com), not the Matrix subdomain. - LiveKit secret rejected (#20) —
generate_secret()produces base64-like output; go-jose requires a pure hex string. Switched togenerate_hex_secret()(64 hex chars) forLIVEKIT_SECRET. - Open registration silently broken (#18) — MAS ignored the registration policy due to incorrect config structure (
policy.registrationinstead ofpolicy.data.registration) and a non-existentrequire_emailfield. Fixed across deploy.sh, quickstart.sh, and the template.
MAS config correctness
- Added missing
passwords.schemesblock (argon2id, minimum_complexity: 3) — without this, MAS v1.11+ rejects the config entirely and won't start. - Added
account:block withpassword_registration_enabled,password_registration_email_required,password_change_allowed, etc. - Fixed
policy.data.registrationnesting (was one level too shallow). - Updated
templates/mas-config.yamlto match the corrected structure.
LiveKit security
- Added
room.auto_create: falsetolivekit.yaml— without this, anyone with a valid JWT can create arbitrary rooms on your LiveKit server.
Element Web
- Removed
participant_limitfrom Element Call config — deprecated field, rejected in recent Element Web versions.
Synapse
- Added
enable_authenticated_media: truetohomeserver.yaml— prevents unauthenticated media access (hardening, not a breaking change). - Added
synapse/Dockerfile+synapse/requirements.txt— drop Python packages (e.g.synapse-s3-storage-provider) intorequirements.txtto install them into the Synapse image at build time. Empty file = no-op.
New: generic OIDC upstream provider
deploy.sh now offers a third SSO option alongside "None" and "Authelia":
3) Other OIDC — Authentik, Keycloak, Zitadel, or any OIDC-compliant provider
Prompts for issuer URL, client ID, and client secret. Generates the upstream_oauth2: block in the MAS config automatically. No extra containers needed.
New: production single-server deployment mode
deploy.sh now has three deployment types:
| Choice | Mode | Description |
|---|---|---|
| 1 | Local testing | Self-signed certs, *.example.test domains |
| 2 | Production (single-server) | Let's Encrypt, all services on one machine |
| 3 | Production (distributed) | Caddy / Authelia / Matrix on separate hosts |
Single-server mode generates a proper Caddyfile with Let's Encrypt and starts the stack with --profile single-machine automatically.
Security
mas/config/set to700,mas/config/config.yamlset to600— was world-readable, exposed database credentials and signing keys..envset to600— was world-readable, exposed all secrets.- OIDC client secret no longer echoed to terminal during input (
read -s).
Upgrading from v1.4
git pull
docker compose pull
docker compose up -d --buildIf you have a running MAS and your mas/config/config.yaml was generated by an older version:
-
Open
mas/config/config.yamland check thepolicy:section. If it looks like this:policy: registration: enabled: false
Change it to:
policy: data: registration: enabled: false
-
Add the
passwords.schemesblock if missing (MAS v1.11+ requires it):passwords: enabled: true minimum_complexity: 3 schemes: - version: 1 algorithm: argon2id
-
Fix permissions:
chmod 700 mas/config chmod 600 mas/config/config.yaml chmod 600 .env
-
Restart MAS:
docker compose restart mas
If you used Element Call and LiveKit isn't accepting connections, regenerate LIVEKIT_SECRET:
new_secret=$(openssl rand -hex 32)
sed -i "s/^LIVEKIT_SECRET=.*/LIVEKIT_SECRET=${new_secret}/" .env
# Update livekit/livekit.yaml key_secret to match, then:
docker compose restart livekit lk-jwt-serviceBreaking change: mautrix-telegram Go rewrite
The mautrix-telegram image was rewritten from Python to Go. Two permission level names changed in bridges/telegram/config/config.yaml:
| Old (Python) | New (Go) |
|---|---|
relaybot |
relay |
full |
user |
If you have an existing Telegram bridge deployment, edit bridges/telegram/config/config.yaml before or after pulling the new image:
# Change this:
bridge:
permissions:
'*': relaybot
'example.com': full
# To this:
bridge:
permissions:
'*': relay
'example.com': userThen restart: docker compose restart mautrix-telegram
No data loss, no database migration — config key rename only.
v1.4.1 — permission fix & templates clarification
What's new
- Permission fix — Synapse/MAS data directories created with correct ownership on new installs (fixes #17)
- templates/ clarification — added README noting these are reference files generated by deploy.sh, not for manual editing
Upstream component updates
No config changes required. Images are on :latest — run docker compose pull to update.
| Component | Latest |
|---|---|
| Synapse | v1.151.0 |
| MAS | v1.15.0 |
| Element Web | v1.12.15 |
| Element Call | v0.19.0 |
| LiveKit | v1.10.1 |
| Authelia | v4.39.18 |
Note: Authelia v4.39.17 tightened domain matching — review your
access_controlrules after upgrading.
Upgrade
git pull && git checkout v1.4.1 && docker compose pullv1.4.0 — quickstart.sh security fixes & full test coverage
What's new
-
quickstart.sh security fixes — synced with the security hardening applied to deploy.sh in v1.3.x:
- Caddy admin API bound to
localhost:2019only (was0.0.0.0:2019) /_synapse/adminendpoints now blocked (403) at the reverse proxyHostandX-Forwarded-Hostheaders forwarded to MAS on all proxy blocks (fixes silent OAuth2 breakage)/account/portal route useshandleinstead ofhandle_path(prefix was being stripped, breaking MAS SPA routing)allow_guest_access,allow_public_rooms_without_auth,allow_public_rooms_over_federationset tofalsein Synapse config- Fixed
sed -ipermission error on Synapse config afterdocker run generate
- Caddy admin API bound to
-
Expanded test coverage — test_deploy.sh now covers all described install scenarios:
- Scenario P: production Caddyfile (
caddy/Caddyfile.production) config assertions - Scenario Q: quickstart.sh config assertions (all 5 security properties verified)
SKIP_START=truesupport added to bothdeploy.shandquickstart.shfor config-only CI testing
- Scenario P: production Caddyfile (
Upgrade
git pull && git checkout v1.4.0