Synapse Matrix Server with Docker
## Prerequisites
### Domains
The following guide will use
- `chaos.boutique`
- `matrix.chaos.boutique`
- Optional: `chat.example.com`
`example.com` will be part of the user name.
For instance `@alice:example.com`.
### Server
- Example: Debian 11
- [Docker (guide)](https://docs.docker.com/engine/install/)
## Docker network
```
docker network create matrix
```
## Database
```
docker run -d \
--name postgres \
--network matrix \
-e POSTGRES_PASSWORD=secret \
-e POSTGRES_INITDB_ARGS='--encoding=UTF-8 --lc-collate=C --lc-ctype=C' \
postgres
```
## Synapse
Start creating the config
```
docker run -it --rm \
--mount type=volume,src=synapse-data,dst=/data \
-e SYNAPSE_SERVER_NAME=example.com \
-e SYNAPSE_REPORT_STATS=no \
matrixdotorg/synapse:latest generate
ls /var/lib/docker/volumes/synapse-data/_data/
vi /var/lib/docker/volumes/synapse-data/_data/homeserver.yaml
```
Configure database in `homeserver.yaml`
```
database:
name: psycopg2
args:
user: postgres
password: geheim
database: postgres
host: postgres
```
Start the container
```
docker run -d --name synapse \
--mount type=volume,src=synapse-data,dst=/data \
--network matrix \
-p 8008:8008 \
matrixdotorg/synapse:latest
```
Check the logs
```
docker logs synapse
```
## Get SSL certificates
```
apt install \
certbot \
python3-certbot-nginx
certbot certonly \
--standalone \
-d matrix.example.com \
-d chat.example.com \
-d example.com
```
## NGINX
```
apt install nginx
```
https://matrix-org.github.io/synapse/latest/reverse_proxy.html
`/etc/nginx/sites-enabled/example.com`
```
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/matrix.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/matrix.example.com/privkey.pem;
set $CWK '';
set $CWK '${CWK}{';
set $CWK '${CWK} "m.homeserver": {';
set $CWK '${CWK} "base_url": "https://matrix.example.com"';
set $CWK '${CWK} }';
set $CWK '${CWK}}';
set $SWK '';
set $SWK '${SWK}{';
set $SWK '${SWK} "m.server": "matrix.example.com:443"';
set $SWK '${SWK}}';
location /.well-known/matrix/client {
return 200 "$CWK";
default_type application/json;
add_header Access-Control-Allow-Origin *;
}
location /.well-known/matrix/server {
return 200 "$SWK";
default_type application/json;
add_header Access-Control-Allow-Origin *;
}
}
```
`/etc/nginx/sites-enabled/matrix.example.com`
```
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
# For the federation port
listen 8448 ssl http2 default_server;
listen [::]:8448 ssl http2 default_server;
server_name matrix.example.com;
ssl_certificate /etc/letsencrypt/live/matrix.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/matrix.example.com/privkey.pem;
location ~ ^(/_matrix|/_synapse/client) {
# note: do not add a path (even a single /) after the port in `proxy_pass`,
# otherwise nginx will canonicalise the URI and cause signature verification
# errors.
proxy_pass http://localhost:8008;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $host;
# Nginx by default only allows file uploads up to 1M in size
# Increase client_max_body_size to match max_upload_size defined in homeserver.yaml
client_max_body_size 50M;
}
}
```
Test:
- https://matrix.example.com/_matrix/federation/v1/version
- https://example.com/.well-known/matrix/client
- https://example.com/.well-known/matrix/server
- https://federationtester.matrix.org/
### Create a user
(only required if self sign up is disabled)
```
docker exec -it synapse \
register_new_matrix_user \
http://localhost:8008 \
-c /data/homeserver.yaml
```
## Element web client
```
mkdir -p /etc/element
curl -o /etc/element/config.json https://raw.githubusercontent.com/vector-im/element-web/develop/config.sample.json
vi /etc/element/config.json
docker run -d --name element \
-v /etc/element/config.json:/app/config.json \
-p 8080:80 \
vectorim/element-web
```
### Reverse Proxy
`/etc/nginx/sites-enabled/chat.example.com`
```
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name chat.example.com;
ssl_certificate /etc/letsencrypt/live/matrix.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/matrix.example.com/privkey.pem;
location / {
proxy_pass http://localhost:8080;
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header Content-Security-Policy "frame-ancestors 'none'";
}
}
```
Test it: https://chat.example.com/
## TURN
Recommendation is not to use Docker since it has some weird issues.
Install coturn
```
apt install coturn
vi /etc/default/coturn
```
Set `TURNSERVER_ENABLED=1`
```
vi /etc/turnserver.conf
```
Example config
- Comment `use-auth-secret` in
- Set `static-auth-secret`
```
systemctl start coturn
systemctl status coturn
```
Recommended is to run non-encrypted coturn on port 80 on a dedicated IP. This works for most network configs.
Set up Synapse config
```
vi /var/lib/docker/volumes/synapse-data/_data/homeserver.yaml
```
Search for `turn_uris` .
Example
```
turn_uris:
- turn:example.com:3478?transport=udp
- turn:example.com:3478?transport=tcp
turn_shared_secret: secret
```
Restart Synapse
```
docker restart synapse
```
Test a one-to-one call with devices in different networks.
## Backup
Strategy:
- Backup can be done online without stopping Synapse
- Start database backup
- Runs inside a transaction and thus will be consistent
- After that backup `data`, server key and the config files
Restore:
- Install Synapse; do not start it yet
- Or stop Synapse and the database and replace all data with the backup
- Restore database dump
- Restore `data` directory, config and server signing key
- Start Synapse
Example script:
```
PGPASSWORD="geheim" pg_dump \
--host=postgres \
--dbname=postgres \
--username=postgres \
> /backup/db.sql
# rsync
# borg create \
# ssh:// \
# /backup /synapse
```
Call using cron or systemd timer
```
docker run --rm \
--network matrix \
--mount type=volume,src=synapse-data,dst=/data,readonly \
-v ./backup.sh:/backup.sh \
mweimann/borg-backup
/backup.sh
```