Matrix et les ponts de messagerie
Activer le serveur Matrix (Synapse), son client web Element et les ponts mautrix (WhatsApp, Signal, Telegram, Messenger, Discord). Pour l’architecture, voir Matrix dans DNF.
Activer Matrix
Section intitulée « Activer Matrix »-
Déclarer les services sur l’hôte cible dans
etc/config.yaml:etc/config.yaml services:matrix:title: "Matrix"description: "Messagerie instantanée"element: # client webturn: # relais audio/vidéo des clients historiques -
Déclarer l’administrateur Matrix (clé globale, hors hôtes) :
etc/config.yaml matrix:admin: "alice" # local part du compte administrateurCe compte administre les ponts et reçoit les alertes de supervision.
-
Créer les secrets requis (voir tableau ci-dessous), puis déployer.
L’authentification passe par le SSO Kanidm (OIDC) : tout utilisateur déclaré se connecte avec son compte réseau, aucune création de compte Matrix n’est nécessaire.
Secrets requis
Section intitulée « Secrets requis »À renseigner dans usr/secrets/secrets.yaml :
| Clé sops | Rôle | Génération |
|---|---|---|
matrix-rss-password | Registration shared secret Synapse | openssl rand -hex 32 |
oidc-secret-matrix | Secret du client OIDC Kanidm | cf. SSO |
turn-secret | Secret partagé coturn (si turn activé) | openssl rand -hex 32 |
livekit-secret | Secret partagé MatrixRTC (si matrixRtc activé) | just passwd-livekit |
mautrix-doublepuppet-as-token | Token appservice double puppeting (commun aux ponts) | openssl rand -hex 32 |
mautrix-doublepuppet-hs-token | Idem, requis par Synapse, jamais utilisé | openssl rand -hex 32 |
Deux modes d’authentification
Section intitulée « Deux modes d’authentification »Le serveur fonctionne dans un seul de ces deux modes, réglé par
darkone.service.matrix.mas.enable. Le mode choisi change les clients
compatibles, la façon d’inscrire des amis et les outils d’administration.
| Synapse historique (défaut) | MAS activé (recommandé) | |
|---|---|---|
| Option | mas.enable = false | mas.enable = true |
| Connexion SSO | Synapse est client OIDC de Kanidm | MAS est client OIDC de Kanidm |
| Element Web / Desktop | oui | oui |
| Element X (Android, iOS) | non | oui |
| Connexion par QR code | non | oui |
| Application proposée sur mobile | Element Classic | Element X |
| Portail de compte | aucun | https://matrix.domain.tld/account/ |
| Jetons d’inscription | API admin Synapse | dnf-mas sur l’hôte |
| Promotion administrateur | SQL dans la base Synapse | dnf-mas manage promote-admin |
Activer MAS
Section intitulée « Activer MAS »Le Matrix Authentication Service 🡕 remplace l’authentification interne de Synapse. Pour ce qu’il change et comment il s’insère, voir l’architecture.
-
Générer les trois secrets dédiés (idempotent, n’écrase jamais l’existant) :
Fenêtre de terminal just passwd-masClé sops Rôle mas-encryption-secretChiffrement interne MAS mas-synapse-secretSecret partagé MAS ↔ Synapse mas-rsa-private-keyClé de signature des tokens -
Activer l’option dans la config nix de l’hôte :
# usr/machines/<host>/default.nixdarkone.service.matrix.mas.enable = true; -
Déployer. Sur un serveur neuf, c’est terminé. Sur un serveur qui a déjà des comptes, enchaîner sur la migration sans laisser personne se connecter entre les deux.
Migrer un serveur déjà en production
Section intitulée « Migrer un serveur déjà en production »MAS devient propriétaire des comptes et des sessions : ils doivent être
importés avec l’outil officiel syn2mas, servi par la commande dnf-mas de
l’hôte. Sans cet import, tous les comptes sont invisibles et tout le monde est
déconnecté.
-
Sauvegarder, dans cet ordre (le dump doit entrer dans l’instantané) :
Fenêtre de terminal sudo systemctl start postgresqlBackup.servicesudo systemctl start restic-backups-system-main.service -
Déployer la configuration avec
mas.enable = true(cf. ci-dessus). La fenêtre de maintenance commence ici. -
Arrêter les deux services :
syn2masexige Synapse hors ligne, et MAS ne doit pas provisionner de compte entre-temps.Fenêtre de terminal sudo systemctl stop matrix-synapse matrix-authentication-service -
Vérifier, puis répéter à blanc, puis migrer :
Fenêtre de terminal sudo dnf-mas syn2mas checksudo dnf-mas syn2mas migrate --dry-runsudo dnf-mas syn2mas migrateLe compte-rendu annonce les comptes, liens SSO, jetons d’accès et devices repris. Les centaines d’utilisateurs « ignorés » sont les fantômes des ponts : c’est normal.
-
Redémarrer, MAS d’abord :
Fenêtre de terminal sudo systemctl start matrix-authentication-servicesudo systemctl start matrix-synapse
Inscrire des amis
Section intitulée « Inscrire des amis »En plus des utilisateurs du SSO, on peut ouvrir une inscription sur jeton pour des comptes locaux à mot de passe (les amis). Sans jeton, aucune inscription n’est possible. Le commutateur est le même dans les deux modes, seule la fabrication du jeton diffère.
# usr/machines/<host>/default.nixdarkone.service.matrix.friendRegistration.enable = true;-
Créer un jeton sur l’hôte Matrix. Ici valable une fois et 7 jours (sans option, le jeton est à usage unique et sans expiration) :
Fenêtre de terminal sudo dnf-mas manage issue-user-registration-token --usage-limit 1 --expires-in 604800La réponse affiche le jeton, par exemple
Created user registration token: 9SwPTGIFGQPa. Le transmettre à l’ami. -
L’ami ouvre
https://matrix.domain.tld/registeret choisit la création par mot de passe. -
Il saisit son identifiant et son mot de passe, puis le jeton, réclamé à l’étape suivante.
-
Il se connecte ensuite avec ce couple identifiant / mot de passe depuis n’importe quel client, Element X compris.
-
Promouvoir le compte
matrix.adminen server admin (une seule fois), sur l’hôte Matrix :Fenêtre de terminal sudo -u matrix-synapse psql matrix-synapse \-c "UPDATE users SET admin = 1 WHERE name = '@alice:domain.tld';" -
Récupérer un access token du compte promu : dans Element, Paramètres → Aide & à propos → Avancé.
-
Créer un jeton d’inscription via l’API d’administration :
Fenêtre de terminal curl -X POST \-A "Mozilla/5.0" \-H "Authorization: Bearer <ACCESS_TOKEN>" \-H "Content-Type: application/json" \-d '{"uses_allowed": 1, "expiry_time": null}' \https://matrix.domain.tld/_synapse/admin/v1/registration_tokens/newLa réponse contient le
tokenà transmettre à l’ami. -
L’ami s’inscrit dans Element : Créer un compte → serveur
domain.tld→ il colle le jeton lorsqu’il est demandé.
Collision d’identifiant avec un utilisateur déclaré
Section intitulée « Collision d’identifiant avec un utilisateur déclaré »Amis et utilisateurs SSO partagent un seul espace de noms :
@bob:domain.tld n’appartient qu’à un compte, quelle que soit son origine. Et
un identifiant Matrix est définitif — la table users de MAS impose son
unicité, et désactiver un compte ne libère pas son identifiant. On ne renomme
pas, on ne recycle pas.
Le cas typique : un ami s’inscrit comme bob, puis bob est déclaré plus
tard comme utilisateur DNF dans etc/config.yaml. Sa première connexion SSO
s’arrête alors sur une page d’erreur User exists :
Upstream account provider returned "bob" as username, which is not linked tothat upstream account. Your homeserver does not allow linking an upstreamaccount to an existing accountVérifier avant de déclarer un utilisateur, sur l’hôte Matrix :
sudo -u postgres psql matrix-authentication-service \ -c "SELECT username FROM users WHERE lower(username) = lower('bob');"Deux issues, selon ce qu’on veut garder :
Rattache l’identité Kanidm au compte ami existant, qui conserve tout : salons, historique, clés de chiffrement, ponts. C’est presque toujours ce qu’on veut, et l’intéressé le fait lui-même.
-
Déclarer d’abord
bobdansetc/config.yamlet déployer, pour qu’il ait des identifiants Kanidm. -
Bob se connecte sur
https://matrix.domain.tld/account/avec son mot de passe d’ami. -
Dans le même navigateur, il ouvre le lien de rattachement du fournisseur IDM :
https://matrix.domain.tld/upstream/authorize/01JDNF0000000000000KAN1DM0 -
Il s’identifie sur Kanidm ; MAS propose alors « Lier à votre compte existant », qu’il valide.
Bob se connecte ensuite par le SSO comme n’importe quel utilisateur déclaré. Son mot de passe d’ami reste valable : le supprimer se fait depuis le portail de compte.
Si le compte ami n’a rien à sauver, il reste plus simple de déclarer
l’utilisateur DNF sous un autre login : l’identifiant bob est perdu
pour de bon, désactiver le compte ami ne le rendra pas disponible.
Verrouiller l’ancien compte pour éviter la confusion :
sudo dnf-mas manage lock-user bobGérer les ponts
Section intitulée « Gérer les ponts »Les ponts WhatsApp, Signal, Telegram et Messenger sont activés par défaut avec Matrix ; Discord est désactivé par défaut. Réglage par hôte dans la configuration nix de la machine :
# usr/machines/<host>/default.nixdarkone.service.matrix.bridges = { discord.enable = true; # opt-in messenger.enable = false; # désactiver un pont par défaut};Chaque pont a ses secrets propres :
| Pont | Clés sops | Remarque |
|---|---|---|
mautrix-whatsapp-as-token, mautrix-whatsapp-hs-token, mautrix-whatsapp-encryption-pickle-key | openssl rand -hex 32 chacun | |
| Signal | mautrix-signal-as-token, mautrix-signal-hs-token, mautrix-signal-encryption-pickle-key | openssl rand -hex 32 chacun |
| Messenger | mautrix-meta-as-token, mautrix-meta-hs-token, mautrix-meta-encryption-pickle-key | openssl rand -hex 32 chacun |
| Telegram | mautrix-telegram-api-id, mautrix-telegram-api-hash, mautrix-telegram-as-token, mautrix-telegram-hs-token | API id/hash à créer sur my.telegram.org 🡕 |
| Discord | mautrix-discord-as-token, mautrix-discord-hs-token | openssl rand -hex 32 chacun |
Les tokens as/hs rendent la registration appservice de chaque pont
déterministe (voir
les tokens d’appservice).
Permissions
Section intitulée « Permissions »Rien à gérer : tout compte local (@*:domain.tld) peut utiliser chaque
pont avec son propre compte distant, sans interférence entre
utilisateurs. Le compte matrix.admin dispose des commandes
d’administration des bots (help en conversation directe avec le bot pour
la liste).
Double puppeting
Section intitulée « Double puppeting »Les ponts partagent un appservice doublepuppet (token
mautrix-doublepuppet-as-token) : les messages envoyés depuis le
téléphone apparaissent dans Matrix comme venant du vrai compte de
l’utilisateur. C’est automatique pour tous les comptes locaux, aucune action
par utilisateur.
Appels audio et vidéo
Section intitulée « Appels audio et vidéo »Deux piles cohabitent, parce qu’aucune ne couvre tous les clients. Elles s’activent séparément et ne se remplacent pas :
| WebRTC historique | MatrixRTC | |
|---|---|---|
| Option | darkone.service.turn.enable | darkone.service.matrix.matrixRtc.enable |
| Composants | coturn | LiveKit (SFU) + service d’autorisation |
| Appels à deux | oui | oui |
| Appels de groupe | non | oui |
| Element Classic (Android) | oui | non |
| Element Web / Desktop | oui | oui |
| Element X (Android, iOS) | non | oui |
Garder les deux activées : Element Classic ne parle que la première, Element X que la seconde.
-
Activer la pile MatrixRTC dans la config nix de l’hôte :
# usr/machines/<host>/default.nixdarkone.service.matrix = {mas.enable = true; # requis par Element X pour se connectermatrixRtc.enable = true; # requis par Element X pour appeler}; -
Générer le secret partagé, puis déployer :
Fenêtre de terminal just passwd-livekitjust apply <host> switch -
Vérifier que le serveur annonce bien un transport :
Fenêtre de terminal # doit contenir "org.matrix.msc4143.rtc_foci"curl -A Mozilla/5.0 https://domain.tld/.well-known/matrix/client# org.matrix.msc4143 doit valoir truecurl -A Mozilla/5.0 https://matrix.domain.tld/_matrix/client/versions
Aucun sous-domaine ni certificat supplémentaire : le SFU et son service
d’autorisation sont servis sur le vhost Matrix, sous /livekit/sfu et
/livekit/jwt. Côté client, rien à régler non plus — Element X et Element
Web embarquent Element Call et découvrent le transport tout seuls.
Ports média
Section intitulée « Ports média »Le média ne passe pas par le proxy inverse : les clients joignent l’hôte directement. Ces ports doivent donc être ouverts jusqu’à lui, et redirigés s’il est derrière un NAT :
| Port | Usage |
|---|---|
| 40000-40100/udp | Média WebRTC, un port par participant |
| 7881/tcp | Repli pour les réseaux qui bloquent l’UDP |
Ouvrir le réseau à la fédération
Section intitulée « Ouvrir le réseau à la fédération »Par défaut, le serveur fédère avec tous les serveurs Matrix, tout en restant
invisible dans les recherches (annuaires non exposés). Pour contrôler la
portée, régler darkone.service.matrix.federation dans la config nix de
l’hôte :
# usr/machines/<host>/default.nixdarkone.service.matrix.federation = { enable = true; # false = fédération totalement bloquée whitelist = [ ]; # vide = ouverte ; sinon liste blanche};| Objectif | Réglage |
|---|---|
| Réseau isolé (aucune fédération) | enable = false; |
| Ouvert à tout l’écosystème Matrix | enable = true; whitelist = [ ]; |
| Restreint à des serveurs de confiance | enable = true; whitelist = [ "ami.org" "matrix.org" ]; |
Vérifier après déploiement :
-
Tester la fédération entrante avec federationtester.matrix.org 🡕 sur
domain.tld→ tous les voyants verts. -
En liste blanche, un serveur non listé est refusé (journal Synapse :
Federation denied), un domaine listé fonctionne.
Salons publics avec validation (knock)
Section intitulée « Salons publics avec validation (knock) »Un salon public au sens Matrix se rejoint librement : pas de validation. Pour un salon « joignable mais sur approbation », utiliser la règle d’accès knock (toquer) — réglage par salon, côté client, sans configuration serveur.
-
Dans Element : salon → Paramètres du salon → Sécurité & confidentialité.
-
Accès au salon → « Demander à rejoindre » (knock).
-
Un utilisateur (local ou distant fédéré) demande l’accès ; un modérateur approuve ou refuse.
Exploitation
Section intitulée « Exploitation »| Action | Commande |
|---|---|
| État des services | systemctl status matrix-synapse mautrix-whatsapp mautrix-signal mautrix-telegram mautrix-meta-messenger |
| Journaux d’un pont | journalctl -u mautrix-whatsapp -f |
| Journaux Synapse | journalctl -u matrix-synapse -f |
| Journaux MAS | journalctl -u matrix-authentication-service -f |
| Journaux MatrixRTC | journalctl -u livekit -u lk-jwt-service -f |
Administrer les comptes avec MAS
Section intitulée « Administrer les comptes avec MAS »dnf-mas enveloppe l’outil officiel mas-cli sur l’hôte Matrix : il
reconstitue la configuration et les secrets du service, et fonctionne donc
service arrêté comme démarré. Toujours en sudo.
| Action | Commande |
|---|---|
| Créer un jeton d’inscription | sudo dnf-mas manage issue-user-registration-token |
| Promouvoir un administrateur | sudo dnf-mas manage promote-admin alice |
| Lister les administrateurs | sudo dnf-mas manage list-admin-users |
| Créer un compte (bot, service) | sudo dnf-mas manage register-user |
| Changer un mot de passe | sudo dnf-mas manage set-password alice |
| Fermer les sessions d’un compte | sudo dnf-mas manage kill-sessions alice |
| Verrouiller un compte | sudo dnf-mas manage lock-user alice |
| Diagnostic complet | sudo dnf-mas doctor |
Diagnostiquer une connexion SSO refusée
Section intitulée « Diagnostiquer une connexion SSO refusée »Après une migration, les sessions déjà ouvertes continuent de fonctionner : une connexion cassée ne se voit donc qu’au premier login neuf. Suivre MAS pendant une tentative :
journalctl -u matrix-authentication-service -f| Message | Cause | Correctif |
|---|---|---|
wrong signature alg sur /upstream/callback/… | MAS attend un id_token RS256, Kanidm signe en ES256 | id_token_signed_response_alg du fournisseur amont : réglé sur ES256 par le module |
client registration denied by the policy: invalid redirect_uri | Le client_uri annoncé par le client ne correspond pas à son schéma de redirection | Ne pas forcer oidc_metadata dans la config Element ; ses valeurs par défaut passent |
M_UNRECOGNIZED sur /login/sso/redirect | Le chemin part vers Synapse au lieu de MAS | Vérifier le matcher @masCompat du vhost Caddy |
Page User exists : « returned “bob” as username, which is not linked » | Un compte ami occupe déjà l’identifiant de l’utilisateur déclaré | Fusionner ou renommer (cf. collision d’identifiant) |
| « Le code QR n’est pas pris en charge » côté client | Le canal de rendez-vous MSC4108 est absent | experimental_features.msc4108_enabled : activé par le module avec MAS |
« L’appel n’est pas pris en charge », MISSING_MATRIX_RTC_TRANSPORT | Aucun backend MatrixRTC annoncé | Activer matrixRtc.enable (cf. Appels audio et vidéo) |
| Appel qui sonne mais reste muet, ou coupe au bout de quelques secondes | Les ports média n’atteignent pas l’hôte | Ouvrir 40000-40100/udp et 7881/tcp jusqu’à lui |
Contrôles rapides, sans se connecter :
# org.matrix.msc4108 doit valoir truecurl -A Mozilla/5.0 https://matrix.domain.tld/_matrix/client/versions
# doit répondre 201 et une url publiquecurl -A Mozilla/5.0 -X POST --data probe \ https://matrix.domain.tld/_matrix/client/unstable/org.matrix.msc4108/rendezvousDiagnostiquer un bot muet
Section intitulée « Diagnostiquer un bot muet »Un bot qui ne répond pas à help alors que son service tourne tombe presque
toujours dans l’un des deux cas : ses tokens ne correspondent plus à la
registration chargée par Synapse, ou il reçoit les messages mais ne peut pas
les déchiffrer. Diagnostic dans l’ordre :
-
Le service tourne-t-il vraiment ?
Fenêtre de terminal systemctl status mautrix-<pont>journalctl -u mautrix-<pont> -n 50S’il redémarre en boucle avec « The as_token was not accepted », l’enregistrement en mémoire de Synapse ne correspond plus aux tokens du pont (typique après un reset ou une migration, voir l’encart plus haut) :
systemctl restart matrix-synapse, puis redémarrer le pont. -
Le message arrive-t-il au pont ? Suivre Synapse pendant l’envoi d’un
helpau bot :Fenêtre de terminal journalctl -u matrix-synapse -f | grep transactionsUne ligne
PUT .../_matrix/app/v1/transactions/... 200doit apparaître. Si rien ne part, l’appservice n’est pas chargé : vérifier la présence de l’enregistrement dans/var/lib/mautrix-<pont>/et redémarrer Synapse. -
Le pont peut-il le déchiffrer ? Si la transaction passe (200) mais que le bot reste muet, suivre ses logs pendant un nouvel envoi :
Fenêtre de terminal journalctl -u mautrix-<pont> -fChercher
decrypt,session,verification,dropping. Un échec de déchiffrement signifie que la clé de session du salon n’a pas été partagée avec le device actuel du bot (cas classique après un reset du pont : son identité e2ee a changé). -
Recréer la conversation. Quitter le message direct avec le bot et en démarrer un nouveau : le client établit une session de chiffrement neuve et partage la clé avec le device actuel du bot. Vérifier au passage que sa propre session Element est vérifiée.
-
Dernier recours : réinitialiser l’état du pont (encart ci-dessous), puis redémarrer Synapse pour recharger l’enregistrement.
Voir aussi
Section intitulée « Voir aussi »- Messagerie Matrix : guide utilisateur : connexion aux ponts pour les utilisateurs
- Matrix dans DNF : architecture et implémentation