Compare commits

...

16 Commits

Author SHA1 Message Date
74f1adaccb Merge pull request 'Add documentation for matrix federation + traefik labels for federation via port 8448 on matrix-federation entrypoint' (#62) from compress-and-federate into main
Reviewed-on: https://git.coopcloud.tech/coop-cloud/matrix-synapse/pulls/62
Reviewed-by: 3wordchant <3wordchant@noreply.git.coopcloud.tech>
2026-06-08 18:17:34 +00:00
17a399ba25 Merge pull request 'Add compression to recipe' (#61) from compress into main
Reviewed-on: https://git.coopcloud.tech/coop-cloud/matrix-synapse/pulls/61
2026-06-08 18:17:11 +00:00
b63dde1275 Merge remote-tracking branch 'origin/main' into compress
# Conflicts:
#	homeserver.yaml.tmpl
2026-06-08 18:13:25 +00:00
f836c74386 improvements to readme 2026-06-08 14:03:16 -04:00
e257349b37 improve documentation of federation 2026-06-04 14:30:29 -04:00
5b21a6b4f9 Merge pull request 'chore: Configure Renovate' (#56) from renovate/configure into main
Reviewed-on: https://git.coopcloud.tech/coop-cloud/matrix-synapse/pulls/56
2026-05-28 17:11:13 +00:00
b730cadb06 docs: document the three federation setup options 2026-05-25 13:05:11 -04:00
59ad89cfb4 add traefik labels for matrix-federation entrypoint
Adds a second Traefik router on the web (nginx) service that listens on
the `matrix-federation` entrypoint (host port 8448 via the traefik
recipe's compose.matrix.yml) and uses Host(${SERVER_NAME}).

Lets remote homeservers reach this server's federation/key endpoints via
the standard `<server_name>:8448` fallback when no .well-known or SRV
delegation exists for SERVER_NAME — useful when SERVER_NAME differs from
DOMAIN and no external service serves /.well-known/matrix/server.

Requires MATRIX_FEDERATION_ENABLED=1 on the traefik stack.
2026-05-25 15:52:16 +00:00
f66bfef727 working on configurable room complexity limits 2026-04-30 15:06:54 -04:00
a809333dcb comments 2026-04-29 15:18:13 -04:00
b39c60d594 add run_compressor command 2026-04-29 15:01:50 -04:00
4830b0596c adding many abra commands 2026-04-29 14:47:51 -04:00
43d68aefb4 use vacuum full 2026-04-29 13:44:55 -04:00
91efd92d31 add abra command for vacuum full 2026-04-29 13:40:41 -04:00
3fab725957 Add optional compose for rust-synapse-compress-state 2026-04-29 13:14:49 -04:00
a5a3a1938d Add renovate.json 2026-03-10 19:22:42 +00:00
9 changed files with 431 additions and 4 deletions

View File

@ -99,9 +99,15 @@ ENABLE_REGISTRATION=false
#DISABLE_FEDERATION=1
# SERVE_SERVER_WELLKNOWN only works if SERVER_NAME and DOMAIN are the same
# if they are different, then a different federation method is needed (like compose.wellknown.yml)
# Set "true" to enable federation endpoint on $DOMAIN/.well-known/matrix/server
SERVE_SERVER_WELLKNOWN=false
# Serve /.well-known/matrix/{server,client} on SERVER_NAME via Traefik.
# Can be used when SERVER_NAME != DOMAIN and SERVER_NAME is served by Traefik.
#COMPOSE_FILE="$COMPOSE_FILE:compose.wellknown.yml"
ALLOW_PUBLIC_ROOMS_FEDERATION=false
## Room auto-join
@ -144,6 +150,10 @@ ENCRYPTED_BY_DEFAULT=all
#TRACK_PUPPETED_USER_IPS=true
## Room complexity limit (prevents joining large remote rooms that cause DB bloat)
## complexity ≈ state_events / 500. Default 100.0 blocks rooms with >50000 state events.
#ROOM_COMPLEXITY_LIMIT=100.0
## Retention
ALLOWED_LIFETIME_MAX=4w
@ -239,6 +249,14 @@ RETENTION_MAX_LIFETIME=4w
#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

View File

@ -39,11 +39,100 @@
### Enabling federation
See [`#27`](https://git.coopcloud.tech/coop-cloud/matrix-synapse/pulls/27) for more. Depending on your setup, using `SERVE_SERVER_WELLKNOWN=true` might work to start federating. Make sure you don't leave `DISABLE_FEDERATION=1` set!
Federation is on by default (`DISABLE_FEDERATION=0`). Remote homeservers need a way to discover the host:port that serves your `SERVER_NAME`.
There are three supported approaches. At least one needs to be working for federation to work (and matrix will fallback between them).
#### Option 1: built-in well-known (`SERVER_NAME` = `DOMAIN`)
Set `SERVE_SERVER_WELLKNOWN=true` and leave `SERVER_NAME` unset (defaults to `DOMAIN`). The recipe's nginx serves `/.well-known/matrix/server` and `/.well-known/matrix/client` on `DOMAIN`.
Suitable when users are e.g. `@alice:matrix.example.com`.
#### Option 2: external well-known on `SERVER_NAME`
Use when you want users to be e.g. `@alice:example.com` while Synapse runs at `matrix.example.com` (and SERVER_NAME is served by the same machine that Synapse is running on). Set:
```
SERVER_NAME=example.com
DOMAIN=matrix.example.com
SERVE_SERVER_WELLKNOWN=false
```
The two paths that must be served on `SERVER_NAME` are:
- `https://example.com/.well-known/matrix/server``{"m.server": "matrix.example.com:443"}`
- `https://example.com/.well-known/matrix/client``{"m.homeserver": {"base_url": "https://matrix.example.com"}}`
**Recommended — let this recipe serve them via Traefik** by enabling `compose.wellknown.yml`:
```
COMPOSE_FILE="$COMPOSE_FILE:compose.wellknown.yml"
```
This publishes a Traefik router `Host(${SERVER_NAME}) && PathPrefix(/.well-known/matrix)`
pointing at the matrix nginx, which already serves both files. The path-scoped, high-priority
rule coexists with any apex website that also serves `Host(${SERVER_NAME})` — that site keeps
serving everything except `/.well-known/matrix`. `SERVER_NAME` must resolve to this Traefik so
ACME can issue its certificate.
**Alternative** — serve the two files yourself from whatever already hosts `example.com`.
#### Option 3: Traefik `matrix-federation` entrypoint (port 8448)
Use when `SERVER_NAME``DOMAIN` but you have no separate web service at `SERVER_NAME`. Remote homeservers fall back to `SERVER_NAME:8448` when there's no delegation (also requires SERVER_NAME pointing to same server that matrix is running on).
Requirements:
- [traefik](https://git.coopcloud.tech/coop-cloud/traefik) `>= 5.1.2+v3.6.15` with `MATRIX_FEDERATION_ENABLED=1` and `compose.matrix.yml` enabled.
- `SERVER_NAME` set in your matrix-synapse env (used by the federation router's Host rule).
With these in place, the recipe publishes a Traefik router on `Host(${SERVER_NAME})` via the `matrix-federation` entrypoint, reusing the existing matrix nginx → synapse path.
#### Option 4: DNS SRV records (usually not viable here)
For reasons explained below, I might be confused, but I think SRV records usually don't help with co-op cloud matrix deployments.
You should probably prefer Option 2 (well known), but the possibility of SRV is explained below:
Federation can also be delegated with a DNS `SRV` record on `SERVER_NAME` instead of well-known:
```
_matrix-fed._tcp.example.com. 3600 IN SRV 10 0 8448 matrix.example.com. # modern
_matrix._tcp.example.com. 3600 IN SRV 10 0 8448 matrix.example.com. # deprecated, for older peers
```
The catch is TLS: on the SRV path a remote validates the certificate against **`SERVER_NAME`**, *not* the SRV target. This recipe's Traefik only issues a cert for **`DOMAIN`**, so:
- **SRV → `DOMAIN`:443 fails** — the presented cert is for `DOMAIN`, but the peer requires one for `SERVER_NAME`.
- **SRV → `SERVER_NAME`:443 collides** — Traefik routes TLS by SNI, and `Host(SERVER_NAME)` on `:443` is already owned by whatever apex site serves `SERVER_NAME`.
- **SRV → `SERVER_NAME`:8448 works** — the Option 3 `matrix-federation` router holds a cert for `SERVER_NAME` — but that's just Option 3 made explicit (the `:8448` fallback already works with no SRV record).
#### Verifying
The canonical test:
- https://federationtester.matrix.org/#YOUR_SERVER_NAME
Or check the underlying paths directly. They should all return JSON:
```bash
# Options 1 & 2 — delegation
curl https://SERVER_NAME/.well-known/matrix/server
# Option 3 — federation endpoint via 8448
curl https://SERVER_NAME:8448/_matrix/key/v2/server
# Confirms Synapse itself is healthy (independent of the path remote servers use)
curl https://DOMAIN/_matrix/key/v2/server
```
### Getting client discovery on a custom domain
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.
Enable `compose.wellknown.yml` (see Option 2 above) — it serves `/.well-known/matrix/client`
on `SERVER_NAME` too, so clients signing in as `@alice:example.com` auto-discover the homeserver.
### Matrix Authentication Service (MAS)

209
abra.sh
View File

@ -1,6 +1,6 @@
export DISCORD_BRIDGE_YAML_VERSION=v2
export ENTRYPOINT_CONF_VERSION=v3
export HOMESERVER_YAML_VERSION=v36
export HOMESERVER_YAML_VERSION=v37
export LOG_CONFIG_VERSION=v2
export SHARED_SECRET_AUTH_VERSION=v2
export SIGNAL_BRIDGE_YAML_VERSION=v6
@ -11,6 +11,213 @@ export WK_CLIENT_VERSION=v2
export MAS_CONFIG_VERSION=v2
export PG_BACKUP_VERSION=v2
export ADMIN_CONFIG_VERSION=v1
export COMPRESS_STATE_ENTRYPOINT_VERSION=v5
###############################################################################
# Database maintenance — shrink a bloated Synapse database
#
# See https://levans.fr/shrink-synapse-database.html
#
# Recommended steps to reclaim disk space:
# 1. abra app cmd <domain> compress-state run_compressor 500 10000
# (compress redundant state — safe while Synapse is running)
# 2. abra app cmd <domain> db reindex
# (rebuild indexes — stop Synapse first)
# 3. abra app cmd <domain> db vacuum_full
# (rewrite tables and reclaim disk — stop Synapse first)
#
# Diagnostic commands (safe to run anytime):
# abra app cmd <domain> db db_size
# abra app cmd <domain> db state_bloat
# abra app cmd <domain> db empty_rooms
#
# Purge commands (require an admin token):
# abra app cmd <domain> app register_admin <user> <pass>
# abra app cmd <domain> app get_token <user> <pass>
# abra app cmd <domain> app purge_remote_media <days> <token>
# abra app cmd <domain> app purge_empty_rooms <token>
# abra app cmd <domain> app purge_room <room_id> <token>
# abra app cmd <domain> app purge_history <room_id> <days> <token>
###############################################################################
# --- Diagnostics (db) ---
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;"
}
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;"
}
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'
);"
}
# --- Compression (compress-state) ---
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"
}
# --- Maintenance (db) — stop Synapse before running these ---
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;"
}
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 (app) — require an admin access token ---
register_admin() {
USER="${1}"
PASS="${2}"
if [ -z "$USER" ] || [ -z "$PASS" ]; then
echo "Usage: register_admin <username> <password>"
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."
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 ""
}
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 ""
}
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 ""
}
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."
}
###############################################################################
# Other commands
###############################################################################
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

