Architecture et prérequis

difuzio (DIFfusion Unifiée vers Abonnés) est un moteur de listes de diffusion et de lettres d'information écrit en Go, pensé comme un successeur moderne de Sympa. Cette documentation s'adresse aux administrateurs système et aux exploitants qui installent, configurent et opèrent le service. Pour la documentation destinée aux abonnés et aux propriétaires de listes côté usage, voir le guide de l'abonné.

Architecture en bref

Un binaire unique, difuzio, expose plusieurs sous-commandes. En production, trois processus de longue durée partagent la même configuration et se coordonnent uniquement via la base de données (pas de bus de messages externe) :

  • serve-web : l'interface web (rendu serveur) et l'API REST /api/v1. C'est le seul processus exposé derrière un reverse proxy TLS.
  • serve-lmtp : la réception du courrier depuis Postfix via LMTP (posts vers les listes, commandes par email, bounces VERP, plaintes FBL).
  • worker : le pipeline de traitement des messages entrants, l'envoi sortant (relais SMTP), et les tâches périodiques (reaper, purge, expiration des tokens, évaluation du kill-switch de réputation). On en lance plusieurs pour le débit.

La base de données est la source de vérité unique : la file d'envoi, les jobs entrants, les sessions, les compteurs de réputation, l'audit, tout y est. Les verrous applicatifs sérialisent les écritures concurrentes entre workers.

Les deux profils de déploiement

Le coeur de difuzio (pipeline, autorisations, transformations, fan-out) est le même dans tous les cas. Ce qui change d'une installation à l'autre, c'est par où le courrier entre et par où il sort. Deux profils sont documentés et supportés.

Profil MTA local - difuzio a son propre serveur de messagerie :

Internet -> MX Postfix -> LMTP (serve-lmtp) -> pipeline -> relais SMTP local -> abonnés

Profil boîte externe - difuzio n'a qu'une boîte mail chez un hébergeur :

Internet -> boîte hébergeur -> poller IMAP (boucle du worker) -> pipeline -> submission 587 AUTH -> abonnés

Ce qui les sépare :

MTA local Boîte externe
Réception LMTP depuis Postfix, adresse d'enveloppe classée (post, subscribe, unsubscribe, owner, bounce) IMAP, une boîte = une liste (l'enveloppe SMTP est perdue, il n'y a rien à classer)
Envoi relais local, sans authentification submission 587 STARTTLS + AUTH de l'hébergeur
Abonnements par courriel et par le web par le web et le lien de désabonnement en un clic uniquement
Rebonds VERP, plaintes FBL, kill-switch de réputation non traités automatiquement : un abonné dont l'adresse meurt se retire à la main
SPF/DKIM/DMARC à publier et à signer soi-même (le MTA frontal signe) alignés nativement, l'hébergeur signe
Débit dimensionné par les pools d'envoi plafonné par le quota de la boîte (souvent quelques centaines de messages par jour)
Déploiement multi-hôte possible mono-hôte (le poller est un singleton)
Prérequis accès administrateur au MTA, MX, DNS une boîte mail et ses identifiants

Les deux coutures sont indépendantes et se règlent liste par liste : une même instance peut recevoir en LMTP pour une liste et relever une boîte IMAP pour une autre, ou n'utiliser le compte SMTP d'un hébergeur que pour certaines listes. Un troisième axe, orthogonal, est le backend de base de données (MariaDB ou SQLite, section suivante) : SQLite et boîte externe se marient bien pour une petite installation autonome, mais rien n'oblige à les prendre ensemble.

Un exploitant qui ne veut pas du profil boîte externe sur son serveur le ferme pour tout le monde avec policy.external_mailboxes: deny : aucun administrateur de domaine ne peut plus attacher un compte de fournisseur à une liste. Voir Configuration, section policy. Fermer le profil MTA local ne demande aucune option : il suffit de ne pas lancer serve-lmtp.

Pour installer le profil boîte externe de bout en bout, suivre Comptes de messagerie externes.

