Tout a commencé le mercredi 30 juin par un message parfaitement innocent de Max qui nous dit que les disques sont presque pleins :
![Capture d'écran d'un message de Max alertant sur les disques presque pleins](/assets/images/posts/synapse-explo.png)
Pour éviter la catastrophe annoncée, je décide de trouver le coupable.
Après une rapide recherche, il apparait que PostgreSQL occupe plus de 50Go.
Ayant des SSD de 120 Go, c'est donc majoritairement PostgreSQL qui occupe de la place.
En creusant plus profondément, c'est la base de donnée de Synapse (le serveur Matrix) qui prend tout cet espace, les autres bases ne comptant que pour quelques kilo-octets.
À ce même moment, nous ne le savions pas encore, mais le réseau Matrix faisait face à [une vague de spam](https://matrix.org/blog/2021/06/30/security-update-synapse-1-37-1-released).
Sans être responsable de l'indisponibilité qui va suivre, elle plante le décor et participe à expliquer pourquoi nous avons été pris de court.
En effet, la croissance rapide de notre base de donnée n'est pas seulement due à des usages normaux, mais aussi au spam qui a généré beaucoup d'activité sur les autres serveurs, et via la fédération, participé à remplir notre base.
Pour finir de planter le décor, notre instance Matrix a 4 ans mais n'a jamais nécessité de nettoyage ou maintenance de quelque sorte que ce soit jusqu'ici, bien que jusqu'à récemment, nous nous fédérerions avec des salons bruyants comme [Matrix HQ](https://view.matrix.org/room/!OGEhHVWSdvArJzumhm:matrix.org/). Nous avons donc aucune expérience dans ce domaine.
Sûr de moi, je vise une petite maintenance de deux heures où je compte supprimer les salons de discussions vides et réduire l'historique distant des salons très bruyants. La documentation sur le sujet est quasi inexistante mais je me dis que c'est parce que la tâche ne doit pas être si complexe. En réalité, la maintenance durera 4 jours et ne se sera pas passée du tout comme prévu. Je vous propose de revenir ici sur tous les points qui ont bloqué !
Avant d'aller plus loin, je souhaite souligner l'existence de deux guides sur le sujet qui m'ont aidé et qui sont de très bons compléments à cet article :
- [Compressing Synapse database](https://levans.fr/shrink-synapse-database.html) par Levans
- [Administration Synapse > Nettoyage du serveur](https://www.tedomum.net/dev/service/matrix/administration/#nettoyage-du-serveur) par Tedomum
## L'API d'administration de Synapse
Replaçons le contexte : Matrix est un protocole, et spécifie entre autre des API de communications clients à serveurs et serveurs à serveurs.
Cependant, à ce jour, les API de Matrix ne permettent pas à des communautés de se gérer totalement en autonomie.
La preuve, nous étions en train d'épuiser les ressources du serveur mais nous pouvions rien faire en tant qu'utilisateur pour les libérer.
Au delà de la gestion des ressources, il manque aussi des outils pour la gestion du spam et la modération.
En suivant l'actualité de Matrix, on peut voir qu'ils travaillent déjà sur ces fonctionnalités.
Pour la gestion de l'espace disque, ils ont une option pour définir la durée de rétention de l'historique d'un salon de discussion mais l'option n'est pas encore disponible dans l'interface.
On sait aussi qu'ils ont échangé avec la Quadrature du Net sur les questions de modération.
En attendant la publication de ces fonctionnalités, les développeurs de Synapse ont déplacé ces responsabilités depuis les utilisateurs vers les administrateurs.
Ils fournissent aux administrateurs des fonctionnalités manuelles et naives via une API ne faisant pas partie de la norme Matrix.
J'ai commencé par explorer cette API via l'interface web synapse-admin réalisée par la communauté.
Elle m'a permis de supprimer presque un millier de comptes invités et quelques salons de discussions vides.
Cependant, cette interface montre vite ses limites : elle est très vite ralentie quand il y a beaucoup de contenu et gèrent très mal les opérations en lot (suppression de 40 salons d'un coup par exemple). Enfin, en affichant par défaut tout le contenu qu'elle a à disposition, elle expose inutilement des données personnelles aux administrateurs.
Très vite, je suis passé en ligne de commande avec `curl` (pour les requêtes HTTP) et `jq` (pour intéragir avec le JSON), ce qui semble être une pratique qui fait consensus parmi les administrateurs de serveurs Synapse.
La mise en route est rapide : il faut commencer par passer un compte Synapse en administrateur dans la base de données
```sql
UPDATE users SET admin = 1 WHERE name = '@foo:bar.com';
```
Ensuite, il faut récupérer un *bearer* pour ce compte.
Pour ma part, je me suis simplement connecté sur Element avec puis j'ai utilisé l'inspecteur réseau de mon navigateur, regardé les détails d'une requête partant vers l'API et extrait l'entête *Authorization* qui contient le *bearer*.
Enfin, pour ne pas retaper le bearer à chaque fois, je définis un alias pour ma session (il faut remplacer les points d'interogation avec le *bearer* que vous avez récupéré précédemment !) :
```bash
alias mctl='curl --header "Authorization: Bearer ???"'
```
Vous pouvez commencer par récupérer quelques informations simples comme le nombre de salons et le nombres de comptes sur votre serveur :
J'ai procédé à chaque fois en deux étapes : référencement des objets à supprimer dans un fichier puis appels à l'API.
J'ai commencé par les comptes, et plus particulièrement les comptes invités, qui étaient souvent utilisés quelques minutes avant d'être définitivement perdus :
```bash
cat users.json \
# requête jq manquante
>> users_to_delete.txt
```
Ensuite, [LX](https://adnab.me) avait développé un bridge entre Synapse et plusieurs autres protocols de communication comme Mattermost, Facebook ou IRC.
Ne nous donnant pas entière satisfaction, nous avons décidé de le décomissioner.
Le bridge devant répliqué un grand nombre de données, il était intéressant de supprimer ses données également.
Étant donné son évolution et ses différents protocoles, nous avons du réaliser plusieurs requetes via `jq` :
Enfin, bien que nous n'avions pas prévu à l'origine de supprimer des salons auxquelles nous participions encore,
il est apparu que certains étaient particulièrement couteux à suivre. Cette information n'est pas disponible via l'API,
cependant à l'aide de requêtes SQL plus loin, nous avons déterminé que les 6 salons suivants étaient trop couteux à suivre pour nous (Matrix HQ, Matrix HQ (old), Arch Linux (old), tor, openwrt et fedora-devel) :
```bash
cat >> rooms_to_delete.txt <<EOF
!OGEhHVWSdvArJzumhm:matrix.org
!mpvDHdMSZHzhzEDirR:matrix.org
!QtykxKocfZaZOUrTwp:matrix.org
!gVMacPcvhtqaEfaANo:matrix.org
!SEgsRQLScqPxYtucHl:archlinux.org
!MqVoatBTzkpWvekEvo:matrix.org
EOF
```
Maintenant que notre liste est complète, on peut supprimer les salons (l'API est synchrone) :
```bash
cat rooms_to_delete.txt \
| while read r; do
echo -e "delete $r\n"
mctl \
-w "\n%{http_code}\n" \
-X DELETE \
-H "Content-Type: application/json" \
-d '{"purge": true}' \
https://synapse.tld/_synapse/admin/v1/rooms/$r
done
```
Pour les salons qui restent, nous voulons limiter l'historique des contenus distants (c'est à dire des messages postés par les internautes ayant un compte rattaché à un autre serveur que le notre) à seulement deux mois. Si on veut remonter plus loin, on peut simplement redemander leur historique à leur serveur d'accueil.
Cette fois-ci l'API est asynchrone et on ne veut pas surcharger le serveur : on va surveiller la suppression courante avant d'en lancer une autre.
On veut aussi retélécharger la liste des salons avant de commencer car elle a bien changé : on en a supprimé beaucoup juste avant !
complexity_error: "Ce salon de discussion a trop d'activité, le serveur n'est pas assez puissant pour le rejoindre. N'hésitez pas à remonter l'information à l'équipe technique, nous pourrons ajuster la limitation au besoin."
admins_can_join: false
retention:
enabled: true
# no default policy for now, this is intended.
# DO NOT ADD ONE BECAUSE THIS IS DANGEROUS AND WILL DELETE CONTENT WE WANT TO KEEP!
purge_jobs:
- interval: 1d
```
## VACUUM FULL et Tablespace, un duo de choc
## Quand le WAL te met au pied du mur
## Stolon : initialisation, mise à jour et subtilités
keeper a besoin de la libc
très facile de flush totalement le cluster : reinit le cluster