feat(matrix): add homeserver and whatsapp bridge
Introduces the Matrix homeserver (Synapse) and the mautrix-whatsapp bridge. Configures Synapse with PostgreSQL, including specific collation requirements. Sets up secret generation for both services and manages their startup order.
This commit is contained in:
@@ -19,6 +19,8 @@
|
||||
./wayvnc
|
||||
# ./dnscrypt
|
||||
./adguard
|
||||
./matrix
|
||||
./matrix-whatsapp
|
||||
./navidrome
|
||||
./tor
|
||||
# ./minio
|
||||
@@ -27,6 +29,7 @@
|
||||
./discord-bot
|
||||
./eternal-terminal
|
||||
./nextcloud-mcp
|
||||
./amazon-mcp
|
||||
# ./gotify
|
||||
./zitadel
|
||||
# ./kanidm
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
# services/matrix-whatsapp/default.nix
|
||||
# Pont Matrix <-> WhatsApp (mautrix-whatsapp), serveur : ../matrix
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
dataDir = "/var/lib/mautrix-whatsapp";
|
||||
in {
|
||||
# mautrix-whatsapp dépend de libolm (goolm) pour le chiffrement megolm,
|
||||
# marqué insecure dans nixpkgs (CVE-2024-4519x, side-channel théorique).
|
||||
# C'est la dépendance crypto standard de TOUS les bridges mautrix.
|
||||
nixpkgs.config.permittedInsecurePackages = ["olm-3.2.16"];
|
||||
|
||||
services.mautrix-whatsapp = {
|
||||
enable = true;
|
||||
settings = {
|
||||
homeserver = {
|
||||
address = "http://127.0.0.1:8008";
|
||||
domain = "matrix.marcpartensky.com";
|
||||
};
|
||||
appservice = {
|
||||
# bind localhost uniquement + URL de registration joignable par synapse
|
||||
hostname = "127.0.0.1";
|
||||
address = "http://127.0.0.1:29318";
|
||||
ephemeral_events = false;
|
||||
};
|
||||
bridge = {
|
||||
permissions = {
|
||||
# le défaut du module "*": "relay" est neutralisé par relay.enabled=false
|
||||
"matrix.marcpartensky.com" = "user";
|
||||
"@marc:matrix.marcpartensky.com" = "admin";
|
||||
};
|
||||
relay.enabled = false;
|
||||
};
|
||||
encryption = {
|
||||
allow = true;
|
||||
default = true;
|
||||
# require=false : ne pas dropper les messages si une room reste non chiffrée
|
||||
require = false;
|
||||
# $VAR substituée par envsubst dans le preStart du module (valeur exportée ci-dessous)
|
||||
pickle_key = "$MAUTRIX_WHATSAPP_PICKLE_KEY";
|
||||
};
|
||||
backfill.enabled = true;
|
||||
# base sqlite dans /var/lib/mautrix-whatsapp (défaut du module), suffisant ici
|
||||
};
|
||||
# Le module ajoute matrix-synapse.service aux deps par défaut ; on inverse
|
||||
# l'ordre : c'est synapse qui attend le bridge (cf. services/matrix),
|
||||
# car le bridge génère sa registration dans son preStart.
|
||||
serviceDependencies = lib.mkForce [];
|
||||
};
|
||||
|
||||
# Pickle key e2ee générée une fois, hors du store nix.
|
||||
# mkBefore : exportée AVANT le envsubst du preStart du module qui l'injecte
|
||||
# dans config.yaml.
|
||||
systemd.services.mautrix-whatsapp.preStart = lib.mkBefore ''
|
||||
if [ ! -f ${dataDir}/pickle_key.txt ]; then
|
||||
${pkgs.openssl}/bin/openssl rand -hex 32 > ${dataDir}/pickle_key.txt
|
||||
chmod 600 ${dataDir}/pickle_key.txt
|
||||
fi
|
||||
export MAUTRIX_WHATSAPP_PICKLE_KEY=$(cat ${dataDir}/pickle_key.txt)
|
||||
'';
|
||||
|
||||
# Le module enregistre tout seul le bridge auprès de synapse
|
||||
# (registerToSynapse = true quand synapse est activé) et donne à synapse
|
||||
# le groupe mautrix-whatsapp pour lire whatsapp-registration.yaml.
|
||||
|
||||
# Après déploiement, connexion WhatsApp (à faire par marc, QR sur son tel) :
|
||||
# 1. ouvrir un DM avec @whatsappbot:matrix.marcpartensky.com dans son client Matrix
|
||||
# 2. envoyer : login
|
||||
# 3. scanner le QR code avec WhatsApp (appareils connectés)
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
# services/matrix/default.nix
|
||||
# Serveur Matrix classique (Synapse), pont WhatsApp : ../matrix-whatsapp
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
dataDir = "/var/lib/matrix-synapse";
|
||||
in {
|
||||
services.matrix-synapse = {
|
||||
enable = true;
|
||||
settings = {
|
||||
# ATTENTION : server_name ne peut plus être changé après le premier démarrage
|
||||
server_name = "matrix.marcpartensky.com";
|
||||
public_baseurl = "https://matrix.marcpartensky.com/";
|
||||
report_stats = false;
|
||||
max_upload_size = "100M";
|
||||
# inscription publique fermée : les comptes se créent avec
|
||||
# sudo matrix-synapse-register_new_matrix_user -u <user> -a
|
||||
# TCP obligatoire : le service tourne avec PrivateUsers=true, ce qui
|
||||
# casse l'auth peer par socket Unix (UID mappé). 127.0.0.1 est trust
|
||||
# (cf. services/postgres) et déclenche la dépendance postgresql.target
|
||||
# du module synapse.
|
||||
database.args.host = "127.0.0.1";
|
||||
};
|
||||
# registration_shared_secret hors du store nix, généré au 1er démarrage (preStart ci-dessous)
|
||||
# TODO : migrer vers sops si une clé age devient accessible à hermes
|
||||
extraConfigFiles = ["${dataDir}/secrets.yaml"];
|
||||
};
|
||||
|
||||
# BDD locale : postgres de tower est en auth trust sur localhost
|
||||
# (cf. services/postgres), donc pas de mot de passe à gérer.
|
||||
# Le module synapse attend postgresql.target tout seul (host = 127.0.0.1).
|
||||
services.postgresql = {
|
||||
ensureUsers = [
|
||||
{
|
||||
name = "matrix-synapse";
|
||||
# pas d'ensureDBOwnership ici : la DB est créée par le oneshot
|
||||
# ci-dessous avec le OWNER (ensureDatabases ne gère pas la collation)
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
# Synapse EXIGE une DB en collation C (sinon IncorrectDatabaseSetup au boot)
|
||||
# et ensureDatabases ne permet pas de la spécifier : création idempotente ici.
|
||||
# Connexion par socket en peer (user postgres local, pas de PrivateUsers ici).
|
||||
systemd.services.matrix-synapse-db = {
|
||||
description = "Création de la base matrix-synapse (collation C)";
|
||||
after = ["postgresql.service" "postgresql-setup.service"];
|
||||
requires = ["postgresql.service"];
|
||||
wantedBy = ["multi-user.target"];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
User = "postgres";
|
||||
};
|
||||
script = ''
|
||||
${pkgs.postgresql}/bin/psql -tAc "SELECT 1 FROM pg_database WHERE datname='matrix-synapse'" \
|
||||
| grep -q 1 \
|
||||
|| ${pkgs.postgresql}/bin/psql -c "CREATE DATABASE \"matrix-synapse\" OWNER \"matrix-synapse\" LC_COLLATE 'C' LC_CTYPE 'C' TEMPLATE template0"
|
||||
'';
|
||||
};
|
||||
|
||||
systemd.services.matrix-synapse = {
|
||||
# Le bridge WhatsApp génère son fichier de registration dans son propre
|
||||
# preStart : synapse doit démarrer APRÈS lui sinon le fichier
|
||||
# app_service_config_files n'existe pas encore et synapse refuse de démarrer.
|
||||
after = ["mautrix-whatsapp.service" "matrix-synapse-db.service"];
|
||||
wants = ["mautrix-whatsapp.service"];
|
||||
requires = ["matrix-synapse-db.service"];
|
||||
# mkBefore : tourne avant le --generate-keys du module
|
||||
preStart = lib.mkBefore ''
|
||||
if [ ! -f ${dataDir}/secrets.yaml ]; then
|
||||
echo "registration_shared_secret: $(${pkgs.openssl}/bin/openssl rand -hex 32)" > ${dataDir}/secrets.yaml
|
||||
chmod 600 ${dataDir}/secrets.yaml
|
||||
fi
|
||||
'';
|
||||
};
|
||||
|
||||
# Listener par défaut du module : 127.0.0.1:8008 (client + federation, x_forwarded).
|
||||
# Pas de port firewall à ouvrir : newt/Pangolin tourne sur tower et tape en local.
|
||||
# Exposition publique à faire côté Pangolin : matrix.marcpartensky.com -> http://127.0.0.1:8008
|
||||
}
|
||||
Reference in New Issue
Block a user