Compare commits

..
12 changed files with 769 additions and 601 deletions
+85 -44
View File
@@ -19,6 +19,91 @@ SECRET_FORM_SECRET_VERSION=v1
SECRET_MACAROON_VERSION=v1
SECRET_REGISTRATION_VERSION=v1
## Authentication
# All login / SSO / MAS-related toggles in one place.
### Local password & registration (Synapse native)
# With MAS_ENABLED=1 you must set PASSWORD_LOGIN_ENABLED=false — Synapse forbids legacy password DB alongside matrix_authentication_service.
PASSWORD_LOGIN_ENABLED=true
ENABLE_REGISTRATION=false
# Token based registration. Enable ADMIN_INTERFACE (below) to use the admin interface to generate tokens.
#REGISTRATION_REQUIRES_TOKEN=true
### OIDC via Keycloak-shaped API (e.g. Authentik)
#COMPOSE_FILE="$COMPOSE_FILE:compose.keycloak.yml"
#KEYCLOAK_ENABLED=1
#KEYCLOAK_ID=keycloak
#KEYCLOAK_NAME=
#KEYCLOAK_URL=
#KEYCLOAK_CLIENT_ID=
#KEYCLOAK_CLIENT_DOMAIN=
#KEYCLOAK_ALLOW_EXISTING_USERS=false
#SECRET_KEYCLOAK_CLIENT_SECRET_VERSION=v1
### Second OIDC provider (compose.keycloak2.yml)
#COMPOSE_FILE="$COMPOSE_FILE:compose.keycloak2.yml"
#KEYCLOAK2_ENABLED=1
#KEYCLOAK2_ID=keycloak2
#KEYCLOAK2_NAME=
#KEYCLOAK2_URL=
#KEYCLOAK2_CLIENT_ID=
#KEYCLOAK2_CLIENT_DOMAIN=
#KEYCLOAK2_ALLOW_EXISTING_USERS=false
#SECRET_KEYCLOAK2_CLIENT_SECRET_VERSION=v1
### Third OIDC provider (compose.keycloak3.yml)
#COMPOSE_FILE="$COMPOSE_FILE:compose.keycloak3.yml"
#KEYCLOAK3_ENABLED=1
#KEYCLOAK3_ID=keycloak3
#KEYCLOAK3_NAME=
#KEYCLOAK3_URL=
#KEYCLOAK3_CLIENT_ID=
#KEYCLOAK3_CLIENT_DOMAIN=
#KEYCLOAK3_ALLOW_EXISTING_USERS=false
#SECRET_KEYCLOAK3_CLIENT_SECRET_VERSION=v1
### Matrix Authentication Service (MAS) — Element X / OIDC-native auth
#COMPOSE_FILE="$COMPOSE_FILE:compose.mas.yml"
#MAS_ENABLED=1
#PASSWORD_LOGIN_ENABLED=false
#SECRET_MAS_ENCRYPTION_VERSION=v1 # length=64 # charset=hex
#SECRET_MAS_SYNAPSE_SHARED_VERSION=v1 # length=64 # charset=hex
# PEM private key: abra cannot generate this format — insert only (e.g. openssl genrsa 2048 | abra app secret insert …)
#SECRET_MAS_SIGNING_RSA_VERSION=v1 # generate=false
#### MAS upstream OIDC provider (e.g. Authentik)
# See mas-authentik-and-roadmap.md for migration procedure.
# Create a new OAuth2 app in your IdP with redirect URI: https://<DOMAIN>/upstream/callback/<MAS_UPSTREAM_PROVIDER_ID>
#COMPOSE_FILE="$COMPOSE_FILE:compose.mas-upstream.yml"
#MAS_UPSTREAM_PROVIDER_ID= # ULID, e.g. 01JSHPZHAXC50QBKH67MH33TNF — generate at https://www.ulidtools.com
#MAS_UPSTREAM_ISSUER= # e.g. https://auth.example.com/application/o/matrix-mas/
#MAS_UPSTREAM_CLIENT_ID=
#MAS_UPSTREAM_HUMAN_NAME=Authentik
# For migration from previous direct Keycloud-style config: set to oidc-<your old KEYCLOAK_ID> so syn2mas maps users correctly.
#MAS_UPSTREAM_SYNAPSE_IDP_ID=
#SECRET_MAS_UPSTREAM_CLIENT_SECRET_VERSION=v1
#### Sign in with QR (Element / Element X) — requires MAS (MSC4108; optional MSC4388)
# Enables Synapse experimental Sign in with QR when used with MAS. See README and
# https://github.com/element-hq/synapse/issues/19434
#QR_LOGIN_ENABLED=1
# Optional: 2025 rendezvous channel (experimental). Valid values: off, public, authenticated (omit or "off" for MSC4108-only).
#MSC4388_MODE=off
### Shared secret auth (bridges / automation)
#COMPOSE_FILE="$COMPOSE_FILE:compose.shared_secret_auth.yml"
#SHARED_SECRET_AUTH_ENABLED=1
#SECRET_SHARED_SECRET_AUTH_VERSION=v1 # length=128
## Federation
#DISABLE_FEDERATION=1
@@ -28,14 +113,6 @@ SERVE_SERVER_WELLKNOWN=false
ALLOW_PUBLIC_ROOMS_FEDERATION=false
## Registration
ENABLE_REGISTRATION=false
PASSWORD_LOGIN_ENABLED=true
# Token based registration. Enable ADMIN_INTERFACE (below) to use the admin interface to generate tokens.
#REGISTRATION_REQUIRES_TOKEN=true
## Room auto-join
#AUTO_JOIN_ROOM_ENABLED=1
@@ -98,30 +175,8 @@ RETENTION_MAX_LIFETIME=4w
#LOGIN_LIMIT_ACCOUNT_PER_SECOND=1
#LOGIN_LIMIT_ACCOUNT_BURST=10
## Keycloak SSO
#COMPOSE_FILE="$COMPOSE_FILE:compose.keycloak.yml"
#KEYCLOAK_ENABLED=1
#KEYCLOAK_ID=keycloak
#KEYCLOAK_NAME=
#KEYCLOAK_URL=
#KEYCLOAK_CLIENT_ID=
#KEYCLOAK_CLIENT_DOMAIN=
#KEYCLOAK_ALLOW_EXISTING_USERS=false
#SECRET_KEYCLOAK_CLIENT_SECRET_VERSION=v1
## TURN
#COMPOSE_FILE="$COMPOSE_FILE:compose.keycloak3.yml"
#KEYCLOAK3_ENABLED=1
#KEYCLOAK3_ID=keycloak3
#KEYCLOAK3_NAME=
#KEYCLOAK3_URL=
#KEYCLOAK3_CLIENT_ID=
#KEYCLOAK3_CLIENT_DOMAIN=
#KEYCLOAK3_ALLOW_EXISTING_USERS=false
#SECRET_KEYCLOAK3_CLIENT_SECRET_VERSION=v1
#COMPOSE_FILE="$COMPOSE_FILE:compose.turn.yml"
#TURN_ENABLED=1
#TURN_URIS="[\"turns:coturn.foo.zone?transport=udp\", \"turns:coturn.foo.zone?transport=tcp\"]"
@@ -189,24 +244,10 @@ RETENTION_MAX_LIFETIME=4w
#SECRET_SIGNAL_HS_TOKEN_VERSION=v1
#SECRET_SIGNAL_PICKLE_KEY_VERSION=v1
## Shared auth
#COMPOSE_FILE="$COMPOSE_FILE:compose.shared_secret_auth.yml"
#SHARED_SECRET_AUTH_ENABLED=1
#SECRET_SHARED_SECRET_AUTH_VERSION=v1 # length=128
## Web Client (Redirect)
#WEB_CLIENT_LOCATION=https://element-web.example.com
## State compression (reduces database bloat from federation)
## Runs synapse_auto_compressor daily, built from source on first start
#COMPOSE_FILE="$COMPOSE_FILE:compose.compress-state.yml"
# See https://github.com/matrix-org/rust-synapse-compress-state#running-options
#STATE_COMPRESS_CHUNK_SIZE=500
#STATE_COMPRESS_CHUNKS=100
#STATE_COMPRESS_SCHEDULE=0 3 * * *
## Admin interface at /admin
#COMPOSE_FILE="$COMPOSE_FILE:compose.admin.yml"
#ADMIN_INTERFACE_ENABLED=1
+46
View File
@@ -45,6 +45,52 @@ See [`#27`](https://git.coopcloud.tech/coop-cloud/matrix-synapse/pulls/27) for m
You'll need to deploy something like [this](https://git.autonomic.zone/ruangrupa/well-known-uris). This could be implemented in this recipe but we haven't merged it in yet. Change sets are welcome.
### Matrix Authentication Service (MAS)
[MAS](https://element-hq.github.io/matrix-authentication-service/) is Elements OAuth/OIDC-native auth service for Matrix: it handles login, tokens, and upstream IdPs while Synapse delegates authentication via `matrix_authentication_service`.
**Enable the stack:**
- In `.env`, uncomment `compose.mas.yml` (and `compose.mas-upstream.yml` plus upstream envs if you use an external IdP), and uncomment the `SECRET_MAS_*` version lines.
- `abra app secret generate YOURAPPDOMAIN`
- **Manually insert** the PEM RSA key for `SECRET_MAS_SIGNING_RSA_VERSION` (`generate=false` in `.env.sample`) — abra cannot generate that format; see the comment there (e.g. `openssl genrsa 2048` piped to `abra app secret insert`).
- `abra app cmd YOURAPPDOMAIN db ensure_mas_database` (once, creates the `mas` database in Postgres)
- `abra app deploy YOURAPPDOMAIN`
**If you plan to migrate an existing homeserver with `syn2mas`:** deploy and configure MAS as above, but **leave `MAS_ENABLED=1` commented** until migration and cutover are done, so Synapse keeps using your current login path until you intentionally switch. You cannot use Synapse legacy OIDC/Keycloak SSO alongside MAS; plan IdP apps and envs accordingly.
**Sign in with QR (experimental):** With `MAS_ENABLED=1`, set `QR_LOGIN_ENABLED=1` in `.env` and redeploy. Synapse then enables experimental [MSC4108](https://github.com/element-hq/synapse/issues/19434) Sign in with QR and `login_via_existing_session`. Optionally set `MSC4388_MODE` to `public` or `authenticated` for the newer rendezvous path ([MSC4388](https://github.com/element-hq/synapse/issues/19433)); omit it or use `off` for MSC4108-only. Client support and proxy caveats (CORS, ETag) are described in those issues.
<details>
<summary><strong>Migrating an existing server (<code>syn2mas</code>)</strong></summary>
Requires PostgreSQL on Synapse and a dedicated MAS database. Backup Postgres (and configs) before you start. Official background: [MAS migration guide](https://element-hq.github.io/matrix-authentication-service/setup/migration.html).
1. **Prepare (Synapse still running):** With MAS in `COMPOSE_FILE` but **`MAS_ENABLED` still off**, deploy, then run checks from your machine:
```bash
abra app cmd YOURAPPDOMAIN prepare_mas_migration
```
This fetches rendered `homeserver.yaml` into the MAS container, runs `syn2mas check`, then `migrate --dry-run` (the dry run rolls back MAS data at the end). The file stays in the MAS container until next restart, so you can repeat this step to provide the file for the actual migration.
2. **Optional snapshot:** save a copy of the rendered config while `app` is up, e.g. `abra app run -t YOURAPPDOMAIN app cat /data/homeserver.yaml > homeserver.snapshot.yaml`.
3. **Downtime — stop Synapse:** run on the **host** with Docker/Swarm access (not inside a container), e.g.:
```bash
docker service scale <STACK_NAME>_app=0
```
Use the real service name from `docker service ls` (suffix `_app`).
4. **Migration:** with MAS still running and Synapse at zero replicas,
```bash
abra app run YOURAPPDOMAIN mas -- mas-cli syn2mas migrate \
--config /etc/mas/config.yaml \
--synapse-config /tmp/homeserver.yaml
```
5. **Cutover:** in `.env`, set `MAS_ENABLED=1`, `PASSWORD_LOGIN_ENABLED=false`, remove legacy Keycloak/SSO envs, then `abra app deploy YOURAPPDOMAIN` (Synapse comes back with MAS delegation). `syn2mas` does not write to the Synapse database; if you abort before serving traffic through MAS, you can often drop and recreate the MAS DB and revert env.
</details>
## Bridges
For all Bridges:
- Setting it up is a bit of a chicken/egg & chasing cats moment.
+35 -161
View File
@@ -1,187 +1,61 @@
export DISCORD_BRIDGE_YAML_VERSION=v2
export ENTRYPOINT_CONF_VERSION=v3
export HOMESERVER_YAML_VERSION=v35
export HOMESERVER_YAML_VERSION=v37
export LOG_CONFIG_VERSION=v2
export SHARED_SECRET_AUTH_VERSION=v2
export SIGNAL_BRIDGE_YAML_VERSION=v6
export TELEGRAM_BRIDGE_YAML_VERSION=v6
export NGINX_CONFIG_VERSION=v12
export NGINX_CONFIG_VERSION=v13
export WK_SERVER_VERSION=v1
export WK_CLIENT_VERSION=v1
export WK_CLIENT_VERSION=v2
export MAS_CONFIG_VERSION=v1
export PG_BACKUP_VERSION=v2
export ADMIN_CONFIG_VERSION=v1
export COMPRESS_STATE_ENTRYPOINT_VERSION=v5
# See https://levans.fr/shrink-synapse-database.html
db_size() {
echo "=== Database size ==="
psql -U synapse -d synapse -c "SELECT pg_size_pretty(pg_database_size('synapse')) AS db_size;"
echo ""
echo "=== Top 10 largest tables ==="
psql -U synapse -d synapse -c "
SELECT nspname || '.' || relname AS table,
pg_size_pretty(pg_total_relation_size(C.oid)) AS total_size
FROM pg_class C
LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
WHERE nspname NOT IN ('pg_catalog', 'information_schema')
ORDER BY pg_total_relation_size(C.oid) DESC
LIMIT 10;"
ensure_mas_database () {
if ! psql -U synapse -d postgres -v ON_ERROR_STOP=1 -Atqc "SELECT 1 FROM pg_database WHERE datname = 'mas'" | grep -qx 1
then
psql -U synapse -d postgres -v ON_ERROR_STOP=1 -c "CREATE DATABASE mas OWNER synapse"
fi
}
state_bloat() {
echo "=== Rooms with most state bloat ==="
psql -U synapse -d synapse -c "
SELECT room_id, count(*) AS state_entries
FROM state_groups_state
GROUP BY room_id
ORDER BY state_entries DESC
LIMIT 20;"
}
# Local helper: fetch homeserver.yaml from app, push to mas, then syn2mas check + dry-run.
prepare_mas_migration () {
local hs_local syn_cfg
empty_rooms() {
echo "=== Rooms with no local members ==="
psql -U synapse -d synapse -c "
SELECT room_id, room_version
FROM rooms
WHERE room_id NOT IN (
SELECT room_id FROM local_current_membership WHERE membership = 'join'
);"
}
syn_cfg=/tmp/homeserver.yaml
reindex() {
echo "WARNING: REINDEX locks tables. Synapse should be stopped before running this."
echo "Running REINDEX on synapse database..."
psql -U synapse -d synapse -c "REINDEX (VERBOSE) DATABASE synapse;"
echo "REINDEX complete."
psql -U synapse -d synapse -c "SELECT pg_size_pretty(pg_database_size('synapse')) AS db_size;"
}
cleanup_prepare_mas_migration() {
rm -f "homeserver.yaml"
}
trap cleanup_prepare_mas_migration EXIT
# Run via: abra app cmd <domain> compress-state run_compressor
run_compressor() {
CHUNK_SIZE="${1:-${STATE_COMPRESS_CHUNK_SIZE:-500}}"
CHUNKS="${2:-${STATE_COMPRESS_CHUNKS:-100}}"
DB_PASS=$(cat /run/secrets/db_password)
echo "Running synapse_auto_compressor (chunk_size=$CHUNK_SIZE, chunks=$CHUNKS)..."
/build/synapse_auto_compressor \
-p "postgresql://synapse:${DB_PASS}@db:5432/synapse" \
-c "$CHUNK_SIZE" -n "$CHUNKS"
}
vacuum_full() {
echo "WARNING: VACUUM FULL locks tables and requires temporary disk space."
echo "Synapse should be stopped before running this."
echo "Running VACUUM FULL on synapse database..."
psql -U synapse -d synapse -c "VACUUM FULL;"
echo "VACUUM FULL complete."
psql -U synapse -d synapse -c "SELECT pg_size_pretty(pg_database_size('synapse')) AS db_size;"
}
# Purge commands — run via: abra app cmd <domain> app <command>
# These use the Synapse admin API and require an admin access token.
register_admin() {
USER="${1}"
PASS="${2}"
if [ -z "$USER" ] || [ -z "$PASS" ]; then
echo "Usage: register_admin <username> <password>"
echo "Fetching /data/homeserver.yaml from app to homeserver.yaml (abra app run … cat)..."
if ! abra app run -t "$DOMAIN" app cat /data/homeserver.yaml > "homeserver.yaml"
then
return 1
fi
register_new_matrix_user -u "$USER" -p "$PASS" -a -c /data/homeserver.yaml http://localhost:8008
}
get_token() {
USER="${1}"
PASS="${2}"
if [ -z "$USER" ] || [ -z "$PASS" ]; then
echo "Usage: get_token <username> <password>"
echo "Returns an admin access token for use with purge commands."
if [ ! -s "homeserver.yaml" ]; then
echo "Error: fetched homeserver.yaml is empty." >&2
return 1
fi
curl -s -X POST "http://localhost:8008/_matrix/client/r0/login" \
-H "Content-Type: application/json" \
-d "{\"type\":\"m.login.password\",\"user\":\"$USER\",\"password\":\"$PASS\"}" \
| python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('access_token', d.get('error', 'unknown error')))"
}
purge_remote_media() {
DAYS="${1:-30}"
TOKEN="${2}"
if [ -z "$TOKEN" ]; then
echo "Usage: purge_remote_media <days> <admin_token>"
return 1
fi
BEFORE_TS=$(( $(date +%s) * 1000 - DAYS * 86400000 ))
echo "Purging remote media older than $DAYS days..."
curl -s -X POST "http://localhost:8008/_synapse/admin/v1/purge_media_cache?before_ts=$BEFORE_TS" \
-H "Authorization: Bearer $TOKEN"
echo ""
}
echo "Copying into mas:/tmp"
abra app cp -C "$DOMAIN" "homeserver.yaml" "mas:/tmp" || return 1
purge_room() {
ROOM_ID="${1}"
TOKEN="${2}"
if [ -z "$ROOM_ID" ] || [ -z "$TOKEN" ]; then
echo "Usage: purge_room <room_id> <admin_token>"
return 1
fi
echo "Purging room $ROOM_ID..."
curl -s -X DELETE "http://localhost:8008/_synapse/admin/v1/rooms/$ROOM_ID" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"purge": true}'
echo ""
}
echo "Running mas-cli syn2mas check..."
abra app run -t "$DOMAIN" mas -- mas-cli syn2mas check \
--config /etc/mas/config.yaml \
--synapse-config "$syn_cfg" || return 1
purge_history() {
ROOM_ID="${1}"
DAYS="${2:-90}"
TOKEN="${3}"
if [ -z "$ROOM_ID" ] || [ -z "$TOKEN" ]; then
echo "Usage: purge_history <room_id> <days> <admin_token>"
return 1
fi
BEFORE_TS=$(( $(date +%s) * 1000 - DAYS * 86400000 ))
echo "Purging history older than $DAYS days from $ROOM_ID..."
curl -s -X POST "http://localhost:8008/_synapse/admin/v1/purge_history/$ROOM_ID" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{\"purge_up_to_ts\": $BEFORE_TS}"
echo ""
}
echo "Running mas-cli syn2mas migrate --dry-run..."
abra app run -t "$DOMAIN" mas -- mas-cli syn2mas migrate \
--config /etc/mas/config.yaml \
--synapse-config "$syn_cfg" \
--dry-run || return 1
purge_empty_rooms() {
TOKEN="${1}"
if [ -z "$TOKEN" ]; then
echo "Usage: purge_empty_rooms <admin_token>"
return 1
fi
echo "Fetching rooms with no local members..."
ROOMS=$(curl -s "http://localhost:8008/_synapse/admin/v1/rooms?limit=1000" \
-H "Authorization: Bearer $TOKEN" \
| python3 -c "
import sys, json
data = json.load(sys.stdin)
for r in data.get('rooms', []):
if r.get('joined_local_members', 0) == 0:
print(r['room_id'])
")
COUNT=$(echo "$ROOMS" | grep -c '.' || true)
echo "Found $COUNT empty rooms."
if [ "$COUNT" -eq 0 ]; then
echo "Nothing to purge."
return 0
fi
echo "$ROOMS"
echo ""
echo "Purging..."
for ROOM_ID in $ROOMS; do
echo " Purging $ROOM_ID"
curl -s -X DELETE "http://localhost:8008/_synapse/admin/v1/rooms/$ROOM_ID" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"purge": true}' > /dev/null
done
echo "Done."
# trap - EXIT
# cleanup_prepare_mas_migration
}
set_admin () {
-31
View File
@@ -1,31 +0,0 @@
version: "3.8"
services:
compress-state:
image: rust:1-alpine
entrypoint: /compress_state_entrypoint.sh
environment:
- STATE_COMPRESS_CHUNK_SIZE=${STATE_COMPRESS_CHUNK_SIZE:-500}
- STATE_COMPRESS_CHUNKS=${STATE_COMPRESS_CHUNKS:-100}
- STATE_COMPRESS_SCHEDULE=${STATE_COMPRESS_SCHEDULE:-0 3 * * *}
secrets:
- db_password
configs:
- source: compress_entrypoint
target: /compress_state_entrypoint.sh
mode: 0555
volumes:
- compress_state_build:/build
networks:
- internal
deploy:
restart_policy:
condition: on-failure
volumes:
compress_state_build:
configs:
compress_entrypoint:
name: ${STACK_NAME}_compress_ep_${COMPRESS_STATE_ENTRYPOINT_VERSION}
file: compress_state_entrypoint.sh
+21
View File
@@ -0,0 +1,21 @@
---
version: "3.8"
# Upstream OIDC provider for MAS (e.g. Authentik, Keycloak).
# Requires compose.mas.yml. Adds the client secret and env vars needed by mas.config.yaml.tmpl.
services:
mas:
environment:
- MAS_UPSTREAM_PROVIDER_ID
- MAS_UPSTREAM_ISSUER
- MAS_UPSTREAM_CLIENT_ID
- MAS_UPSTREAM_HUMAN_NAME
- MAS_UPSTREAM_SYNAPSE_IDP_ID
secrets:
- mas_upstream_client_secret
secrets:
mas_upstream_client_secret:
external: true
name: ${STACK_NAME}_mas_upstream_client_secret_${SECRET_MAS_UPSTREAM_CLIENT_SECRET_VERSION}
+64
View File
@@ -0,0 +1,64 @@
---
version: "3.8"
# Matrix Authentication Service (MAS) — optional overlay for Element X / OIDC-native auth.
services:
mas:
image: ghcr.io/element-hq/matrix-authentication-service:1.14.0
command: ["server", "--config=/etc/mas/config.yaml"]
environment:
- DOMAIN
- SERVER_NAME
- STACK_NAME
networks:
- internal
configs:
- source: mas_config
target: /etc/mas/config.yaml
secrets:
- db_password
- mas_encryption
- mas_synapse_shared
- mas_signing_rsa
# Official image is distroless (no curl/wget); upstream suggests `mas-cli config check` for probes.
# See https://github.com/element-hq/matrix-authentication-service/issues/3741 — validates config, not HTTP.
# GET /health is still served (resource `health` in mas.config.yaml.tmpl) for probes from other images.
healthcheck:
test:
[
"CMD",
"/usr/local/bin/mas-cli",
"--config",
"/etc/mas/config.yaml",
"config",
"check",
]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
deploy:
restart_policy:
condition: on-failure
app:
secrets:
- mas_synapse_shared
configs:
mas_config:
name: ${STACK_NAME}_mas_config_${MAS_CONFIG_VERSION}
file: mas.config.yaml.tmpl
template_driver: golang
secrets:
mas_encryption:
external: true
name: ${STACK_NAME}_mas_encryption_${SECRET_MAS_ENCRYPTION_VERSION}
mas_synapse_shared:
external: true
name: ${STACK_NAME}_mas_synapse_shared_${SECRET_MAS_SYNAPSE_SHARED_VERSION}
mas_signing_rsa:
external: true
name: ${STACK_NAME}_mas_signing_rsa_${SECRET_MAS_SIGNING_RSA_VERSION}
+4
View File
@@ -10,6 +10,7 @@ services:
environment:
- DOMAIN
- STACK_NAME
- MAS_ENABLED
- NGINX_ACCESS_LOG_LOCATION
- NGINX_ERROR_LOG_LOCATION
- MAX_UPLOAD_SIZE
@@ -46,6 +47,9 @@ services:
- macaroon
- form_secret
environment:
- MAS_ENABLED
- QR_LOGIN_ENABLED
- MSC4388_MODE
- ALLOWED_LIFETIME_MAX
- ALLOW_PUBLIC_ROOMS_FEDERATION
- AUTO_JOIN_ROOM
-46
View File
@@ -1,46 +0,0 @@
#!/bin/sh
set -e
BINARY="/build/synapse_auto_compressor"
REPO_DIR="/build/rust-synapse-compress-state"
DB_PASS=$(cat /run/secrets/db_password)
CONN="postgresql://synapse:${DB_PASS}@db:5432/synapse"
CHUNK_SIZE="${STATE_COMPRESS_CHUNK_SIZE:-500}"
CHUNKS="${STATE_COMPRESS_CHUNKS:-100}"
SCHEDULE="${STATE_COMPRESS_SCHEDULE:-0 3 * * *}"
# Build from source if binary doesn't exist
if [ ! -f "$BINARY" ]; then
echo "[compress-state] Binary not found, building from source..."
apk add --no-cache git openssl-dev openssl-libs-static perl make musl-dev jemalloc-dev
rm -rf "$REPO_DIR"
git clone https://github.com/matrix-org/rust-synapse-compress-state "$REPO_DIR"
cd "$REPO_DIR"
cargo build --release -p synapse_auto_compressor
cp target/release/synapse_auto_compressor "$BINARY"
echo "[compress-state] Build complete"
# Clean up source to save space
rm -rf "$REPO_DIR"
else
echo "[compress-state] Using cached binary"
fi
# Run once at startup
echo "[compress-state] Running initial compression at $(date)"
"$BINARY" -p "$CONN" -c "$CHUNK_SIZE" -n "$CHUNKS" || echo "[compress-state] Error: $?"
# Set up cron job
CRON_SCRIPT="/build/run_compressor.sh"
cat > "$CRON_SCRIPT" <<EOF
#!/bin/sh
echo "[compress-state] Running at \$(date)"
$BINARY -p "$CONN" -c $CHUNK_SIZE -n $CHUNKS || echo "[compress-state] Error: \$?"
echo "[compress-state] Done at \$(date)"
EOF
chmod +x "$CRON_SCRIPT"
echo "$SCHEDULE $CRON_SCRIPT" | crontab -
echo "[compress-state] Cron scheduled: $SCHEDULE"
# Run crond in the foreground
exec crond -f -l 2
+405 -317
View File
@@ -1,317 +1,405 @@
# All configuration options are documented on the following link:
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html
{{ if eq (env "SHARED_SECRET_AUTH_ENABLED") "1" }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#modules-1
modules:
- module: shared_secret_authenticator.SharedSecretAuthProvider
config:
shared_secret: {{ secret "shared_secret_auth" }}
m_login_password_support_enabled: true
{{ end }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#server_name
server_name: {{ or (env "SERVER_NAME") (env "DOMAIN") }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#public_baseurl
public_baseurl: https://{{ env "DOMAIN" }}/
# https://element-hq.github.io/synapse/latest/usage/configuration/config_documentation.html#require_auth_for_profile_requests
require_auth_for_profile_requests: {{ env "REQUIRE_AUTH_FOR_PROFILE_REQUESTS" }}
# https://element-hq.github.io/synapse/latest/usage/configuration/config_documentation.html#limit_profile_requests_to_users_who_share_rooms
limit_profile_requests_to_users_who_share_rooms: {{ env "LIMIT_PROFILE_REQUESTS_TO_USERS_WHO_SHARE_ROOMS" }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#serve_server_wellknown
serve_server_wellknown: {{ env "SERVE_SERVER_WELLKNOWN" }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#allow_public_rooms_without_auth
allow_public_rooms_without_auth: false
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#allow_public_rooms_over_federation
allow_public_rooms_over_federation: {{ or (env "ALLOW_PUBLIC_ROOMS_FEDERATION") "true" }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#listeners
listeners:
- port: 8008
tls: false
type: http
x_forwarded: true
{{ if eq (env "DISABLE_FEDERATION") "1" }}
resources:
{{ if eq (env "KEYCLOAK_ENABLED") "1" }}
- names: [client, openid]
compress: true
{{ else }}
- names: [client]
compress: true
{{ end }}
{{ else }}
resources:
{{ if eq (env "KEYCLOAK_ENABLED") "1" }}
- names: [client, openid, federation]
compress: true
{{ else }}
- names: [client, federation]
compress: true
{{ end }}
{{ end }}
# https://element-hq.github.io/synapse/latest/usage/configuration/config_documentation.html#delete_stale_devices_after
{{ if (env "DELETE_STALE_DEVICES_AFTER") }}
delete_stale_devices_after: {{ env "DELETE_STALE_DEVICES_AFTER" }}
{{ end }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#admin_contact
admin_contact: 'mailto:{{ env "ADMIN_EMAIL" }}'
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#limit_remote_rooms
limit_remote_rooms:
enabled: true
complexity: 200.0
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#max_avatar_size
max_avatar_size: 10M
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#forgotten_room_retention_period
forgotten_room_retention_period: 3d
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#request_token_inhibit_3pid_errors
request_token_inhibit_3pid_errors: true
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#redaction_retention_period
redaction_retention_period: {{ env "REDACTION_RETENTION_PERIOD" }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#user_ips_max_age
user_ips_max_age: {{ env "USER_IPS_MAX_AGE" }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#retention
retention:
enabled: true
default_policy:
min_lifetime: 1d
max_lifetime: {{ env "RETENTION_MAX_LIFETIME" }}
allowed_lifetime_min: 1d
allowed_lifetime_max: {{ env "ALLOWED_LIFETIME_MAX" }}
purge_jobs:
- longest_max_lifetime: 3d
interval: 12h
- shortest_max_lifetime: 3d
interval: 1d
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#federation_domain_whitelist
{{ if eq (env "DISABLE_FEDERATION") "1" }}
federation_domain_whitelist: []
{{ else if eq (env "ENABLE_ALLOWLIST") "1" }}
federation_domain_whitelist: {{ env "FEDERATION_ALLOWLIST" }}
{{ end }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#database-1
database:
name: psycopg2
txn_limit: 10000
args:
user: synapse
password: "{{ secret "db_password" }}"
database: synapse
host: "{{ env "STACK_NAME" }}_db"
port: 5432
cp_min: 5
cp_max: 10
keepalives_idle: 10
keepalives_interval: 10
keepalives_count: 3
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#log_config
log_config: "/data/log.config"
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#media_store_path
media_store_path: "/data/media_store"
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#max_upload_size
max_upload_size: 50M
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#turn
{{ if eq (env "TURN_ENABLED") "1" }}
turn_uris: {{ env "TURN_URIS" }}
turn_shared_secret: "{{ secret "turn_shared_secret" }}"
turn_user_lifetime: 1h
turn_allow_guests: {{ env "TURN_ALLOW_GUESTS" }}
{{ end }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#enable_registration
enable_registration: {{ env "ENABLE_REGISTRATION" }}
# https://element-hq.github.io/synapse/latest/usage/configuration/config_documentation.html#registration_requires_token
registration_requires_token: {{ env "REGISTRATION_REQUIRES_TOKEN" }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#enable_3pid_lookup
enable_3pid_lookup: {{ env "ENABLE_3PID_LOOKUP" }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#allow_guest_access
allow_guest_access: false
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#registration_shared_secret
registration_shared_secret: {{ secret "registration" }}
{{ if eq (env "AUTO_JOIN_ROOM_ENABLED") "1" }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#auto_join_rooms
# AUTO_JOIN_ROOM only for backwards compatibility
{{ if (env "AUTO_JOIN_ROOM") }}
auto_join_rooms:
- "{{ env "AUTO_JOIN_ROOM" }}"
{{ else }}
auto_join_rooms: {{ env "AUTO_JOIN_ROOM_LIST" }}
{{ end }}
{{ end }}
# https://element-hq.github.io/synapse/latest/usage/configuration/config_documentation.html#session_lifetime
{{ if (env "SESSION_LIFETIME") }}
session_lifetime: {{ env "SESSION_LIFETIME" }}
{{ end }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#report_stats
report_stats: false
# https://element-hq.github.io/synapse/latest/usage/configuration/config_documentation.html#track_puppeted_user_ips
track_puppeted_user_ips: {{ env "TRACK_PUPPETED_USER_IPS" }}
{{ if eq (env "APP_SERVICES_ENABLED") "1" }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#app_service_config_files
app_service_config_files: {{ env "APP_SERVICE_CONFIGS" }}
{{ end }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#macaroon_secret_key
macaroon_secret_key: "{{ secret "macaroon" }}"
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#form_secret
form_secret: "{{ secret "form_secret" }}"
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#signing_key_path
signing_key_path: "/data/{{ env "DOMAIN" }}.signing.key"
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#old_signing_keys
{{ if (and (env "OLD_SIGNING_KEY_ID") (env "OLD_SIGNING_KEY") (env "OLD_SIGNING_KEY_EXPIRES")) }}
old_signing_keys:
"ed25519:{{ env "OLD_SIGNING_KEY_ID" }}": { key: "{{ env "OLD_SIGNING_KEY" }}", expired_ts: {{ env "OLD_SIGNING_KEY_EXPIRES" }} }
{{ end }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#trusted_key_servers
{{ if eq (env "ENABLE_ALLOWLIST") "1" }}
trusted_key_servers: [] # NOTE(d1): defaults to requesting server directly, which matches FEDERATION_ALLOWLIST
{{ else }}
trusted_key_servers:
- server_name: "matrix.org"
{{ end }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#oidc_providers
{{ if eq (env "KEYCLOAK_ENABLED") "1" }}
oidc_providers:
- idp_id: {{ env "KEYCLOAK_ID" }}
idp_name: {{ env "KEYCLOAK_NAME" }}
issuer: "{{ env "KEYCLOAK_URL" }}"
client_id: "{{ env "KEYCLOAK_CLIENT_ID" }}"
client_secret: "{{ secret "keycloak_client_secret" }}"
scopes: ["openid", "profile"]
allow_existing_users: {{ env "KEYCLOAK_ALLOW_EXISTING_USERS" }}
user_mapping_provider:
config:
localpart_template: "{{ "{{ user.preferred_username }}" }}"
display_name_template: "{{ "{{ user.name }}" }}"
{{ if eq (env "KEYCLOAK2_ENABLED") "1" }}
- idp_id: {{ env "KEYCLOAK2_ID" }}
idp_name: {{ env "KEYCLOAK2_NAME" }}
issuer: "{{ env "KEYCLOAK2_URL" }}"
client_id: "{{ env "KEYCLOAK2_CLIENT_ID" }}"
client_secret: "{{ secret "keycloak2_client_secret" }}"
scopes: ["openid", "profile"]
allow_existing_users: {{ env "KEYCLOAK2_ALLOW_EXISTING_USERS" }}
user_mapping_provider:
config:
localpart_template: "{{ "{{ user.preferred_username }}" }}"
display_name_template: "{{ "{{ user.name }}" }}"
{{ end }}
{{ if eq (env "KEYCLOAK3_ENABLED") "1" }}
- idp_id: {{ env "KEYCLOAK3_ID" }}
idp_name: {{ env "KEYCLOAK3_NAME" }}
issuer: "{{ env "KEYCLOAK3_URL" }}"
client_id: "{{ env "KEYCLOAK3_CLIENT_ID" }}"
client_secret: "{{ secret "keycloak3_client_secret" }}"
scopes: ["openid", "profile"]
allow_existing_users: {{ env "KEYCLOAK3_ALLOW_EXISTING_USERS" }}
user_mapping_provider:
config:
localpart_template: "{{ "{{ user.preferred_username }}" }}"
display_name_template: "{{ "{{ user.name }}" }}"
{{ end }}
{{ end }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#sso
{{ if eq (env "KEYCLOAK_ENABLED") "1" }}
sso:
client_whitelist:
- https://{{ env "KEYCLOAK_CLIENT_DOMAIN" }}
{{ end }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#password_config
password_config:
enabled: {{ env "PASSWORD_LOGIN_ENABLED" }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#email
{{ if eq (env "SMTP_ENABLED") "1" }}
email:
smtp_host: {{ env "SMTP_HOST" }}
smtp_port: {{ env "SMTP_PORT" }}
smtp_user: {{ env "SMTP_USER" }}
smtp_pass: "{{ secret "smtp_password" }}"
require_transport_security: true
notif_from: Your Friendly %(app)s homeserver <{{ env "SMTP_FROM" }}>
app_name: {{ env "SMTP_APP_NAME" }}
enable_notifs: true
client_base_url: https://{{ env "DOMAIN" }}
{{ end }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#encryption_enabled_by_default_for_room_type
encryption_enabled_by_default_for_room_type: {{ env "ENCRYPTED_BY_DEFAULT" }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#user_directory
user_directory:
enabled: {{ env "USER_DIRECTORY_ENABLED" }}
search_all_users: {{ env "USER_DIRECTORY_SEARCH_ALL_USERS" }}
prefer_local_users: {{ env "USER_DIRECTORY_PREFER_LOCAL_USERS" }}
show_locked_users: {{ env "USER_DIRECTORY_SHOW_LOCKED_USERS" }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#media_retention
media_retention:
local_media_lifetime: {{ env "MEDIA_RETENTION_LOCAL_LIFETIME" }}
remote_media_lifetime: {{ env "MEDIA_RETENTION_REMOTE_LIFETIME" }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#enable_metrics
enable_metrics: false
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#track_appservice_user_ips
track_appservice_user_ips: false
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#forget_rooms_on_leave
forget_rooms_on_leave: true
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#opentracing-1
opentracing:
enabled: false
# https://matrix-org.github.io/synapse/develop/usage/configuration/config_documentation.html#ratelimiting
rc_login:
address:
per_second: {{ env "LOGIN_LIMIT_IP_PER_SECOND" }}
burst_count: {{ env "LOGIN_LIMIT_IP_BURST" }}
account:
per_second: {{ env "LOGIN_LIMIT_ACCOUNT_PER_SECOND" }}
burst_count: {{ env "LOGIN_LIMIT_ACCOUNT_BURST" }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#web_client_location
web_client_location: {{ env "WEB_CLIENT_LOCATION" }}
# All configuration options are documented on the following link:
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html
{{ if eq (env "SHARED_SECRET_AUTH_ENABLED") "1" }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#modules-1
modules:
- module: shared_secret_authenticator.SharedSecretAuthProvider
config:
shared_secret: {{ secret "shared_secret_auth" }}
m_login_password_support_enabled: true
{{ end }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#server_name
server_name: {{ or (env "SERVER_NAME") (env "DOMAIN") }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#public_baseurl
public_baseurl: https://{{ env "DOMAIN" }}/
# https://element-hq.github.io/synapse/latest/usage/configuration/config_documentation.html#require_auth_for_profile_requests
{{ if (env "REQUIRE_AUTH_FOR_PROFILE_REQUESTS") }}
require_auth_for_profile_requests: {{ env "REQUIRE_AUTH_FOR_PROFILE_REQUESTS" }}
{{ end }}
# https://element-hq.github.io/synapse/latest/usage/configuration/config_documentation.html#limit_profile_requests_to_users_who_share_rooms
{{ if (env "LIMIT_PROFILE_REQUESTS_TO_USERS_WHO_SHARE_ROOMS") }}
limit_profile_requests_to_users_who_share_rooms: {{ env "LIMIT_PROFILE_REQUESTS_TO_USERS_WHO_SHARE_ROOMS" }}
{{ end }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#serve_server_wellknown
{{ if (env "SERVE_SERVER_WELLKNOWN") }}
serve_server_wellknown: {{ env "SERVE_SERVER_WELLKNOWN" }}
{{ end }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#allow_public_rooms_without_auth
allow_public_rooms_without_auth: false
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#allow_public_rooms_over_federation
{{ if (env "ALLOW_PUBLIC_ROOMS_FEDERATION") }}
allow_public_rooms_over_federation: {{ env "ALLOW_PUBLIC_ROOMS_FEDERATION" }}
{{ end }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#listeners
listeners:
- port: 8008
tls: false
type: http
x_forwarded: true
{{ if eq (env "DISABLE_FEDERATION") "1" }}
resources:
{{ if eq (env "KEYCLOAK_ENABLED") "1" }}
- names: [client, openid]
compress: true
{{ else }}
- names: [client]
compress: true
{{ end }}
{{ else }}
resources:
{{ if eq (env "KEYCLOAK_ENABLED") "1" }}
- names: [client, openid, federation]
compress: true
{{ else }}
- names: [client, federation]
compress: true
{{ end }}
{{ end }}
# https://element-hq.github.io/synapse/latest/usage/configuration/config_documentation.html#delete_stale_devices_after
{{ if (env "DELETE_STALE_DEVICES_AFTER") }}
delete_stale_devices_after: {{ env "DELETE_STALE_DEVICES_AFTER" }}
{{ end }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#admin_contact
{{ if (env "ADMIN_EMAIL") }}
admin_contact: 'mailto:{{ env "ADMIN_EMAIL" }}'
{{ end }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#limit_remote_rooms
limit_remote_rooms:
enabled: true
complexity: 200.0
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#max_avatar_size
max_avatar_size: 10M
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#forgotten_room_retention_period
forgotten_room_retention_period: 3d
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#request_token_inhibit_3pid_errors
request_token_inhibit_3pid_errors: true
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#redaction_retention_period
{{ if (env "REDACTION_RETENTION_PERIOD") }}
redaction_retention_period: {{ env "REDACTION_RETENTION_PERIOD" }}
{{ end }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#user_ips_max_age
{{ if (env "USER_IPS_MAX_AGE") }}
user_ips_max_age: {{ env "USER_IPS_MAX_AGE" }}
{{ end }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#retention
retention:
enabled: true
default_policy:
min_lifetime: 1d
{{ if (env "RETENTION_MAX_LIFETIME") }}
max_lifetime: {{ env "RETENTION_MAX_LIFETIME" }}
{{ end }}
allowed_lifetime_min: 1d
{{ if (env "ALLOWED_LIFETIME_MAX") }}
allowed_lifetime_max: {{ env "ALLOWED_LIFETIME_MAX" }}
{{ end }}
purge_jobs:
- longest_max_lifetime: 3d
interval: 12h
- shortest_max_lifetime: 3d
interval: 1d
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#federation_domain_whitelist
{{ if eq (env "DISABLE_FEDERATION") "1" }}
federation_domain_whitelist: []
{{ else if eq (env "ENABLE_ALLOWLIST") "1" }}
federation_domain_whitelist: {{ env "FEDERATION_ALLOWLIST" }}
{{ end }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#database-1
database:
name: psycopg2
txn_limit: 10000
args:
user: synapse
password: "{{ secret "db_password" }}"
database: synapse
host: "{{ env "STACK_NAME" }}_db"
port: 5432
cp_min: 5
cp_max: 10
keepalives_idle: 10
keepalives_interval: 10
keepalives_count: 3
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#log_config
log_config: "/data/log.config"
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#media_store_path
media_store_path: "/data/media_store"
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#max_upload_size
max_upload_size: 50M
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#turn
{{ if eq (env "TURN_ENABLED") "1" }}
{{ if (env "TURN_URIS") }}
turn_uris: {{ env "TURN_URIS" }}
{{ end }}
turn_shared_secret: "{{ secret "turn_shared_secret" }}"
turn_user_lifetime: 1h
{{ if (env "TURN_ALLOW_GUESTS") }}
turn_allow_guests: {{ env "TURN_ALLOW_GUESTS" }}
{{ end }}
{{ end }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#enable_registration
{{ if (env "ENABLE_REGISTRATION") }}
enable_registration: {{ env "ENABLE_REGISTRATION" }}
{{ end }}
# https://element-hq.github.io/synapse/latest/usage/configuration/config_documentation.html#registration_requires_token
{{ if (env "REGISTRATION_REQUIRES_TOKEN") }}
registration_requires_token: {{ env "REGISTRATION_REQUIRES_TOKEN" }}
{{ end }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#enable_3pid_lookup
{{ if (env "ENABLE_3PID_LOOKUP") }}
enable_3pid_lookup: {{ env "ENABLE_3PID_LOOKUP" }}
{{ end }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#allow_guest_access
allow_guest_access: false
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#registration_shared_secret
registration_shared_secret: {{ secret "registration" }}
{{ if eq (env "AUTO_JOIN_ROOM_ENABLED") "1" }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#auto_join_rooms
# AUTO_JOIN_ROOM only for backwards compatibility
{{ if (env "AUTO_JOIN_ROOM") }}
auto_join_rooms:
- "{{ env "AUTO_JOIN_ROOM" }}"
{{ else }}
auto_join_rooms: {{ env "AUTO_JOIN_ROOM_LIST" }}
{{ end }}
{{ end }}
# https://element-hq.github.io/synapse/latest/usage/configuration/config_documentation.html#session_lifetime
{{ if (env "SESSION_LIFETIME") }}
session_lifetime: {{ env "SESSION_LIFETIME" }}
{{ end }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#report_stats
report_stats: false
# https://element-hq.github.io/synapse/latest/usage/configuration/config_documentation.html#track_puppeted_user_ips
{{ if (env "TRACK_PUPPETED_USER_IPS") }}
track_puppeted_user_ips: {{ env "TRACK_PUPPETED_USER_IPS" }}
{{ end }}
{{ if eq (env "APP_SERVICES_ENABLED") "1" }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#app_service_config_files
app_service_config_files: {{ env "APP_SERVICE_CONFIGS" }}
{{ end }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#macaroon_secret_key
macaroon_secret_key: "{{ secret "macaroon" }}"
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#form_secret
form_secret: "{{ secret "form_secret" }}"
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#signing_key_path
signing_key_path: "/data/{{ env "DOMAIN" }}.signing.key"
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#old_signing_keys
{{ if (and (env "OLD_SIGNING_KEY_ID") (env "OLD_SIGNING_KEY") (env "OLD_SIGNING_KEY_EXPIRES")) }}
old_signing_keys:
"ed25519:{{ env "OLD_SIGNING_KEY_ID" }}": { key: "{{ env "OLD_SIGNING_KEY" }}", expired_ts: {{ env "OLD_SIGNING_KEY_EXPIRES" }} }
{{ end }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#trusted_key_servers
{{ if eq (env "ENABLE_ALLOWLIST") "1" }}
trusted_key_servers: [] # NOTE(d1): defaults to requesting server directly, which matches FEDERATION_ALLOWLIST
{{ else }}
trusted_key_servers:
- server_name: "matrix.org"
{{ end }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#oidc_providers
{{ if eq (env "KEYCLOAK_ENABLED") "1" }}
oidc_providers:
- idp_id: {{ env "KEYCLOAK_ID" }}
idp_name: {{ env "KEYCLOAK_NAME" }}
issuer: "{{ env "KEYCLOAK_URL" }}"
client_id: "{{ env "KEYCLOAK_CLIENT_ID" }}"
client_secret: "{{ secret "keycloak_client_secret" }}"
scopes: ["openid", "profile"]
{{ if (env "KEYCLOAK_ALLOW_EXISTING_USERS") }}
allow_existing_users: {{ env "KEYCLOAK_ALLOW_EXISTING_USERS" }}
{{ end }}
user_mapping_provider:
config:
localpart_template: "{{ "{{ user.preferred_username }}" }}"
display_name_template: "{{ "{{ user.name }}" }}"
{{ if eq (env "KEYCLOAK2_ENABLED") "1" }}
- idp_id: {{ env "KEYCLOAK2_ID" }}
idp_name: {{ env "KEYCLOAK2_NAME" }}
issuer: "{{ env "KEYCLOAK2_URL" }}"
client_id: "{{ env "KEYCLOAK2_CLIENT_ID" }}"
client_secret: "{{ secret "keycloak2_client_secret" }}"
scopes: ["openid", "profile"]
{{ if (env "KEYCLOAK2_ALLOW_EXISTING_USERS") }}
allow_existing_users: {{ env "KEYCLOAK2_ALLOW_EXISTING_USERS" }}
{{ end }}
user_mapping_provider:
config:
localpart_template: "{{ "{{ user.preferred_username }}" }}"
display_name_template: "{{ "{{ user.name }}" }}"
{{ end }}
{{ if eq (env "KEYCLOAK3_ENABLED") "1" }}
- idp_id: {{ env "KEYCLOAK3_ID" }}
idp_name: {{ env "KEYCLOAK3_NAME" }}
issuer: "{{ env "KEYCLOAK3_URL" }}"
client_id: "{{ env "KEYCLOAK3_CLIENT_ID" }}"
client_secret: "{{ secret "keycloak3_client_secret" }}"
scopes: ["openid", "profile"]
{{ if (env "KEYCLOAK3_ALLOW_EXISTING_USERS") }}
allow_existing_users: {{ env "KEYCLOAK3_ALLOW_EXISTING_USERS" }}
{{ end }}
user_mapping_provider:
config:
localpart_template: "{{ "{{ user.preferred_username }}" }}"
display_name_template: "{{ "{{ user.name }}" }}"
{{ end }}
{{ end }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#sso
{{ if eq (env "KEYCLOAK_ENABLED") "1" }}
sso:
client_whitelist:
- https://{{ env "KEYCLOAK_CLIENT_DOMAIN" }}
{{ end }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#password_config
# With MAS (matrix_authentication_service), Synapse rejects password_config.enabled: true — set PASSWORD_LOGIN_ENABLED=false in app .env when MAS_ENABLED=1 (.env.sample).
{{ if (env "PASSWORD_LOGIN_ENABLED") }}
password_config:
enabled: {{ env "PASSWORD_LOGIN_ENABLED" }}
{{ end }}
{{ if eq (env "MAS_ENABLED") "1" }}
# https://element-hq.github.io/synapse/latest/usage/configuration/config_documentation.html#matrix_authentication_service
matrix_authentication_service:
enabled: true
endpoint: http://{{ env "STACK_NAME"}}_mas:8080/
secret_path: /run/secrets/mas_synapse_shared
{{ end }}
{{ if and (eq (env "QR_LOGIN_ENABLED") "1") (eq (env "MAS_ENABLED") "1") }}
# Sign in with QR (MSC4108 / optional MSC4388). Requires matrix_authentication_service.
# https://github.com/element-hq/synapse/issues/19434 — https://github.com/element-hq/synapse/issues/19433
experimental_features:
msc4108_enabled: true
{{ if and (env "MSC4388_MODE") (ne (env "MSC4388_MODE") "off") }}
msc4388_mode: {{ env "MSC4388_MODE" }}
{{ end }}
# # https://element-hq.github.io/synapse/latest/usage/configuration/config_documentation.html#login_via_existing_session
# login_via_existing_session:
# enabled: true
# require_ui_auth: false
# token_timeout: 5m
{{ end }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#email
{{ if eq (env "SMTP_ENABLED") "1" }}
email:
smtp_host: {{ env "SMTP_HOST" }}
smtp_port: {{ env "SMTP_PORT" }}
smtp_user: {{ env "SMTP_USER" }}
smtp_pass: "{{ secret "smtp_password" }}"
require_transport_security: true
notif_from: Your Friendly %(app)s homeserver <{{ env "SMTP_FROM" }}>
app_name: {{ env "SMTP_APP_NAME" }}
enable_notifs: true
client_base_url: https://{{ env "DOMAIN" }}
{{ end }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#encryption_enabled_by_default_for_room_type
{{ if (env "ENCRYPTED_BY_DEFAULT") }}
encryption_enabled_by_default_for_room_type: {{ env "ENCRYPTED_BY_DEFAULT" }}
{{ end }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#user_directory
{{ if or (env "USER_DIRECTORY_ENABLED") (env "USER_DIRECTORY_SEARCH_ALL_USERS") (env "USER_DIRECTORY_PREFER_LOCAL_USERS") (env "USER_DIRECTORY_SHOW_LOCKED_USERS") }}
user_directory:
{{ if (env "USER_DIRECTORY_ENABLED") }}
enabled: {{ env "USER_DIRECTORY_ENABLED" }}
{{ end }}
{{ if (env "USER_DIRECTORY_SEARCH_ALL_USERS") }}
search_all_users: {{ env "USER_DIRECTORY_SEARCH_ALL_USERS" }}
{{ end }}
{{ if (env "USER_DIRECTORY_PREFER_LOCAL_USERS") }}
prefer_local_users: {{ env "USER_DIRECTORY_PREFER_LOCAL_USERS" }}
{{ end }}
{{ if (env "USER_DIRECTORY_SHOW_LOCKED_USERS") }}
show_locked_users: {{ env "USER_DIRECTORY_SHOW_LOCKED_USERS" }}
{{ end }}
{{ end }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#media_retention
{{ if or (env "MEDIA_RETENTION_LOCAL_LIFETIME") (env "MEDIA_RETENTION_REMOTE_LIFETIME") }}
media_retention:
{{ if (env "MEDIA_RETENTION_LOCAL_LIFETIME") }}
local_media_lifetime: {{ env "MEDIA_RETENTION_LOCAL_LIFETIME" }}
{{ end }}
{{ if (env "MEDIA_RETENTION_REMOTE_LIFETIME") }}
remote_media_lifetime: {{ env "MEDIA_RETENTION_REMOTE_LIFETIME" }}
{{ end }}
{{ end }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#enable_metrics
enable_metrics: false
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#track_appservice_user_ips
track_appservice_user_ips: false
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#forget_rooms_on_leave
forget_rooms_on_leave: true
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#opentracing-1
opentracing:
enabled: false
# https://matrix-org.github.io/synapse/develop/usage/configuration/config_documentation.html#ratelimiting
{{ if or (and (env "LOGIN_LIMIT_IP_PER_SECOND") (env "LOGIN_LIMIT_IP_BURST")) (and (env "LOGIN_LIMIT_ACCOUNT_PER_SECOND") (env "LOGIN_LIMIT_ACCOUNT_BURST")) }}
rc_login:
{{ if and (env "LOGIN_LIMIT_IP_PER_SECOND") (env "LOGIN_LIMIT_IP_BURST") }}
address:
per_second: {{ env "LOGIN_LIMIT_IP_PER_SECOND" }}
burst_count: {{ env "LOGIN_LIMIT_IP_BURST" }}
{{ end }}
{{ if and (env "LOGIN_LIMIT_ACCOUNT_PER_SECOND") (env "LOGIN_LIMIT_ACCOUNT_BURST") }}
account:
per_second: {{ env "LOGIN_LIMIT_ACCOUNT_PER_SECOND" }}
burst_count: {{ env "LOGIN_LIMIT_ACCOUNT_BURST" }}
{{ end }}
{{ end }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#web_client_location
{{ if (env "WEB_CLIENT_LOCATION") }}
web_client_location: {{ env "WEB_CLIENT_LOCATION" }}
{{ end }}
+73
View File
@@ -0,0 +1,73 @@
# Docs: https://element-hq.github.io/matrix-authentication-service/
http:
public_base: https://{{ env "DOMAIN" }}/
trusted_proxies:
- 10.0.0.0/8
- 172.16.0.0/12
- 192.168.0.0/16
- 127.0.0.0/8
- fd00::/8
- ::1/128
listeners:
- name: web
resources:
- name: discovery
- name: human
- name: oauth
- name: compat
- name: graphql
playground: false
- name: assets
# https://element-hq.github.io/matrix-authentication-service/reference/configuration.html#httplisteners
- name: health
binds:
- address: "[::]:8080"
database:
uri: postgresql://synapse:{{ secret "db_password" }}@{{ env "STACK_NAME" }}_db:5432/mas?sslmode=disable
matrix:
kind: synapse
homeserver: {{ or (env "SERVER_NAME") (env "DOMAIN") }}
endpoint: http://{{ env "STACK_NAME" }}_app:8008/
secret_file: /run/secrets/mas_synapse_shared
secrets:
# Plain hex in file (abra: length=64 charset=hex). See .env.sample modifiers.
encryption_file: /run/secrets/mas_encryption
keys:
- key_file: /run/secrets/mas_signing_rsa
passwords:
enabled: true
schemes:
- version: 1
algorithm: bcrypt
unicode_normalization: true
- version: 2
algorithm: argon2id
{{ if env "MAS_UPSTREAM_PROVIDER_ID" }}
# https://element-hq.github.io/matrix-authentication-service/setup/sso.html
upstream_oauth2:
providers:
- id: {{ env "MAS_UPSTREAM_PROVIDER_ID" }}
{{ if env "MAS_UPSTREAM_SYNAPSE_IDP_ID" }}synapse_idp_id: {{ env "MAS_UPSTREAM_SYNAPSE_IDP_ID" }}{{ end }}
human_name: {{ or (env "MAS_UPSTREAM_HUMAN_NAME") "SSO" }}
issuer: {{ env "MAS_UPSTREAM_ISSUER" }}
client_id: {{ env "MAS_UPSTREAM_CLIENT_ID" }}
client_secret_file: /run/secrets/mas_upstream_client_secret
token_endpoint_auth_method: client_secret_basic
scope: "openid profile email"
claims_imports:
localpart:
action: require
template: "{{ "{{ user.preferred_username }}" }}"
displayname:
action: suggest
template: "{{ "{{ user.name }}" }}"
email:
action: suggest
template: "{{ "{{ user.email }}" }}"
{{ end }}
+32 -1
View File
@@ -15,6 +15,14 @@ http {
keepalive 16;
}
{{ if eq (env "MAS_ENABLED") "1" }}
upstream mas_upstream {
zone mas_upstream 64k;
server {{ env "STACK_NAME"}}_mas:8080 resolve;
keepalive 8;
}
{{ end }}
server {
listen 80;
@@ -32,7 +40,30 @@ http {
proxy_http_version 1.1;
}
location ~* ^(\/_matrix|\/_synapse\/client) {
{{ if eq (env "MAS_ENABLED") "1" }}
# MAS on same Host as Synapse (public_base = https://$DOMAIN/): browser/OIDC paths live at repo root, not only under /_matrix/
# Router reference: element-hq/matrix-authentication-service crates/router/src/endpoints.rs
# https://element-hq.github.io/matrix-authentication-service/setup/reverse-proxy.html
location ~ ^/(complete-compat-sso/|oauth2/|\.well-known/(openid-configuration|webfinger|change-password)|authorize|login|logout|register(/|$)|account/|upstream/|consent/|link(\?|/|$)|device/|recover(/|$)|assets/|graphql(/|$)|api/) {
proxy_pass http://mas_upstream;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
client_max_body_size 50M;
}
# Matrix CS API compat (login / logout / refresh and subpaths, e.g. …/login/sso/redirect) — before generic /_matrix
location ~ ^/_matrix/client/[^/]+/(login|logout|refresh)(/.*)?$ {
proxy_pass http://mas_upstream;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
client_max_body_size 50M;
}
{{ end }}
location ~* ^(\/_matrix|\/_synapse\/client|\/_synapse\/mas) {
proxy_pass http://matrix_upstream;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto https;
+4 -1
View File
@@ -1,5 +1,8 @@
{
"m.homeserver": {
"base_url": "https://{{ env "DOMAIN" }}"
}
}{{ if eq (env "MAS_ENABLED") "1" }},
"org.matrix.msc2965.authentication": {
"issuer": "https://{{ env "DOMAIN" }}/"
}{{ end }}
}