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>
This commit is contained in:
@ -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
|
||||
|
||||
93
README.md
93
README.md
@ -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)
|
||||
|
||||
|
||||
24
compose.wellknown.yml
Normal file
24
compose.wellknown.yml
Normal 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"
|
||||
@ -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
|
||||
|
||||
Reference in New Issue
Block a user