View File

@ -0,0 +1,31 @@
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

24
compose.wellknown.yml Normal file
View File

@ -0,0 +1,24 @@
---
version: "3.8"
# Serve /.well-known/matrix/{server,client} on SERVER_NAME via Traefik, routed to
# the matrix nginx (`web`) — so server/client delegation works without hand-placing
# files on whatever else hosts SERVER_NAME.
#
# Enable when SERVER_NAME != DOMAIN (users are @alice:example.com, Synapse runs at
# matrix.example.com). The PathPrefix rule is more specific than a bare Host()
# router, and the explicit high priority guarantees it wins over any apex website
# that also serves Host(SERVER_NAME) — so the two coexist, the apex site keeps
# serving everything except /.well-known/matrix.
#
# Requires SERVER_NAME to resolve to this Traefik so ACME can issue its cert.
services:
web:
deploy:
labels:
- "traefik.http.routers.${STACK_NAME}-wellknown.rule=Host(`${SERVER_NAME}`) && PathPrefix(`/.well-known/matrix`)"
- "traefik.http.routers.${STACK_NAME}-wellknown.entrypoints=web-secure"
- "traefik.http.routers.${STACK_NAME}-wellknown.tls=true"
- "traefik.http.routers.${STACK_NAME}-wellknown.tls.certresolver=${LETS_ENCRYPT_ENV}"
- "traefik.http.routers.${STACK_NAME}-wellknown.service=${STACK_NAME}"
- "traefik.http.routers.${STACK_NAME}-wellknown.priority=1000"

