Docker compose managed Synapse home server with Postgres and Riot.
- Synapse and Coturn: avhost/docker-matrix
- Postgres: postgres
- Element: vectorim/element-web
- Volume provisioner: hasnat/volumes-provisioner
- Docker
- docker-compose
- A reverse proxy
- Python 3 (for admin scripts)
You will need to have a reverse proxy setup. I use a variant of jwilder/nginx-proxy.
Assuming you have some base domain, domain.com, and you want the matrix client to use matrix.domain.com and Element to be at element.domain.com, you will need the following from your reverse proxy:
- Listen on 443 for matrix.domain.com and forward to the Synapse container (name: matrix-synapse) at port 8008
- Listen on 8448 for domain.com and forward to the Synapse container (name: matrix-synapse) at port 8008
- Listen on 443 for element.domain.com and forward to the Riot container (name: matrix-element) at port 80
See docs/reverse_proxy for Synapse docs on reverse proxying.
- Configure env files
- Copy
samples/envto.envand set desired values - Copy
samples/{postgres|synapse|element}.envfiles to top level directory and set desired values
- Copy
- Configure postgres synapse user
- Copy
samples/init.sqltoconfig/init.sql - Add postrgres synapse user password in
config/init.sql
- Copy
- Configure Riot
- Copy
samples/config.jsontoconfig/config.json - Change desired settings
- Copy
- Run
setup/generate.sh - Configure Synapse
- Copy
config/generated/homeserver.yamltoconfig/homeserver.yaml - Configure
databasesection - Make other desired changes (see sample)
- Copy
- Configure Coturn - DEPRECATED
- Copy
config/generated/turnserver.conftoconfig/turnserver.conf - Add
min-port=49152andmax-port=49300or desired range - Be sure to update the port ranges in
docker-compose.ymlif you change these values - Make other desired changes to
config/turnserver.conf
- Copy
Coturn is deprecated in the avhost/docker-matrix image. So, I added a coturn as a separate container in this compose file. The idea is to use the same settings file and move needed ports to this container.
This docker compose has containers to support Element Call. But, it seems Element Call is still under development and how to setup may change. To get propery support there are several details you must get correct. This is a general overview of the steps. See the links below about Element Call for better information.
- Enable Synapse experimental features and settings:
experimental_features:
# MSC3266: Room summary API. Used for knocking over federation
msc3266_enabled: true
# MSC4222 needed for syncv2 state_after. This allow clients to
# correctly track the state of the room.
msc4222_enabled: true
# The maximum allowed duration by which sent events can be delayed, as
# per MSC4140.
max_event_delay_duration: 24h
rc_message:
# This needs to match at least e2ee key sharing frequency plus a bit of headroom
# Note key sharing events are bursty
per_second: 0.5
burst_count: 30
rc_delayed_event_mgmt:
# This needs to match at least the heart-beat frequency plus a bit of headroom
# Currently the heart-beat is every 5 seconds which translates into a rate of 0.2s
per_second: 1
burst_count: 20
- Reverse proxy livekit jwt and sfu. This can be done with path based routing (like described in the self-hosting docs) or separate sub-domains.
- Respond to .well-known on your base domain to indicate that you support element call:
"org.matrix.msc4143.rtc_foci": [
{
"type": "livekit",
"livekit_service_url": "https://matrix-rtc.example.com/livekit/jwt"
}
]
- There may be other settings required in this .well-known, see self-hosting docs.
- Create livekit configuration in
config/livekit.conf, with something like:
port: 7880 # Port LiveKit listens on internally
bind_addresses:
- "0.0.0.0" # Listen on all interfaces within the container
rtc:
tcp_port: 7881
port_range_start: 50100 # Match docker-compose port range
port_range_end: 50200 # Match docker-compose port range
use_external_ip: false # Rely on reverse proxy/NAT
# if you want to use coturn instead of the built in turn server:
turn_servers:
- host: turnserver.mydomain.com
port: 3478
protocol: tcp
secret: ""
- host: turnserver.mydomain.com
port: 3478
protocol: udp
secret: ""
logging:
level: info
# Disable LiveKit's internal TURN server - using coturn instead
turn:
enabled: false
- Create
livekit.envwith LIVEKIT_KEYS:
LIVEKIT_KEYS="livekit: somesecret"
- Create
livekit-jwt.envwith these settings:
# Publicly accessible URL for the LiveKit SFU WebSocket endpoint (updated domain)
LIVEKIT_URL=wss://matrixrtc.server.tld/livekit/sfu
# API Key and Secret (must match LiveKit service and secrets)
LIVEKIT_KEY=livekit
LIVEKIT_SECRET=somesecret
# Optional: Restrict call creation to users from specific homeservers
LIVEKIT_FULL_ACCESS_HOMESERVERS=server.tld
- Run
setup/init.sh - Run
docker-compose up -d
- Register your user
- Make user an admin:
docker-compose exec postgres bashpsql -U postgress\c synapseUPDATE users SET admin = 1 WHERE name = '@foo:bar.com'
The following are the settings I have changed from the generated homeserver config.
public_baseurl: https://matrix.domain.com/- Keys under
Listenersand valueport: 8008:bind_addresses: ['0.0.0.0']
admin_contact: 'mailto:email@email.email'- Keys under
database:name: psycopg2- Keys under
args:user: synapsepassword: "changethisbadpassword"database: synapsehost: postgrescp_min: 5cp_max: 10
enable_registration: true- This enables registration from your Riot client; set to
falseif you want to disable.
- This enables registration from your Riot client; set to
- Values under
registrations_require_3pid:- email
disable_msisdn_registration: trueenable_3pid_lookup: true- Keys under
email:smtp_host: smtp.gmail.comsmtp_port: 587smtp_user: "email@gmail.com"smtp_pass: "gmailpassword"require_transport_security: truenotif_from: "%(app)s Homeserver <email@gmail.com>"app_name: "whatever"enable_notifs: trueclient_base_url: "https://element.domain.com"
- Keys under
push:include_content: true
- Keys under
server_notices:system_mxid_localpart: noticessystem_mxid_display_name: "Server Notices"room_name: "Server Notices"
adm/synapseadm provides a convient command line wrapper around curling the Synapse admin API. This is written with Python 3.
Run adm/synapseadm --help to see available commands.
See docs/admin_api for additional Synapse admin API.
- Synapse docs: synapse
- Generating
homeserver.yaml: synapse/docker - Postgres settings: docs/postgres
- Federation
- Email settings: synapse/install
- Reverse proxy: docs/reverse_proxy
- TURN
- Synapse Admin API: docs/admin_api
- Matrix FAQ
- Matrix API
- Element docs: element
- Configuration: docs/config
- Key backup:
- Self-hosting: self-hosting
- Blog walkthrough: deploy-element-call
- WebRTC explainer: WebRTC TURN
- Used for inspiration