Présentation
Synapse
Synapse est un serveur domestique Matrix open-source écrit et maintenu par la Fondation Matrix.org. Le développement de Synapse et du protocole Matrix lui-même se poursuit sérieusement aujourd’hui.En bref, Matrix est un standard ouvert pour les communications sur Internet, prenant en charge la fédération, le cryptage et la VoIP. Matrix.org en dit plus sur les objectifs du projet Matrix, et la spécification formelle décrit les détails techniques.
Element
Element (anciennement connu sous le nom de Vector et Riot) est un client web Matrix construit à l’aide du kit SDK React de Matrix.
Coturn
coturn est une implémentation libre et gratuite de TURN et de STUN Server.Le serveur TURN est un serveur et une passerelle de traversée NAT pour le trafic VoIP.
- Source: https://github.com/coturn/coturn
L’association de ces 3 outils vous permet donc d’avoir à disposition un ensemble composant cette messagerie instantanée (un peu comme Discord) supportant les appels audio et vidéo.
Prérequis
Je pars, comme d’habitude, du principe que vous disposez de Docker et de Portainer, que vous souhaitez installer le tout sous Linux et que vous utilisez un reverse proxy pour exposer vos services (Caddy).
Pour simplifier cet article, je considère que vous avez déjà les services suivants qui sont pleinement opérationnels :
- Redis
- PostgreSQL
Vous aurez à créer les répertoires ci-dessous (en partant du principe que vous êtes sur /opt/docker/matrix/ comme répertoire de base) :
- conf/nginx
- datas/coturn
- datas/discord (factultatif)
- datas/synapse (factultatif)
- datas/telegram (factultatif)
- datas/whatsapp (factultatif)
Vous aurez besoin des fichiers ci-dessous :
docker-compose.yml
[Fichier]
version: "3.0"
#
# updated: 2023-04-05
# stack: matrix
#
#
# If you don's want Telegam, WhatsApp or Discord bridge, you may remove the relevant section(s)
#
# sudo docker run -it --rm \
# -v /opt/docker/standard/matrix/work:/data \
# -e SYNAPSE_SERVER_NAME=matrix.domain.com \
# -e SYNAPSE_REPORT_STATS=yes \
# matrixdotorg/synapse:latest generate
# sudo docker exec -it synapse bash
# register_new_matrix_user -c /data/homeserver.yaml http://localhost:8008
services:
element:
container_name: element
hostname: element
image: vectorim/element-web:latest
restart: always
stdin_open: true
tty: true
security_opt:
- "no-new-privileges:true"
ports:
- "7080:80"
expose:
- "80"
depends_on:
- synapse
environment:
TZ: "Europe/Paris"
volumes:
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- /opt/docker/matrix/conf/element-config.json:/app/config.json
synapse:
container_name: synapse
hostname: synapse
image: matrixdotorg/synapse:latest
restart: always
stdin_open: true
tty: true
security_opt:
- "no-new-privileges:true"
ports:
- "8008:8008"
expose:
- "8008"
depends_on:
- synapserp
- coturn
environment:
TZ: "Europe/Paris"
volumes:
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- /opt/docker/matrix/datas/synapse:/data
synapserp:
container_name: synapserp
hostname: synapserp
image: nginx:latest
restart: always
stdin_open: true
tty: true
security_opt:
- "no-new-privileges:true"
ports:
- "3080:80"
expose:
- "80"
environment:
TZ: "Europe/Paris"
volumes:
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- /opt/docker/matrix/conf/nginx:/etc/nginx/conf.d
coturn:
container_name: coturn
hostname: coturn
image: coturn/coturn:latest
restart: always
stdin_open: true
tty: true
security_opt:
- "no-new-privileges:true"
ports:
- "3478:3478"
- "5349:5349"
- "3478:3478/udp"
- "5349:5349/udp"
- "14000-15535:64000-65535/udp"
expose:
- "3478"
- "5349"
- "64000-65535"
environment:
TZ: "Europe/Paris"
volumes:
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- /opt/docker/matrix/conf/turnserver.conf:/etc/coturn/turnserver.conf
- /opt/docker/matrix/datas/coturn:/var/lib/coturn
telegram:
container_name: telegram
hostname: telegram
image: dock.mau.dev/mautrix/telegram:latest
restart: always
stdin_open: true
tty: true
security_opt:
- "no-new-privileges:true"
ports:
- "29317:29317"
expose:
- "29317"
depends_on:
- synapse
environment:
TZ: "Europe/Paris"
volumes:
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- /opt/docker/matrix/datas/telegram:/data
whatsapp:
container_name: whatsapp
hostname: whatsapp
image: dock.mau.dev/mautrix/whatsapp:latest
restart: always
stdin_open: true
tty: true
security_opt:
- "no-new-privileges:true"
ports:
- "29318:29318"
expose:
- "29318"
depends_on:
- synapse
environment:
TZ: "Europe/Paris"
volumes:
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- /opt/docker/matrix/datas/whatsapp:/data
discord:
container_name: discord
hostname: discord
image: dock.mau.dev/mautrix/discord:latest
restart: always
stdin_open: true
tty: true
security_opt:
- "no-new-privileges:true"
ports:
- "29334:29334"
expose:
- "29334"
depends_on:
- synapse
environment:
TZ: "Europe/Paris"
volumes:
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- /opt/docker/matrix/datas/discord:/data
element-config.json
[Fichier]
{
"default_server_config": {
"m.homeserver": {
"base_url": "https://matrix.domain.com",
"server_name": "matrix.domain.com"
},
"m.identity_server": {
"base_url": "https://vector.im"
}
},
"brand": "Matrix",
"integrations_ui_url": "https://scalar.vector.im/",
"integrations_rest_url": "https://scalar.vector.im/api",
"integrations_widgets_urls": [
"https://scalar.vector.im/_matrix/integrations/v1",
"https://scalar.vector.im/api",
"https://scalar-staging.vector.im/_matrix/integrations/v1",
"https://scalar-staging.vector.im/api",
"https://scalar-staging.riot.im/scalar/api"
],
"hosting_signup_link": "https://element.io/matrix-services?utm_source=element-web&utm_medium=web",
"bug_report_endpoint_url": "https://element.io/bugreports/submit",
"uisi_autorageshake_app": "element-auto-uisi",
"showLabsSettings": true,
"roomDirectory": {
"servers": [
"matrix.org",
"gitter.im",
"libera.chat"
]
},
"enable_presence_by_hs_url": {
"https://matrix.org": false,
"https://matrix-client.matrix.org": false
},
"terms_and_conditions_links": [
{
"url": "https://element.io/privacy",
"text": "Privacy Policy"
},
{
"url": "https://element.io/cookie-policy",
"text": "Cookie Policy"
}
],
"hostSignup": {
"brand": "Matrix",
"cookiePolicyUrl": "https://element.io/cookie-policy",
"domains": [
"matrix.org"
],
"privacyPolicyUrl": "https://element.io/privacy",
"termsOfServiceUrl": "https://element.io/terms-of-service",
"url": "https://ems.element.io/element-home/in-app-loader"
},
"sentry": {
"dsn": "https://[email protected]/6",
"environment": "develop"
},
"posthog": {
"projectApiKey": "phc_Jzsm6DTm6V2705zeU5dcNvQDlonOR68XvX2sh1sEOHO",
"apiHost": "https://posthog.element.io"
},
"privacy_policy_url": "https://element.io/cookie-policy",
"features": {
"feature_spotlight": true,
"feature_video_rooms": true
},
"element_call": {
"url": "https://element-call.netlify.app"
},
"map_style_url": "https://api.maptiler.com/maps/streets/style.json?key=fU3vlMsMn4Jb6dnEIFsx"
}
homeserver.yaml
[Fichier]
# Configuration file for Synapse.
#
# This is a YAML file: see [1] for a quick introduction. Note in particular
# that *indentation is important*: all the elements of a list or dictionary
# should have the same indentation.
#
# [1] https://docs.ansible.com/ansible/latest/reference_appendices/YAMLSyntax.html
#
# For more information on how to configure Synapse, including a complete accounting of
# each option, go to docs/usage/configuration/config_documentation.md or
# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html
server_name: "matrix.domain.com"
pid_file: /data/homeserver.pid
federation_rc_reject_limit: 128
listeners:
- port: 8008
tls: false
type: http
x_forwarded: true
resources:
- names: [client, federation]
compress: false
#database:
# name: sqlite3
# args:
# database: /data/homeserver.db
database:
name: psycopg2
args:
user: [removed]
password: [removed]
database: synapse
host: [removed]
cp_min: 5
cp_max: 10
log_config: "/data/matrix.domain.com.log.config"
media_store_path: /data/media_store
registration_shared_secret: "[removed]"
report_stats: true
macaroon_secret_key: "[removed]"
form_secret: "[removed]"
signing_key_path: "/data/matrix.domain.com.signing.key"
trusted_key_servers:
- server_name: "matrix.org"
enable_registration: true
registrations_require_3pid:
- email
admin_contact: 'mailto:[email protected]'
email:
smtp_host: [smtp server address]
smtp_port: [smtp port]
smtp_user: [username]
smtp_pass: [password]
force_tls: true
require_transport_security: true
enable_tls: true
notif_from: "Matrix <[email protected]>"
app_name: "Matrix"
enable_notifs: true
notif_for_new_users: false
validation_token_lifetime: 15m
invite_client_location: https://element.domain.com
subjects:
message_from_person_in_room: "[%(app)s] Vous avez un message sur %(app)s de %(person)s dans le canal %(room)s..."
message_from_person: "[%(app)s] Vous avez un message sur %(app)s de %(person)s..."
messages_from_person: "[%(app)s] Vous avez des messages sur %(app)s de %(person)s..."
messages_in_room: "[%(app)s] Vous avez des messages sur %(app)s dans le canal %(room)s..."
messages_in_room_and_others: "[%(app)s] Vous avez des messages sur %(app)s dans le canal %(room)s et d'autres..."
messages_from_person_and_others: "[%(app)s] Vous avez des messages sur %(app)s de %(person)s et d'autres..."
invite_from_person_to_room: "[%(app)s] %(person)s vous invite à rejoindre le canal %(room)s sur %(app)s..."
invite_from_person: "[%(app)s] %(person)s vous a invité à chatter sur %(app)s..."
password_reset: "[%(server_name)s] Réinitialisation du mot de passe"
email_validation: "[%(server_name)s] Validez votre email"
redis:
enabled: true
host: [ip of redis server]
room_list_publication_rules:
- user_id: "*"
alias: "*"
room_id: "*"
action: allow
turn_uris:
- "turns:turn.domain.com?transport=udp"
- "turns:turn.domain.com?transport=tcp"
- "turn:turn.domain.com?transport=udp"
- "turn:turn.domain.com?transport=tcp"
turn_shared_secret: "[a secret here !]"
turn_user_lifetime: "1h"
turn_username: [username]
turn_password: [password]
app_service_config_files:
- /data/mautrix-telegram-registration.yaml #only if you keep telegram bridge
- /data/mautrix-whatsapp-registration.yaml #only if you keep whatsapp bridge
- /data/mautrix-discord-registration.yaml #only if you keep discord bridge
# vim:ft=yaml
turnserver.conf
[Fichier]
syslog
lt-cred-mech
use-auth-secret
static-auth-secret=[password]
realm=matrix.domain.com
server-name=matrix.domain.com
cert=/etc/letsencrypt/live/turn.example.org/fullchain.pem
pkey=/etc/letsencrypt/live/turn.example.org/privkey.pem
#no-udp
external-ip=[public external ip]
min-port=14000
max-port=15535
Pour Coturn, la plage de port (en UDP) qui lui est alloué est 14000-15535.
Il vous faudra penser à les ouvrir, soit sur votre box internet, soit sur votre routeur.
conf/nginx/default.conf
[Fichier]
# 2023-04-02
server {
listen 80 default_server;
server_name matrix.domain.com;
location /_matrix {
proxy_pass http://192.168.50.102:8008;
proxy_set_header X-Forwarded-For $remote_addr;
client_max_body_size 128m;
}
location /.well-known/matrix/server {
access_log off;
add_header Access-Control-Allow-Origin *;
default_type application/json;
return 200 '{"m.server": "matrix.domain.com:443"}';
}
location /.well-known/matrix/client {
access_log off;
add_header Access-Control-Allow-Origin *;
default_type application/json;
return 200 '{"m.homeserver": {"base_url": "https://matrix.domain.com"}}';
}
location / {
return 301 /_matrix/static/;
}
}
default.conf est pour le cas ou vous utilisiez Traefik et non Caddy
Méthodologie
Tout d’abord, vous placez les fichiers requis dans les répertoires indiqués par le fichier docker-compose.
Dans le fichier element-config.json, il vous faudra mettre à jour le nom de domaine sur lequel vous souhaiter que les services soient associés. Et pour le fichier turnserver.conf, il faudra modifier a minima la partie [password] et si vous le souhaitez la plage des ports alloués. Dans le fichier homeserver.yaml il vous faut aussi mettre à jour le nom de domaine ainsi que toutes les entrées entre crochets.
Les ports des services sont renseignés à plusieurs endroits, si vous devez les modifier pensez à reporter ces changements partout.
Avant de lancer la stack entièrement, il vous faudra lancer la commande suivante afin d’initialiser la configuration de Synapse:
sudo docker run -it --rm \
-v /opt/docker/matrix/datas/synapse/:/data \
-e SYNAPSE_SERVER_NAME=matrix.domain.com \
-e SYNAPSE_REPORT_STATS=yes \
matrixdotorg/synapse:latest generate
Pensez à modifier le SYNAPSE_SERVER_NAME
Une fois la stack complète lancée, vous devez lancer un shell sur le conteneur de Synapse pour créer le premier utilisateur (qui sera donc administrateur du serveur) :
sudo docker exec -it synapse bash &&
register_new_matrix_user -c /data/homeserver.yaml http://localhost:8008
La partie propre à la configuration de Caddy est relativement simple :)
@matrix host matrix.domain.com
handle @matrix {
import common
header /.well-known/matrix/* Content-Type application/json
header /.well-known/matrix/* Access-Control-Allow-Origin *
respond /.well-known/matrix/server `{"m.server": "matrix.domain.com:443"}`
respond /.well-known/matrix/client `{"m.homeserver":{"base_url":"https://matrix.domain.com"}}`
reverse_proxy /_matrix/* [ip]:8008
reverse_proxy /_synapse/client/* [ip]:8008
}
@element host element.domain.com
handle @element {
import common
reverse_proxy [ip]:7080
}
Pour le contenu de common, je vous renvoie à mon autre article Caddy, Docker et Cloudflare.
Si vous utilisez Traefik, vous aurez à ajouter ces élements dans le config.yml :
routers
synapse:
entryPoints:
- https
rule: Host(`matrix.domain.com`)
middlewares:
- default
tls: {}
service: synapse
element:
entryPoints:
- https
rule: Host(`element.domain.com`)
middlewares:
- default
tls: {}
service: element
services
element:
loadBalancer:
servers:
- url: "http://[element's ip addres]:7080"
passHostHeader: true
synapse:
loadBalancer:
servers:
- url: "http://[synapse reverse proxy ip addres]:3080"
passHostHeader: true
Une fois tous ces préparatifs réalisés, vous pourrez lancer la stack avec Portainer.
Les ‘bridges’
Synapse permet de lui connecter différents autres services tels que Telegram, WhatsApp, Discord et bien d’autres.
Je vous renvoie vers les instructions spécifiques à chaque service que vous voulez intégrer à Synapse :
https://docs.mau.fi/bridges/general/docker-setup.html?bridge=telegram&ref=infos.zogg.fr
Dans le cadre de ce tutoriel, l’intégration des services est donnée à titre d’exemple et dépasse le cadre de la mise en place de Synapse et Element :)
Communiquez !
Quelques exemples de l’interface desktop :
Il existe bien entendu des applications iOS et Android officielles :
Conclusion
Vous avez la base technique pour l’installation, à domicile, d’un outil de communication décentralisé, collaboratif et extensible.
Je ne suis pas rentré ici dans le détail de la mise en place du serveur Redis (c’est très simple) ni du serveur de base de données PostgreSQL (c’est presque simple) car ce sera probablement traité dans d’autres articles à venir.
Quant à l’administration et la gestion du serveur, des canaux de communication ; tout cela sort du contexte lié à la simple mise en place du service :)
Extensible ?
Oui, tout à fait puisque vous pouvez y connecter différents autres canaux de communication.
En voici une brève liste :
- IRC
- Slack
- Discord
- SMS
- Skype
- Signal
- Telegram
- Mastodon
Changelog
2023-04-06
- Mise à jour de la structure des répertoires
- Ajout des bridges Telegram, WhatsApp et Discord