View File

@ -30,6 +30,11 @@ services:
- "traefik.http.routers.${STACK_NAME}.rule=Host(`${DOMAIN}`)"
- "traefik.http.routers.${STACK_NAME}.entrypoints=web-secure"
- "traefik.http.routers.${STACK_NAME}.tls.certresolver=${LETS_ENCRYPT_ENV}"
- "traefik.http.routers.${STACK_NAME}-federation.rule=Host(`${SERVER_NAME}`)"
- "traefik.http.routers.${STACK_NAME}-federation.entrypoints=matrix-federation"
- "traefik.http.routers.${STACK_NAME}-federation.tls=true"
- "traefik.http.routers.${STACK_NAME}-federation.tls.certresolver=${LETS_ENCRYPT_ENV}"
- "traefik.http.routers.${STACK_NAME}-federation.service=${STACK_NAME}"
healthcheck:
test: curl -f http://${STACK_NAME}_app:8008/health || exit 1
interval: 30s
@ -92,6 +97,7 @@ services:
- LOGIN_LIMIT_IP_BURST=${LOGIN_LIMIT_IP_BURST:-5}
- LOGIN_LIMIT_ACCOUNT_PER_SECOND=${LOGIN_LIMIT_ACCOUNT_PER_SECOND:-0.003}
- LOGIN_LIMIT_ACCOUNT_BURST=${LOGIN_LIMIT_ACCOUNT_BURST:-5}
- ROOM_COMPLEXITY_LIMIT=${ROOM_COMPLEXITY_LIMIT:-100.0}
- WEB_CLIENT_LOCATION
networks:
- internal

View File

@ -0,0 +1,46 @@
#!/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

View File

@ -79,7 +79,7 @@ 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
complexity: {{ env "ROOM_COMPLEXITY_LIMIT" }}
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#max_avatar_size
max_avatar_size: 10M

6
renovate.json Normal file
View File

@ -0,0 +1,6 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:recommended"
]
}