Backend de base de données

difuzio se compile en deux variantes : la variante MariaDB (celle par défaut, pour un service multi-hôtes et à volume) et la variante SQLite (installation mono-hôte, faible volume, aucun serveur de base à administrer). Le choix se fait à la compilation, pas au démarrage. Voir Base de données pour choisir, construire le bon binaire et connaître les limites de chacun.

Prérequis

Communs aux deux profils :

  • Un reverse proxy TLS devant serve-web.
  • Trois secrets (keyrings) d'au moins 32 octets, stockés en fichiers 0600, jamais en base.
  • MariaDB >= 10.6 (indispensable pour FOR UPDATE ... SKIP LOCKED). Une version antérieure fait échouer le démarrage (fatal, pas de repli silencieux). Avec la variante SQLite, aucun serveur de base n'est nécessaire.

Propres au profil MTA local :

  • Postfix en frontal (réception LMTP) et en relais (submission/réinjection), avec un accès administrateur pour router le domaine et publier le DNS.

Propres au profil boîte externe :

  • Une boîte mail par liste chez un hébergeur, avec IMAP et submission authentifié. Ni MX, ni Postfix, ni serve-lmtp.

Par où commencer

Les deux profils ne demandent pas la même lecture.

Profil boîte externe (une boîte chez un hébergeur, pas de serveur mail à soi) : lire Comptes de messagerie externes, qui déroule l'installation complète, puis Base de données pour la variante SQLite, Proxy web frontal, Listes et Mails transactionnels. Les sections Postfix de Installation et de Domaines, ainsi que les parties rebonds et pools d'envoi de Délivrabilité, ne s'appliquent pas : elles sont signalées comme telles sur place.

Profil MTA local (Postfix devant difuzio) : suivre le sommaire ci-dessous dans l'ordre, en sautant Comptes de messagerie externes.

Sommaire

  • Installation et déploiement - base de données, migrations, keyrings, systemd, intégration Postfix.
  • Comptes de messagerie externes - le profil boîte externe de bout en bout : IMAP relevé, submission authentifié, comptes par liste, limites et verrou global.
  • Base de données - MariaDB ou SQLite : choix, compilation, DSN, limites et sauvegarde.
  • Configuration - le fichier config.yaml section par section, surcharge par variables d'environnement, invariants validés au démarrage.
  • Proxy web frontal - exposer l'interface et l'API derrière Apache ou Nginx : TLS, en-têtes, vhosts complets.
  • Domaines - provisionner un domaine, le router dans Postfix, vérifier le DNS, préparer la délivrabilité.
  • Listes - créer des listes, choisir le type, régler les politiques (post, abonnement, archives, reply-to, munging).
  • Mails transactionnels - les courriers envoyés aux abonnés hors diffusion : confirmation, bienvenue, adieu, lien de connexion ; langue du domaine, textes personnalisables, forme HTML et texte.
  • Utilisateurs et rôles - le modèle RBAC, le bootstrap du premier super_admin, l'octroi de rôles.
  • Modération - la file de modération des messages et des abonnements, le kill-switch de réputation.
  • Délivrabilité - SPF/DKIM/DMARC/ARC, munging d'en-tête From, bounces, plaintes, pools d'envoi.
  • API REST - clés d'API, périmètre, points d'entrée existants, webhooks (avec garde anti-SSRF).
  • Exploitation - métriques Prometheus, sondes de santé, file d'envoi, sauvegarde, journaux et rétention.
  • RGPD - consentement, droit à l'effacement, rétention.
  • Référence CLI - toutes les sous-commandes et leurs options.

Conventions de cette documentation

Tous les exemples de commandes utilisent le binaire difuzio. Les commandes d'administration prennent soit --dsn <dsn>, soit --config <chemin> pour la connexion à la base. Les commandes daemon (serve-web, serve-lmtp, worker) prennent --config <chemin> et chargent les keyrings.

Toutes les dates et heures manipulées par difuzio sont en UTC.