3. Installation

Pepsi peut être installé de deux façons. Construire depuis les sources à partir de l’espace de travail Cargo vous donne les binaires et vous laisse créer les comptes de service, régler les bits privilégiés et disposer les répertoires d’exécution. Le paquet Debian préconstruit fait tout cela pour vous — son postinst crée les comptes, les groupes, les répertoires, les redéfinitions de binaires privilégiés et la base de données — de sorte qu’il ne reste que l’amorçage spécifique au site (éditer la configuration et exécuter pepsi-setup).

Choisissez l’onglet de la méthode que vous utilisez. Tout ce qui suit — provisionner le schéma/les clés/le DNS, exécuter les services, le modèle de privilèges et le cycle de vie du schéma — est identique pour les deux.

3.1. Prérequis

  • PostgreSQL — une base de données, dans laquelle Pepsi installe l’unique schéma pepsi. Tous les composants se connectent à la même base de données. (Le paquet Debian Depends de postgresql et le tire pour vous.)

  • Le ``postgresql-contrib`` de PostgreSQL – optionnel, et seulement pour les listes de diffusion. Il porte l’extension pg_trgm, que les archives de listes emploient pour la recherche de sous-chaîne et approchée : trouver un nom d’hôte, une clé de configuration, une ligne de trace d’exécution, ou un nom que le chercheur a mal orthographié. Un dictionnaire de racinisation jette exactement cette matière : la recherche plein texte ne peut donc pas répondre du tout à ces requêtes.

    Un site sans elle s’installe et fonctionne normalement. L’extension est créée dans un bloc protégé : son absence est un avertissement et non un échec d’installation ; les archives n’ont alors que la recherche plein texte, et pepsi-list check indique dans quel mode le site se trouve. L’installer plus tard et relancer pepsi-setup run l’active, après quoi les archives existantes ont besoin d’un pepsi-archive reindex pour peupler la colonne que l’index lit.

    Le paquet Debian la place en Recommends : un apt install par défaut l’installe, et un site qui n’héberge aucune liste peut la retirer.

  • Pour un flux de courrier réel : un DNS public que vous contrôlez pour chaque domaine servi (pour publier les enregistrements DKIM, SPF et MTA-STS), et la capacité de lier le port SMTP privilégié 25 (et 465/587 pour la soumission). Un build de développement peut tourner entièrement sur des ports non privilégiés et une base de données jetable.

3.2. Installer Pepsi

Construisez l’espace de travail, placez les binaires et le SQL avec make install, et créez vous-même les comptes système et les privilèges (les mêmes que le paquet créerait — voir Utilisateurs, groupes et privilèges ci-dessous).

Prérequis supplémentaires

  • Une chaîne d’outils Rust avec rustc 1.93 ou ultérieur (le plancher est fixé par le taler-common vendorisé ; ./configure avertit en cas de version plus ancienne), plus les dépendances de construction natives des crates de cryptographie et Kerberos : pkg-config, cmake, libclang, nettle, GMP et les en-têtes de développement Kerberos (sur Debian : libclang-dev, nettle-dev, libgmp-dev, libkrb5-dev).

  • Le sous-module GNU Taler Rust intégré (vendored), récupéré avant le premier build

    git submodule update --init --recursive
    

Construction

Pepsi est un espace de travail Cargo dont le paquet racine (pepsi) possède chaque binaire sous src/bin/ ; les crates membres pepsi-* sont des bibliothèques que les binaires fins appellent. Un build de développement produit un exécutable par programme

cargo build --workspace

Un build de release lie à la place la plupart des programmes en un unique binaire multi-appel, pepsi, qui sélectionne le programme à exécuter d’après le nom sous lequel il est invoqué (argv[0]). Ceci est sélectionné par la fonctionnalité Cargo unibin (que la cible make build active pour vous) ; la fonctionnalité multibin par défaut conserve les binaires par programme utilisés pour le développement et la suite de tests

make build   # == cargo build --release --locked \
             #      --no-default-features --features unibin,crypto-nettle

Dans les deux cas, ce sont les noms par programme que vous exécutez ; la disposition de release les installe comme des liens symboliques vers l’unique binaire (voir Installation). Certains programmes ne sont pas pliés dedans et restent autonomes ; la liste faisant foi est STANDALONE_BINARIES dans le Makefile. Deux raisons y placent un programme :

  • il porte son propre bit setuid ou setgid, ce qu’un binaire partagé ne peut pas faire par programme — les helpers de remise locale, de ~/.forward et de wallet et les étapes qui les appellent, le relais smarthost, pepsi-quota, pepsi-whitelist, et pepsi-stage-encrypt et pepsi-stage-decrypt (tous deux setuid pepsi-crypto, afin de pouvoir atteindre le matériel de clé privée) — ou un site peut lui en donner un (pepsi-keys) ;

  • il est déployé ou invoqué séparément — pepsi-setup, pepsi-config, pepsi-stage-detect-language (ses modèles de langue sont volumineux ; ce binaire est lui-même multi-appel, et un second lien symbolique de $PATH, pepsi-detect-language, en exécute l’outil de diagnostic hors ligne), pepsi-telemetry (livré dans son propre paquet et tournant sur un hôte distinct) et pepsi-helper-mailbox-scan (que pepsi-whitelist exécute par son nom).

Les programmes auxquels ce chapitre fait référence sont listés ci-dessous. C’est une sélection, non un inventaire : les listes faisant foi sont FOLDED_BINARIES et STANDALONE_BINARIES dans le Makefile (BINARIES est dérivé de ces deux-là et n’est pas lui-même éditable).

  • pepsi-ingress — serveur SMTP entrant

  • pepsi-dispatch — dispatcher d’étapes

  • pepsi-stage-arc, pepsi-stage-srs, pepsi-stage-encrypt, pepsi-stage-decrypt, pepsi-stage-dkim-sign, pepsi-stage-bounce, pepsi-stage-relay-to-internet, pepsi-stage-relay-to-smarthost, pepsi-stage-discard — les étapes

  • pepsi-setup — provisionnement/amorçage

  • pepsi-queue — inspection/réparation de la file

  • pepsi-status — résumé de santé du pipeline

  • pepsi-sendmail — soumission locale (installé comme /usr/sbin/sendmail par le paquet Debian)

Les barrières de qualité que le projet garde vertes sont

RUSTFLAGS="-D warnings" cargo build --workspace
cargo clippy --workspace --all-targets -- -D warnings
cargo fmt --all -- --check
cargo test --workspace
cargo deny check
make docs

cargo test --workspace nécessite un PostgreSQL joignable, car la crate de cycle de vie du dispatcher lance le vrai dispatcher contre une base de données. make check est le point d’entrée qui la conditionne – il saute cette suite au lieu d’échouer lorsqu’aucune base de données n’est utilisable – et il exécute aussi cargo deny check ; voir Autres cibles make ci-dessous.

Installation

Un simple build ne produit que des binaires ; Pepsi livre aussi des migrations SQL et un exemple de configuration qui doivent être placés sur disque. Le Makefile enveloppe les deux — exécutez-le en tant que root afin qu’il puisse aussi appliquer les bits de binaire privilégié (il imprime sinon les chown/chmod exacts à exécuter à la main)

make install PREFIX=/usr/local SYSCONFDIR=/etc DESTDIR=

Mieux encore, lancez d’abord ./configure et laissez-le résoudre les variables de répertoire dans config.mk (que le Makefile lit avant ses propres valeurs par défaut, de sorte que ce que configure a décidé l’emporte). Chaque répertoire dérive de --prefix, si bien que nommer un préfixe et rien d’autre relocalise toute l’installation — binaires, SQL, valeurs par défaut de config.d et modèles de messages — en dessous

./configure --prefix=/opt/pepsi     # templates at /opt/pepsi/share/pepsi/templates
make && make install

--sysconfdir est la seule exception, car un fichier de configuration doit se trouver là où le système le cherche : c’est /etc lorsqu’aucun --prefix n’a été donné (et lorsque --prefix=/usr l’a été, puisque /usr/etc n’existe sur aucun système), et $(PREFIX)/etc sinon. Passez --sysconfdir explicitement pour redéfinir dans un sens comme dans l’autre.

./configure --help énumère tout ce qu’il accepte. Outre les variables de répertoire GNU (--prefix, --exec-prefix, --bindir, --sbindir, --libexecdir, --sysconfdir, --datarootdir, --datadir, --mandir, --infodir, --docdir), il prend :

--with-templatedir=DIR

L’endroit où vont les modèles de message ; doit correspondre à [pepsi] TEMPLATE_DIR. Par défaut $(DATADIR)/templates.

--with-systemdunitdir=DIR / --with-tmpfilesdir=DIR / --with-sendmail-libdir=DIR

Les fichiers d’unité, le fragment tmpfiles.d, et l’endroit où va le lien historique /usr/lib/sendmail.

--with-maildir-group=NAME, --with-forward-group=NAME, --with-wallet-group=NAME, --with-token-group=NAME, --with-dispatch-group=NAME, --with-crypto-user=NAME, --with-whitelist-user=NAME

Les noms, propres au site, des comptes et groupes qui conditionnent l’accès aux binaires privilégiés (voir Binaires privilégiés ci-dessous). Ils valent par défaut pepsi-maildir, pepsi-forward, pepsi-wallets, pepsi-token, pepsi, pepsi-crypto et pepsi-whitelist.

--enable-docs / --disable-docs

Détermine si les pages de manuel et le manuel info sont rendus depuis les sources ou repris pré-construits (ce que livre une archive de version). La valeur par défaut est auto : activé lorsque sphinx-build, makeinfo et Python avec docutils sont tous présents.

--enable-mta-links / --disable-mta-links

Détermine si make install revendique /usr/sbin/sendmail et le reste de l’interface Debian mail-transport-agent. Désactivé par défaut, afin qu’une installation depuis les sources ne puisse pas évincer silencieusement le MTA existant du système ; le paquet Debian passe INSTALL_MTA_LINKS=yes parce que son Conflicts: mail-transport-agent garantit déjà l’exclusivité.

--with-crypto-backend=FEATURE

La fonctionnalité Cargo du backend cryptographique de sequoia (par défaut crypto-nettle).

CARGO=, INSTALL=, SPHINXBUILD=, MAKEINFO=, INSTALL_INFO=, RST2MAN= et PYTHON= sont acceptés comme arguments VAR=VALUE ou depuis l’environnement. Les options dont cette construction n’a pas l’usage (--libdir, --localstatedir, --build, --host, …) sont acceptées et ignorées, de sorte qu’un pilote d’empaquetage générique puisse appeler le script sans modification ; seul un cargo manquant est une erreur fatale.

make install effectue les étapes suivantes :

install-bin

Construit le binaire de release (unifié) et l’installe dans $(DESTDIR)$(PREFIX)/libexec/pepsi/pepsi, puis crée un lien symbolique $(DESTDIR)$(PREFIX)/bin par nom de programme plié pointant vers lui (par exemple pepsi-ingress -> ../libexec/pepsi/pepsi). Les dix-sept programmes autonomes nommés dans le STANDALONE_BINARIES du Makefile sont installés comme leurs propres exécutables $(DESTDIR)$(PREFIX)/bin. Comme chaque lien symbolique réside toujours dans $(PREFIX)/bin (sur le $PATH), la dérivation de DATADIR à l’exécution ci-dessous n’est pas affectée.

install-data

Copie les fichiers SQL de pepsi-setup/db/ vers $(DESTDIR)$(DATADIR)/sql (où DATADIR = $(PREFIX)/share/pepsi). pepsi-setup les lit lors de l’installation du schéma ; le SQL_DIR par défaut est ${DATADIR}/sql. Installe aussi contrib/hosters.txt en tant que $(DATADIR)/hosters.txt, la liste des hébergeurs publics pour lesquels pepsi-whitelist import --auto-wildcard ne propose jamais de joker.

install-templates

Copie les modèles de messages (<name>.<lang>.body — la demande de paiement de l’anti-spam, les corps de rebond, les avis des listes de diffusion et les autres réponses automatiques) vers $(DESTDIR)$(TEMPLATEDIR), qui vaut par défaut $(DATADIR)/templates. La valeur par défaut [pepsi] TEMPLATE_DIR des binaires est ${DATADIR}/templates et se résout par la même dérivation à l’exécution, de sorte que les deux extrémités s’accordent sous n’importe quel préfixe sans que la configuration ne nomme de chemin.

install-config

Installe le pepsi.conf.sample de référence sous $(DESTDIR)$(SYSCONFDIR)/pepsi/. Ne crée jamais pepsi.conf : l’exemple câble des étapes facultatives qui demandent une configuration supplémentaire et n’est pas une configuration fonctionnelle ; le fichier en service provient donc de pepsi-setup --wizard (un fichier existant n’est jamais modifié).

install-config-d

Copie contrib/config.d/*.conf vers $(DESTDIR)$(DATADIR)/config.d. Ce sont des valeurs par défaut livrées, et non des conffiles, et elles sont analysées avant pepsi.conf — voir Configuration. Deux fichiers sont livrés avec Pepsi : les textes d’avis d’absence par langue et le réglage du conteneur S/MIME (CRYPTO_ALLOW_DOWNGRADE).

install-man / install-info

Installe les pages de manuel roff rendues sous $(DESTDIR)$(MANDIR)/manN et pepsi.info sous $(DESTDIR)$(INFODIR) (enregistré auprès d”install-info). Avec BUILD_DOCS=no — ce que règle ./configure --disable-docs, et ce qu’emploie une archive de release — des pages pré-construites sont installées au lieu d’être rendues, et chaque étape est sautée avec un message si aucune n’est présente.

install-doc

Installe README.md, NEWS, SECURITY.md, AUTHORS, COPYING et les textes de licence de LICENSES/ sous $(DESTDIR)$(DOCDIR), qui vaut par défaut $(DATAROOTDIR)/doc/pepsi.

install-systemd

Installe les unités systemd de debian/systemd/ dans $(DESTDIR)$(SYSTEMDUNITDIR) (en réécrivant /usr/bin et /etc/pepsi vers les BINDIR/SYSCONFDIR configurés) ainsi que le fragment tmpfiles.d qui donne à /run/pepsi son propriétaire et son ACL – d’où viennent entièrement les droits de ce répertoire, puisqu’aucune unité ne peut le déclarer comme RuntimeDirectory (voir Aucune unité ne peut le revendiquer comme RuntimeDirectory). Tout est livré désactivé. make install INSTALL_ADMIN_UNITS=no omet les deux unités pepsi-setup-apply, ce qui est l’équivalent, pour une installation depuis les sources, de ne pas installer le paquet pepsi-httpd-admin.

En outre, install dépend des cibles de bits privilégiés (install-helper, install-maildir-stage, install-forward-*, install-auto-pay-*, install-smarthost-stage, install-whitelist-suid, install-crypto-suid, install-quota-tool) décrites sous Binaires privilégiés ci-dessous ; chacune imprime les chown/ chmod à exécuter à la main lorsqu’elle n’est pas exécutée en tant que root, ou lorsque le groupe dont elle a besoin n’existe pas.

Redéfinissez PREFIX, SYSCONFDIR et DESTDIR pour convenir au système cible. make uninstall supprime tout ce que make install a placé (toujours y compris les deux unités pepsi-setup-apply, quoi que dise INSTALL_ADMIN_UNITS) mais laisse en place le pepsi.conf en service.

Autres cibles make

make check

Le point d’entrée des tests qui ne nécessite aucun compte distant : les vérifications croisées par inspection de fichiers des unités systemd et du chemin de la socket de télémétrie, les tests de l’espace de travail (moins la crate de cycle de vie du dispatcher, qui a besoin de PostgreSQL), puis – au mieux, sautés plutôt qu’échoués lorsque le prérequis est absent – la suite de cycle de vie contre une base de données pepsicheck locale, les tests de contrat des helpers setuid, le script d’interopérabilité de l’authentification, cargo deny check et la vérification des renvois croisés du manuel.

make integrationtests / make benchmarks

Les scripts de pipeline en conditions réelles sous tests/, qui nécessitent un SSH sans mot de passe vers les hôtes nommés dans ACCOUNTS (par défaut tests/test-accounts.ini, créé à partir de tests/test-accounts.ini.sample) ; integrationtests exécute d’abord la barrière d’interopérabilité Thunderbird. Les benchmarks forment une cible distincte parce qu’ils chargent délibérément le MTA.

make docs

Le manuel pour la langue source — un alias pour make docs-en, qui construit son HTML et son PDF, ainsi que les pages de manuel et le manuel info (tous deux dans la seule langue source). make docs-<lang> construit une autre langue et make docs-all construit toutes les langues de DOC_LANGUAGES (en de fr) ; make html construit le seul HTML de chaque langue.

make dist / make distcheck

Construire l’archive de version pepsi-$(VERSION).tar.gz (tous les fichiers suivis, y compris le sous-module vendorisé, plus configure et la documentation pré-construite), et la vérifier en la dépaquetant dans une arborescence propre et en y exécutant configure, make, make check, make install et make uninstall contre un préfixe jetable. L’archive est copiée depuis l’arbre de travail : make dist refuse donc de s’exécuter tant qu’un fichier suivi diffère de HEAD ou que le sous-module n’est pas au commit enregistré dans HEAD (les fichiers non suivis ne comptent pas) ; make dist DIST_ALLOW_DIRTY=yes construit malgré tout une archive de développement.

make clean / make distclean

clean exécute cargo clean et supprime la documentation rendue ; distclean supprime en outre config.mk, config.status et tout ce qu’a produit make dist.

Note

DATADIR doit correspondre à ce que les binaires calculent à l’exécution : taler-common dérive ${DATADIR} comme <install-prefix>/share/pepsi à partir de l’emplacement propre du binaire. Lors d’une exécution depuis un checkout des sources (non installé), réglez [pepsi-postgres] SQL_DIR explicitement afin que pepsi-setup trouve les migrations.

Préparer le système

Le postinst du paquet Debian effectue les étapes ci-dessous automatiquement ; sur une installation depuis les sources, vous les faites vous-même, en utilisant la même disposition de compte, groupe, mode et répertoire documentée sous Utilisateurs, groupes et privilèges et Répertoires et secrets ci-dessous. Créez les comptes et groupes avant make install (pour qu’il puisse appliquer les bits privilégiés), et les rôles de base de données avant pepsi-setup (qui installe le schéma) :

  1. Créez les comptes système, chacun --system avec /usr/sbin/nologin, home /var/pepsi et un groupe privé du même nom, plus les groupes de contrôle d’accès. debian/pepsi.postinst est la liste faisant foi ; cette boucle en est la transposition

    for u in pepsi pepsi-ingress pepsi-httpd pepsi-owner \
             pepsi-helper-token-refresh pepsi-whitelist pepsi-crypto \
             pepsi-keydisc pepsi-config; do
        addgroup --system "$u"
        adduser --system --home /var/pepsi --no-create-home \
                --ingroup "$u" --shell /usr/sbin/nologin \
                --disabled-password "$u"
    done
    for g in pepsi-maildir pepsi-forward pepsi-token pepsi-admin \
             pepsi-telemetry; do
        addgroup --system "$g"
    done
    # The shared-wallet account owns its wallet databases, so unlike the
    # service accounts it gets a real home.
    addgroup --system pepsi-wallets
    adduser --system --home /var/lib/pepsi-wallets --ingroup pepsi-wallets \
            --shell /usr/sbin/nologin --disabled-password pepsi-wallets
    install -d -o pepsi-wallets -g pepsi-wallets -m 0700 /var/lib/pepsi-wallets
    # Memberships: telemetry producers, and the SRS secret fragment.
    adduser pepsi pepsi-telemetry
    adduser pepsi-ingress pepsi-telemetry
    adduser pepsi pepsi-ingress
    

    Chacun des quatre derniers comptes existe parce que quelque chose refuse de fonctionner sans lui : pepsi-whitelist est le compte vers lequel la CLI de liste blanche est setuid, pepsi-crypto est le seul rôle de base de données à qui crypto_identity.private_wrapped est accordé et le propriétaire du fragment de chiffrement de clés, pepsi-keydisc est le rôle le plus étroit du déploiement (il analyse du matériel de clé récupéré sur l’internet ouvert), et pepsi-config est le seul rôle autorisé à écrire la surcouche de configuration. Omettez pepsi-crypto et install-crypto-suid se contente d’avertir — laissant les deux étapes cryptographiques non privilégiées et incapables d’ouvrir la moindre clé privée.

  2. Créez les neuf rôles de connexion PostgreSQL et la base de données (authentification par pair, en tant que superutilisateur postgres) — le même ensemble que crée debian/pepsi.postinst, soit chaque compte qui s’authentifie en tant que lui-même via la socket d’authentification par pair. pepsi-telemetry en fait partie même sur un nœud qui ne sert aucune télémétrie : pepsi-setup run lui accorde des droits sur chaque hôte, et il effectue son travail en base de données en tant que pepsi-owner, qui ne peut pas créer un rôle manquant

    for r in pepsi-owner pepsi pepsi-ingress pepsi-httpd \
             pepsi-whitelist pepsi-config pepsi-crypto pepsi-keydisc \
             pepsi-telemetry; do
        createuser "$r"          # createuser takes one role name at a time
    done
    createdb -O pepsi-owner pepsi
    
  3. Exécutez make install en tant que root (ci-dessus) afin que les bits setuid/setgid soient appliqués ; sinon appliquez-les à la main selon Binaires privilégiés ci-dessous. Chaque cible install-* se contente d’avertir lorsque le groupe dont elle a besoin manque, de sorte qu’un compte ou un groupe sauté ci-dessus laisse silencieusement le programme correspondant non privilégié.

  4. Créez les répertoires d’exécution avec la propriété et les modes listés sous Répertoires et secrets. pepsi-setup crée /var/pepsi/keys pour vous ; ne créez les répertoires de secrets de smarthost que si vous configurez un smarthost qui les utilise.

Le paquet est le chemin le plus simple : il livre les binaires (installés dans /usr/bin), le schéma SQL, les modèles de messages, les pages de manuel, le manuel GNU info et des unités systemd activées par socket, et son postinst provisionne tout le système pour vous.

Installer le paquet

Installez le .deb avec apt afin que ses dépendances (y compris postgresql) soient tirées

apt install ./pepsi_*.deb

Lors de la configure, le postinst automatiquement :

  • crée les dix comptes de service et les six groupes de contrôle d’accès — pepsi-maildir, pepsi-forward, pepsi-token, pepsi-admin, pepsi-telemetry et pepsi-wallets — avec les appartenances entre eux (les mêmes identités que l’installation depuis les sources crée à la main) ;

  • crée les répertoires d’exécution /var/pepsi — keys, tokens, token-refresh, tls, krb5 — ainsi que /etc/pepsi/secrets et /etc/pepsi/secrets.d avec la propriété et les modes documentés sous Répertoires et secrets ci-dessous ;

  • applique les bits de binaire privilégié via dpkg-statoverride (les trois helpers setuid-root, les programmes setgid qui peuvent les exécuter — les deux étapes de remise, l’étape de portefeuille et pepsi-quota —, le relais smarthost setgid, le pepsi-whitelist setuid et les deux étapes setuid pepsi-crypto — voir Binaires privilégiés ci-dessous) ; et

  • crée au mieux les neuf rôles de connexion PostgreSQL (pepsi-owner, pepsi, pepsi-ingress, pepsi-httpd, pepsi-whitelist, pepsi-config, pepsi-crypto, pepsi-keydisc, pepsi-telemetry) et la base de données pepsi (possédée par pepsi-owner) lorsqu’un cluster local est joignable — imprimant les rôles à créer à la main sinon.

Le service est livré désactivé : le paquet installe mais ne démarre pas Pepsi, vous laissant l’amorçage spécifique au site.

Note

pepsi est l’un des quatre paquets binaires construits depuis cette source : l’étape de détection de langue et le collecteur de télémétrie sont séparés pour des raisons de taille et de déploiement, et pepsi-httpd-admin — que pepsi Recommends, si bien qu”apt l’installe par défaut — porte l’unique mécanisme par lequel la console de navigateur peut provoquer un changement privilégié sur cet hôte. Retirer ce seul paquet est une mesure de durcissement prise en charge pour un déploiement administré depuis un terminal. Paquets Debian décrit chaque paquet et ce levier en détail.

Après l’installation du paquet

Lors de la première installation, le paquet copie une configuration provisoire dans /etc/pepsi/pepsi.conf ; les mises à niveau ultérieures ne touchent jamais ce fichier (ce n’est pas un conffile dpkg, de sorte qu’une mise à niveau ne s’interrompt jamais pour poser une question à son sujet). Éditez-le, puis exécutez l’amorçage exactement comme dans les étapes communes ci-dessous — par exemple

# 1. edit /etc/pepsi/pepsi.conf (HOSTNAME, ACCEPTED_DOMAINS, domains, TLS)
# 2. install the schema + DKIM keys and print the DNS records:
pepsi-setup --no-certbot run        # or:  pepsi-setup --wizard
# 3. publish the printed DNS records, then start the pipeline:
systemctl enable --now pepsi.target

Comme les unités sont activées par socket, pepsi.target démarre pepsi-ingress, pepsi-httpd et pepsi-dispatch ensemble ; vous n’invoquez pas les sous-commandes serve à la main.

3.3. Migrer depuis un serveur de messagerie existant

Si cet hôte exécute déjà Postfix, Exim, Sendmail, qmail ou Stalwart, vous n’avez pas à redériver sa configuration à la main. En l’absence de pepsi.conf, pepsi-setup --wizard détecte ce qui est installé et propose de l’importer : le nom d’hôte, les domaines acceptés, le smarthost (avec les identifiants de relais lus dans le propre fichier de mots de passe de ce serveur), la méthode de remise locale, la socket SASL de soumission, les réseaux de confiance, la limite de taille des messages, la durée de vie en file d’attente et les chemins des certificats TLS arrivent tous comme réponses pré-remplies du questionnaire, que vous confirmez ou corrigez ensuite une par une.

Pour voir ce qu’une migration produirait avant de lancer l’assistant — rien n’est écrit

pepsi-setup import

Les tables de routage sont converties elles aussi. /etc/aliases, /etc/postfix/virtual, la virtusertable de Sendmail, les fichiers .qmail-* de qmail et leurs équivalents deviennent une table d’alias Pepsi à côté de la configuration (voir pepsi-stage-aliases), les noms d’alias nus étant qualifiés dans le style que vous choisissez. Comme les clés d’alias de Pepsi doivent porter un domaine, postmaster: root devient par défaut postmaster@example.org  root@example.org pour chaque domaine accepté.

Tout ce qui n’est pas repris est écrit dans import-report.txt à côté de la configuration, réparti entre ce qui n’a pas pu être analysé, ce à quoi Pepsi n’a pas d’équivalent (header_checks, un alias qui remet à une commande), ce qui a été approché (une remise mbox devenue Maildir) et ce que l’importateur n’a pas reconnu. Un import n’interrompt jamais la configuration initiale — un fichier illisible ou une directive inconnue produit une entrée de rapport, pas un échec.

Deux choses ne sont délibérément pas migrées : le courrier en file d’attente (laissez la file de l’ancien serveur se vider avant de basculer le MX) et les clés DKIM (pepsi-setup run en génère de nouvelles et affiche les enregistrements à publier). Si l’ancien MTA occupe encore le port 25 au moment où l’assistant s’exécute, le rapport le signale — arrêtez-le et désactivez-le avant de démarrer pepsi-ingress.

Voir pepsi-setup pour le détail par serveur, les choix de --alias-style et les options --expert qui exposent les réglages sur lesquels le questionnaire ne vous interroge pas autrement.

3.3.1. Les filtres de courrier déjà présents sur l’hôte

Indépendamment de toute migration, l’assistant parcourt l’hôte à la recherche de démons milter — clamav-milter, rspamd, spamass-milter, milter-greylist, milter-regex, mimedefang, amavisd-milter — et propose chacun de ceux qu’il trouve comme étape. En trouver un signifie trois choses successives : le paquet est installé, une socket peut être lue depuis sa propre configuration (ou son unité, ou les chemins que livre sa distribution), et une véritable négociation d’options milter aboutit face à cette socket. Rien n’est proposé sur la seule foi d’un paquet installé, et la négociation est aussi la raison pour laquelle l”ALLOW_ACTIONS généré accorde exactement ce que ce filtre demande plutôt qu’une supposition.

Les filtres acceptés sont placés selon ce qu’ils font — politique et greylisting, puis virus, puis spam, puis cadres à usage général — après le déchiffrement et avant les barrières de liste blanche et de paywall. Comme Pepsi filtre après avoir accepté un message, le REJECT d’un filtre est acheminé vers une étape de rejet générée plutôt que de le faire rebondir, de sorte que les expéditeurs falsifiés n’obtiennent aucun backscatter ; voir pepsi-stage-milter. Les filtres dont Pepsi fait déjà le travail (opendkim, openarc, opendmarc, démons SPF, postsrsd) sont nommés et sautés plutôt que proposés.

3.4. Provisionner la base de données, les clés et le DNS

Avec un fichier de configuration en place (voir Configuration), exécutez l’outil d’amorçage une fois

pepsi-setup -c /etc/pepsi/pepsi.conf run > pepsi-dns.zone

Cela valide toute la configuration, installe le schéma pepsi, génère des clés DKIM RSA-2048 et Ed25519 par domaine sous KEY_DIR (seulement si absentes), et imprime les enregistrements DNS à publier (clés publiques DKIM, une politique SPF à partir des adresses PUBLIC_IP configurées, et un enregistrement MTA-STS). L’opération est idempotente et peut être relancée à tout moment ; la mise à niveau du schéma vers une nouvelle version se fait avec pepsi-setup schema (voir Mise à niveau). run --reset supprime et recrée le schéma (détruisant tout le courrier en file ; les clés sur disque sont conservées).

Publiez les enregistrements DNS imprimés, puis vérifiez ce qui est en service par rapport à ce que Pepsi attend

pepsi-setup -c /etc/pepsi/pepsi.conf check

Voir pepsi-setup pour le flux de provisionnement complet.

3.5. Configurer dans un navigateur

Tout ce qui précède peut aussi se faire depuis un navigateur, contre le même code. La voie du terminal est la plus courte sur une machine où vous avez un shell ; la voie du navigateur est là pour celles où vous n’en avez pas, et pour les opérateurs qui préfèrent voir les enregistrements DNS comme une liste rouge/verte plutôt que comme un fichier de zone.

3.5.1. La scission, et pourquoi

La configuration initiale est privilégiée : elle écrit /etc/pepsi/pepsi.conf, remet chaque fragment secrets.d à l’unique compte qui le lit, exécute certbot, crée des rôles de base de données et génère du matériel de clé — le tout en root. pepsi-httpd, qui sert l’interface, abandonne ses privilèges avant d’accepter une connexion et ne doit jamais les regagner.

Elle n’agit donc pas. Elle écrit une ligne d”intention disant ce qui devrait être vrai, et un programme root distinct — pepsi-setup apply, démarré à la demande et reparti dès qu’il n’a plus rien à faire — décide comment, le fait, et note ce qui s’est passé. Root n’est jamais sur le réseau. Lisez « Le modèle de confiance de l’applicateur » dans :doc:`programs/pepsi-setup` avant d’activer ceci : il énonce exactement ce que l’applicateur fera et ne fera pas, y compris ce qu’il ne peut délibérément pas faire (il n’y a aucune tâche de redémarrage ou d’arrêt, et install-schema refuse reset).

3.5.2. L’activer

Les paquets Debian livrent une configuration minimale mais complète, un listener d’administration sur une socket UNIX, et — dans pepsi-httpd-admin, que pepsi Recommends et qu”apt installe donc par défaut — l’unité socket de l’applicateur (voir Paquets Debian). Trois étapes :

# systemctl enable --now pepsi-httpd.socket pepsi-setup-apply.socket
# pepsi-setup -c /etc/pepsi/pepsi.conf bootstrap

La deuxième imprime un jeton à usage unique et la commande curl qui le transforme en premier compte d’administrateur. Sur la machine elle-même vous pouvez l’omettre entièrement : un membre du groupe pepsi-admin (et root) est identifié par SO_PEERCRED sur /run/pepsi/admin.sock et n’a besoin d’aucun identifiant.

Un réglage de plus est nécessaire avant que quoi que ce soit de privilégié puisse être demandé : [pepsi-admin] CONFIG_DB doit nommer une connexion qui s’authentifie en tant que rôle de base de données pepsi-config. C’est la limite : seul ce rôle peut mettre en file du travail de configuration, et le compte propre de pepsi-httpd ne l’est pas, de sorte qu’une compromission de la couche web n’est pas une compromission de la définition du pipeline. Tant qu’il n’est pas défini, les points de terminaison de configuration répondent 503 et le disent.

3.5.3. Le piloter

Le questionnaire est une donnée. GET /api/v1/setup/questions renvoie les étapes ordonnées et, pour chaque question, sa forme, sa valeur par défaut, son texte d’aide et la condition sous laquelle elle est posée — le même modèle que pepsi-setup questions imprime et le même par lequel l’assistant de terminal est décrit, dont la suite de tests garantit l’égalité. Les réponses sont mises en attente par PUT /api/v1/setup/answers dans des lignes de brouillon qu’aucun processus en fonctionnement ne peut voir, de sorte qu’une session interrompue ne puisse rien configurer à moitié.

POST /api/v1/setup/tasks demande ensuite la moitié privilégiée — écrire la configuration, obtenir des certificats, installer le schéma, générer des clés — et GET /api/v1/setup/tasks/{id}?since=<seq> diffuse ligne par ligne ce que fait l’applicateur.

3.5.4. Ce qui exigera toujours un éditeur de texte

Certains réglages ne sont lus que depuis le fichier de configuration, et aucune interface n’y changera rien : [pepsi], [pepsi-postgres], [paths], et les sections de listener HTTP(S) et d’ingress. Ils doivent fonctionner avant qu’une connexion à la base n’existe, ou bien ils constituent une limite de sécurité — une base capable de déplacer une socket d’écoute ou d’assouplir la politique cryptographique ferait d’une compromission de la base une compromission du TLS et des ports propres du MTA.

Ainsi, ajouter un port de soumission, ou déplacer un listener, est une opération éditeur-de-texte-et-redémarrage. Il en va de même de tout changement que la console marque restart plutôt que hot : il n’y a aucun bouton de redémarrage, car un bouton qui redémarrerait un service à la demande remettrait les privilèges de la couche web à quiconque l’atteint.

3.5.5. Le scripter

Le même modèle de réponses pilote une installation sans surveillance

pepsi-setup --wizard --answers answers.json -c /etc/pepsi/pepsi.conf

pepsi-setup questions imprime le schéma contre lequel ce fichier est écrit. Ce n’est pas une troisième implémentation du questionnaire : il exécute le questionnaire interactif avec chaque question répondue depuis le fichier, de sorte que les branches et la validation par champ sont celles qu’un humain voit.

3.6. Exécuter les services

Deux processus de longue durée doivent s’exécuter en continu :

  • pepsi-ingress serve — accepte le courrier (typiquement sous un gestionnaire de service, éventuellement avec l’activation par socket systemd pour les ports privilégiés).

  • pepsi-dispatch serve — exécute exactement une instance par système ; c’est le seul processus qui démarre les programmes d’étape.

Les programmes d’étape eux-mêmes sont lancés par le dispatcher comme des processus PROGRAM worker persistants qui lisent les identifiants de message sur l’entrée standard ; vous ne les exécutez pas à la main en production (pour le débogage, vous pouvez envoyer un identifiant par tube à worker, par exemple echo 42 | pepsi-stage-srs -c /etc/pepsi/pepsi.conf worker).

3.7. Mise à niveau

À partir de la première version, 0.0.0, chaque version met à niveau sur place la base de données de toute version antérieure : la file d’attente, le magasin de clés, les réglages et tout ce qu’elle contient d’autre sont conservés, et le courrier en attente dans la file est remis par la nouvelle version. Les retours à une version antérieure ne sont pas pris en charge (voir plus bas).

La procédure :

  1. Lisez NEWS pour la version. Il liste les options de configuration qui ont changé, et tout ce qui doit encore être fait à la main.

  2. Faites une sauvegarde (Sauvegarde et restauration), ou au moins activez le vidage automatique décrit plus bas.

  3. Installez la nouvelle version. Les paquets Debian font le reste : ils mettent à niveau le schéma et redémarrent les services qui tournaient. Depuis les sources : make install, puis pepsi-setup -c /etc/pepsi/pepsi.conf schema et systemctl try-restart pepsi.target.

  4. Vérifiez avec pepsi-status que la file d’attente se vide, et consultez le journal à la recherche d’avertissements (Journaux).

La suite de cette section explique ce qui se passe pendant l’étape 3.

Chaque programme Pepsi vérifie, lorsqu’il se connecte à la base de données, que le schéma a été construit à partir exactement des fichiers SQL avec lesquels le programme lui-même a été compilé. L’installateur enregistre le SHA-256 et la version de chaque fichier qu’il applique dans pepsi.schema_file, et un programme qui trouve autre chose – un schéma plus ancien, un plus récent, ou un construit à partir d’autres fichiers – s’arrête aussitôt avec le code de sortie 78 et un message indiquant le remède, plutôt que d’échouer sur sa première colonne manquante au milieu d’un message. Le dispatcher traite un worker d’étape qui s’arrête ainsi comme « ne peut pas encore s’exécuter », et non comme un plantage : le message qui lui avait été confié est remis dans la file, jamais mis en échec.

La mise à niveau du schéma est une étape à part

pepsi-setup -c /etc/pepsi/pepsi.conf schema

Elle installe les patchs qu’ajoute cette version, remplace les fonctions stockées, réapplique les droits des rôles et ne fait rien d’autre – ni certificats, ni clés, ni DNS – elle n’a donc besoin que de la section [pepsi-postgres]. Sur un collecteur de télémétrie, donnez-lui le fichier du collecteur, /etc/pepsi-telemetry/pepsi-telemetry.conf.

Les paquets Debian l’exécutent automatiquement lors de leur mise à niveau, avant le redémarrage des services ; une nouvelle installation est laissée à pepsi-setup run. Si elle échoue (la base de données est arrêtée, par exemple), le paquet s’installe quand même, un avis le signale, et les services refusent de démarrer et sont relancés par systemd – en espaçant les tentatives jusqu’à une par minute, sans limite de démarrage – jusqu’à ce que le schéma corresponde. Une fois la cause corrigée, il suffit d’exécuter la commande ci-dessus ; les services reviennent d’eux-mêmes.

Depuis les sources, après make install

pepsi-setup -c /etc/pepsi/pepsi.conf schema
systemctl try-restart pepsi.target

Ce que signifient les refus :

Le message indique

Que faire

pas de schéma pepsi

Une nouvelle installation : pepsi-setup run (ou pepsi-setup schema sur un hôte collecteur).

plus ancien que ce programme

pepsi-setup -c FILE schema.

plus récent que ce programme

Un retour à une version antérieure, qui n’est pas pris en charge. Réinstallez la version plus récente, ou restaurez la sauvegarde de la base de données prise avant la mise à niveau (ci-dessous).

construit à partir d’une autre copie d’un patch

Un patch publié ne change jamais, il s’agit donc d’un bogue ; merci de le signaler. La seule exception est une base de données construite à partir d’un instantané de développement (une copie Git entre deux versions), où le patch le plus récent est encore en cours de modification : videz-la puis recréez-la avec pepsi-setup run --reset.

fonctions stockées d’une autre compilation

Compilations de développement uniquement : pepsi-setup -c FILE schema.

3.7.1. Retour à une version antérieure

Non pris en charge. pepsi-setup refuse d’installer le SQL d’une version plus ancienne par-dessus un schéma plus récent (code de sortie 78, rien n’est modifié), et les programmes de la version plus ancienne refusent de s’exécuter dessus. Revenir à une version plus ancienne implique de restaurer une sauvegarde de la base de données prise avant la mise à niveau, puis d’installer les paquets plus anciens.

3.7.2. Sauvegarder avant une mise à niveau du schéma

Aucune sauvegarde n’est effectuée à moins que vous ne l’activiez. Une fois activée, la sauvegarde n’est effectuée que lorsqu’une mise à niveau modifie réellement le schéma : pg_dump enregistre le schéma pepsi (avec les extensions qu’il utilise) sous pepsi-<previous version>-<UTC time>.dump, lisible par root seulement. Si le vidage échoue, le schéma n’est pas mis à niveau. Les sauvegardes ne sont jamais supprimées automatiquement.

Avec les paquets Debian, c’est un réglage debconf, posé seulement à la priorité low

dpkg-reconfigure -plow pepsi

Répondez oui, puis confirmez ou modifiez le répertoire (par défaut /var/backups/pepsi). Sans surveillance, ou avant la première mise à niveau

echo "pepsi pepsi/schema-backup boolean true" | debconf-set-selections
echo "pepsi pepsi/schema-backup-dir string /var/backups/pepsi" | debconf-set-selections

Sur un hôte collecteur de télémétrie, les questions appartiennent à pepsi-telemetry (pepsi-telemetry/schema-backup, pepsi-telemetry/schema-backup-dir). Lorsque les deux paquets sont installés et utilisent la même base de données, celui qui la met à niveau le premier effectue la sauvegarde.

Depuis les sources, passez le répertoire à l’étape de mise à niveau

pepsi-setup -c /etc/pepsi/pepsi.conf schema --backup-dir /var/backups/pepsi

Pour en restaurer une, arrêtez les services, recréez la base de données vide et appartenant au propriétaire du schéma, et restaurez-y la sauvegarde en tant que ce propriétaire

systemctl stop pepsi.target
sudo -u postgres dropdb pepsi
sudo -u postgres createdb -O pepsi-owner pepsi
sudo -u pepsi-owner pg_restore -d pepsi /var/backups/pepsi/pepsi-0.0.0-20261001T000000Z.dump

Installez ensuite la version dont provient la sauvegarde et redémarrez les services. Tout ce que la base de données a appris après la sauvegarde – le courrier accepté depuis, les réglages modifiés depuis – est perdu. Les clés privées stockées dans le vidage sont chiffrées sous la clé de chiffrement de clés de secrets.d, qui ne se trouve pas dans la base de données : conservez ce fichier, et sauvegardez-le séparément (voir Sauvegarde et restauration).

3.8. Utilisateurs, groupes et privilèges

Pepsi ne s’exécute jamais en tant que root. Les démons de longue durée peuvent être démarrés en tant que root pour pouvoir lier les ports privilégiés et lire les clés TLS réservées à root, mais chacun abandonne ses privilèges vers son propre compte de service non privilégié avant de servir la moindre connexion ; si l’abandon ne peut être complété, le processus refuse de démarrer plutôt que de risquer de s’exécuter en tant que root (voir pepsi-common::privdrop). La remise locale — qui doit écrire dans les boîtes aux lettres d’utilisateurs arbitraires — est la seule opération qui nécessite plus que ce que l’utilisateur de service peut donner, et elle est confinée à un unique helper setuid à portée étroite plutôt que confiée au pipeline en général.

Avec les unités systemd fournies, les démons ne sont jamais root : systemd lie les sockets privilégiées (activation par socket) et démarre chaque processus directement sous son compte de service. Restent les clés TLS, que certbot conserve lisibles par root seul — pepsi-setup les fait donc lire par systemd également, en écrivant un drop-in LoadCredential= par unité : systemd ouvre chaque certificat et chaque clé en tant que root au démarrage de l’unité et remet au service une copie privée sous $CREDENTIALS_DIRECTORY, où le serveur regarde en premier. Relancez pepsi-setup run chaque fois que vous ajoutez, déplacez ou supprimez un certificat, afin que le drop-in soit régénéré. Voir pepsi-httpd.

La configuration par navigateur décrite ci-dessus est la seule voie par laquelle quelque chose d’autre qu’un opérateur à un terminal peut faire tourner un processus root : pepsi-httpd sonne à une socket de sonnette et systemd démarre un pepsi-setup apply root de courte durée. Cette voie est le privilège le plus facile à retirer dans Pepsi. Ses deux unités systemd forment un paquet Debian distinct, pepsi-httpd-admin, dont l’équivalent pour une installation depuis les sources est make install INSTALL_ADMIN_UNITS=no ; sans elles, rien ne vide pepsi.setup_task et aucune requête HTTP ne peut rien changer sous /etc/pepsi, tandis que pepsi-setup sur un terminal continue de fonctionner sans changement. Remettre le paquet n’agit pas rétroactivement sur ce qui a été demandé pendant son absence : son installation vide cette file avant que ses unités ne soient armées. Voir La scission comme levier de durcissement.

Les comptes et groupes ci-dessous sont créés automatiquement par le postinst du paquet Debian ; sur un make install vous les créez vous-même (les mêmes noms). L’accès à PostgreSQL se fait par authentification par pair via la socket locale : chaque compte de service se connecte en tant qu’un rôle de base de données du même nom, de sorte qu’aucun mot de passe n’est stocké nulle part. Une base de données distante conserve le même modèle : un rôle de connexion par compte, chacun authentifié par un certificat client ou un fichier de mot de passe qui lui est propre et que seul ce compte peut lire, nommé par rôle avec le paramètre substituable {role} dans [pepsi-postgres] CONFIG (voir CONFIG dans pepsi.conf(5)). Le fichier de configuration ne contient jamais de mot de passe.

3.8.1. Comptes de service

Ce sont des comptes système (--system, /usr/sbin/nologin, home /var/pepsi), chacun avec un groupe primaire privé du même nom. Les trois premiers sont des démons de longue durée qui abandonnent leurs privilèges vers leur compte après s’être liés ; les autres ne sont pas des démons du pipeline.

Compte

Exécute

But / accès

pepsi-ingress

pepsi-ingress

Serveur SMTP entrant. Activé par socket sous systemd (jamais root ; le matériel TLS arrive comme identifiant de service) ; démarré à la main, il lie 25/465/587 et lit les clés TLS en tant que root, puis abandonne ses privilèges. Rôle DB pepsi-ingress.

pepsi-httpd

pepsi-httpd

Serveur HTTP/HTTPS (politique MTA-STS + /metrics). Activé par socket sous systemd, exactement comme pepsi-ingress ; démarré à la main, il lie 80/443 en tant que root, puis abandonne ses privilèges. Rôle DB pepsi-httpd.

pepsi

pepsi-dispatch et chaque worker d’étape qu’il lance

L’identité de travail du pipeline. Lit les clés DKIM (via le groupe pepsi) pour signer. Rôle DB pepsi (possède les lignes de la file). C’est le compte qui acquiert transitoirement les deux identités de groupe de remise ci-dessous.

pepsi-owner

pepsi-setup (transitoirement)

Pas un service d’exécution. Possède la base de données, le schéma, les tables et les fonctions pepsi. Lorsque pepsi-setup s’exécute en tant que root, il assume temporairement cette identité (seteuid) afin que les objets qu’il crée soient possédés par le rôle pepsi-owner authentifié par pair, puis revient à root pour le travail sur le système de fichiers (génération de clés, corrections de propriété).

pepsi-helper-token-refresh

service pepsi-helper-token-refresh

Présent uniquement lorsqu’un smarthost utilise AUTH = oauth. Rafraîchit les jetons d’accès OAuth et écrit les fichiers de jeton que le relais smarthost lit. N’a aucun rôle de base de données.

pepsi-crypto

pepsi-keys (transitoirement), et les étapes cryptographiques de bout en bout

Gardien du matériel de clé privée de bout en bout. Possède secrets.d/pepsi-crypto.secret, la clé de chiffrement de clés qui ouvre pepsi.crypto_identity.private_wrapped, et constitue le seul rôle de base de données à qui cette colonne est accordée — tout autre rôle, pepsi compris, reçoit un droit au niveau colonne qui l’omet. pepsi-keys endosse cette identité le temps d’un appel à la base et la rend aussitôt. Voir Gestion des clés.

pepsi-whitelist

pepsi-whitelist (transitoirement)

Compte qu’endosse la CLI de liste blanche setuid afin que les utilisateurs ordinaires puissent entretenir leurs propres listes blanches d’expéditeurs. Son rôle de base de données se voit accorder SELECT/INSERT/DELETE sur pepsi.whitelist et rien d’autre.

pepsi-keydisc

services pepsi-keydisc@<method>

Découverte de clés (WKD, DANE, VKS, LDAP). Analyse du matériel de clé récupéré sur l’Internet ouvert, de sorte que son rôle de base de données est le plus étroit du déploiement. Voir Gestion des clés.

pepsi-config

pepsi-config (tel qu’exécuté par un opérateur)

Le seul rôle de base de données autorisé à écrire la surcouche pepsi.config_override : un composant qui traite le courrier ne doit pas pouvoir réécrire le pipeline dans lequel il s’exécute.

Les neuf rôles de connexion PostgreSQL — pepsi-owner, pepsi, pepsi-ingress, pepsi-httpd, pepsi-telemetry, plus les rôles étroits pepsi-whitelist, pepsi-config, pepsi-crypto et pepsi-keydisc — sont créés par le postinst du paquet (ou, sur une installation manuelle, par vous) avant que pepsi-setup n’installe le schéma ; pepsi-setup accorde ensuite à chacun ce dont il a besoin.

3.8.2. Groupes contrôlant l’accès aux ressources partagées

Quatre groupes existent uniquement pour contrôler l’accès aux binaires privilégiés et aux fichiers de secrets. L’utilisateur pepsi n’est délibérément pas un membre permanent de l’un d’eux : le bit setgid sur le binaire d’étape concerné accorde au worker l’identité de groupe seulement pour la durée de vie de ce processus.

pepsi-maildir

Contrôle l’accès au helper de remise locale. pepsi-helper-maildir-writer est setuid root et mode 4750 (root:pepsi-maildir), de sorte que seul ce groupe peut l’exécuter. pepsi-stage-relay-to-maildir est setgid de ce groupe (mode 2550, pepsi:pepsi-maildir — exécutable par le seul propriétaire, de sorte qu’aucun autre utilisateur local ne peut atteindre le bit setgid) ; lorsque le worker pepsi exec l’étape, il acquiert egid=pepsi-maildir, exactement le droit de lancer le helper — qui fait alors un setuid vers le destinataire et écrit dans ~/Maildir/new/. Le helper est le seul code qui touche jamais à la boîte aux lettres d’un tiers.

pepsi-forward

Contrôle l’accès au helper ~/.forward, exactement dans la forme de la paire maildir ci-dessus : pepsi-helper-dot-forward est setuid root et mode 4750 (root:pepsi-forward), et pepsi-stage-dot-forward est setgid de ce groupe (mode 2550, pepsi:pepsi-forward). Nécessaire seulement si vous exécutez l’étape ~/.forward ; sans le groupe, les cibles install-forward-helper / install-forward-stage de make install se contentent d’imprimer un avertissement et laissent les binaires non privilégiés.

pepsi-wallets

Contrôle l’accès au helper de wallet de la même façon : pepsi-helper-auto-pay est 4750 root:pepsi-wallets et pepsi-stage-auto-pay est setgid de ce groupe (mode 2550, pepsi:pepsi-wallets). Un compte système du même nom possède les bases de wallets partagées sous /var/lib/pepsi-wallets lorsque WALLET_MODE = shared. Nécessaire seulement si vous exécutez l’étape auto-pay ; sinon install-auto-pay-helper / install-auto-pay-stage se dégradent en avertissement.

pepsi-token

Contrôle l’accès au matériel secret que le relais smarthost lit : fichiers de jeton OAuth, le certificat/la clé client de TLS mutuel, et le cache d’identifiants Kerberos. pepsi-stage-relay-to-smarthost est setgid de ce groupe (mode 2550, pepsi:pepsi-token) ; les répertoires contenant ces secrets sont setgid pepsi-token de sorte que les fichiers déposés dedans héritent du groupe, et le relais peut les lire sans que l’utilisateur pepsi soit membre.

3.8.3. Binaires privilégiés

Ces bits sont réglés par make install lorsqu’il est exécuté en tant que root (il imprime sinon les chown/chmod exacts à exécuter à la main), et par le paquet Debian via dpkg-statoverride, qui est la liste faisant foi (debian/pepsi.postinst) :

Binaire

Mode / propriétaire

Pourquoi

pepsi-helper-maildir-writer

4750 root:pepsi-maildir

Setuid root pour pouvoir écrire dans la boîte aux lettres de n’importe quel utilisateur local ; verrouillé au groupe afin que seul pepsi-maildir puisse l’exécuter.

pepsi-stage-relay-to-maildir

2550 pepsi:pepsi-maildir

Setgid afin que le worker pepsi puisse exécuter le helper ci-dessus. Exécutable par le propriétaire et non par tout le monde : le bit setgid est toute la barrière, aussi tout autre utilisateur local ne doit-il pas pouvoir l’atteindre. pepsi ne peut pas obtenir le droit d’exécution par le groupe (il n’en est délibérément pas membre), il l’obtient donc en possédant le fichier. pepsi-quota, pepsi-stage-dot-forward et pepsi-stage-auto-pay portent la même forme pour leurs propres groupes.

pepsi-quota

2550 pepsi:pepsi-maildir

Même groupe et même raison : measure/reconcile exécutent le helper ci-dessus, et c’est ce bit qui permet à un balayage sans surveillance de le faire sans root.

pepsi-helper-dot-forward

4750 root:pepsi-forward

Setuid root pour pouvoir exécuter le ~/.forward d’un utilisateur en tant que cet utilisateur ; verrouillé au groupe de son étape.

pepsi-stage-dot-forward

2550 pepsi:pepsi-forward

Setgid afin que le worker pepsi puisse exec le helper ci-dessus.

pepsi-helper-auto-pay

4750 root:pepsi-wallets

Setuid root pour pouvoir descendre vers le compte propriétaire du wallet (ou vers l’uid propre du destinataire) afin d’exécuter taler-wallet-cli.

pepsi-stage-auto-pay

2550 pepsi:pepsi-wallets

Setgid afin que le worker pepsi puisse exec le helper ci-dessus.

pepsi-stage-relay-to-smarthost

2550 pepsi:pepsi-token

Setgid afin que le worker pepsi puisse lire les secrets pepsi-token ; non exécutable par tous, puisque l’étape accepte -c et enverrait sinon ces secrets à n’importe quel serveur qu’un utilisateur local désignerait.

pepsi-whitelist

4755 pepsi-whitelist:pepsi-whitelist

Setuid, et exécutable par tout le monde à dessein : tout utilisateur local peut gérer son propre espace de noms <login>/…, et la règle qui l’empêche de toucher à celui d’autrui est dans le programme, non dans le mode du fichier.

pepsi-stage-encrypt, pepsi-stage-decrypt

4750 pepsi-crypto:pepsi

Setuid, et non setgid : l’authentification par pair de PostgreSQL se fonde sur l”uid effectif, et pepsi-crypto est le seul rôle à qui crypto_identity.private_wrapped est accordé. Mode 4750 avec le groupe pepsi parce que ce ne sont pas des commandes d’utilisateur — seul le compte du dispatcher et root peuvent les exécuter.

Tout autre binaire est installé non privilégié, y compris pepsi-keys, qui est autonome pour les mêmes raisons mais est livré en 0755 : un binaire capable d’ouvrir chaque clé privée d’un déploiement est une prise bien plus grosse que l’unique table de pepsi-whitelist, aussi le rendre setuid pepsi-crypto est-il une décision propre à chaque site plutôt que la valeur par défaut.

3.8.4. Répertoires et secrets

pepsi-setup et le paquet créent ce qui suit sous /var/pepsi (le home du service) et /etc/pepsi. Les répertoires setgid (2750) font hériter les nouveaux fichiers du groupe du répertoire, de sorte que le matériel jeton/TLS/Kerberos est lisible par le groupe pour le relais sans aucun chgrp par fichier.

Chemin

Propriétaire / mode

Contenu

/var/pepsi

pepsi-owner:pepsi

Home du service.

/var/pepsi/keys

pepsi-owner:pepsi 2750

Clés privées DKIM par domaine : écrites par pepsi-setup, lues par le dispatcher pepsi (groupe pepsi) pour signer.

/var/pepsi/tokens

pepsi-helper-token-refresh:pepsi-token 2750

Fichiers de jeton d’accès OAuth : écrits par le rafraîchisseur, lus par le relais smarthost via le groupe pepsi-token.

/var/pepsi/token-refresh

pepsi-helper-token-refresh 0700

Jetons de rafraîchissement renouvelés privés ; jamais lisibles par le groupe.

/etc/pepsi/secrets

root:pepsi-helper-token-refresh 0750

Les identifiants de rafraîchissement de jeton @inline-secret@ ; seul le rafraîchisseur peut les lire.

/etc/pepsi/secrets.d

root:root 0751

Les fragments que pepsi-setup génère : la clé SRS, les mots de passe smarthost/LMTP, les jetons marchand et de reprise, la clé de preuve d’origine et la clé de chiffrement de clés pepsi-crypto. Traversable par tous (et non lisible), de sorte que chaque service puisse atteindre l’unique fragment qu’il a le droit d’ouvrir ; les fragments eux-mêmes sont en 0640 et appartiennent à leur unique compte lecteur. pepsi-setup crée le répertoire s’il est absent.

/var/pepsi/tls

root:pepsi-token 2750

Certificat + clé client de TLS mutuel pour le relais smarthost (TLS_CLIENT_CERT / TLS_CLIENT_KEY).

/var/pepsi/krb5

root:pepsi-token 2750

Cache d’identifiants Kerberos pour les smarthosts AUTH = gssapi (pointez KRB5CCNAME vers un cache FILE: ici ; un rafraîchisseur de keytab externe le remplit).

/run/pepsi

root:root 0775 + ACL

Les sockets de soumission locale, d’administration, HTTP et de l’applicateur de configuration. Créé par l’extrait tmpfiles.d, dont l’ACL accorde nommément à pepsi-ingress et pepsi-httpd l’accès en écriture.

/var/lib/pepsi-wallets

pepsi-wallets:pepsi-wallets 0700

Home du compte pepsi-wallets et bases de wallets que pepsi-helper-auto-pay crée en dessous (wallets/<key>.sqlite3, mode 0700). Uniquement avec pepsi-stage-auto-pay en WALLET_MODE = shared.

Les répertoires /var/pepsi/tokens, /var/pepsi/tls et /var/pepsi/krb5 (et le compte pepsi-helper-token-refresh) n’importent que lorsque vous configurez un smarthost avec le mécanisme AUTH correspondant ; un déploiement par défaut en direct-vers-MX ou en remise locale n’en utilise aucun.

3.9. Migrer depuis GNU Mailman

Une installation GNU Mailman existante – 2.1 ou 3 – passe sur Pepsi avec pepsi-list import et pepsi-archive import. Lisez le tableau ci-dessous avant de commencer, non après.

Les différences de comportement font un autre tableau, et il n’est pas dupliqué ici : Différences déclarées avec GNU Mailman 3 dans Listes de diffusion rassemble chaque endroit où Pepsi fait délibérément autre chose qu’amont – le désabonnement en un clic, l’éclatement toujours par destinataire, les adresses d’expéditeur obscurcies dans les archives, la pierre tombale de suppression, les en-têtes X-Mailman-* renommés, et ce qui est simplement absent (pas de passerelle NNTP, pas d’archiveurs enfichables, pas d’API de greffons). Deux copies de ce tableau divergeraient, et la copie que l’exploitant en migration lirait par hasard serait la périmée. Cette section ne traite que de ce que l”importeur laisse derrière lui.

3.9.1. Ce qui ne passe pas, et pourquoi

Pourquoi

Les mots de passe

Ni les empreintes sha512_crypt du cœur de Mailman ni les pbkdf2_sha256 de Django dans mailman-web ne sont importées. L’importeur d’amont a le code, et il est commenté. C’est pourquoi l’importeur n’a jamais à lire la base Django, et pourquoi il n’existe nulle part dans Pepsi de vérificateur d’empreintes héritées. Les adresses vérifiées restent vérifiées, personne ne prouve donc une adresse deux fois – il ne reste qu’à choisir un mot de passe, et c’est à cela que sert pepsi-list invite.

Les scores de bounce

Amont ne les importe pas non plus : le bounce_info de config.pck et les événements de rejet de Mailman 3 sont tous deux écartés, un membre migré démarre donc au score zéro sur les deux systèmes.

Les jetons en cours

Un jeton de confirmation ou de modération en attente est une promesse portant sur un flux qui n’existera plus après la bascule. Quiconque est au milieu d’un abonnement redemande.

Les « topics » (2.1)

Pas d’équivalent dans Mailman 3.

Les URI de modèles que nous refusons de récupérer

Une substitution en file: lirait le disque du serveur lui-même ; elle n’est donc pas importée. L’importeur signale chacune de ces URI au moment de l’import, plutôt que de laisser échouer des mois plus tard la première notification qui en a besoin, et la liste se rabat sur le modèle intégré.

Tout ce que l’importeur n’a pas compris figure dans son rapport. Il sort avec un état non nul lorsque quelque chose a été perdu, et c’est tout l’intérêt : une migration à moitié réussie sortie avec zéro est une migration que personne ne vérifie. Rien n’est annulé, et relancer un import est sans danger – chaque écriture est clé sur l’identifiant de liste, l’adresse ou la Message-ID, une seconde passe est donc sans effet.

3.9.3. Quand notre lecteur de pickle est plus strict que le leur

pepsi-list import mailman21 lit config.pck avec son propre analyseur, qui ne construit rien : aucun module n’est cherché et aucun appelable n’est appelé, car une config.pck vient du serveur de quelqu’un d’autre et le pickle.load de Python sur une entrée non fiable équivaut à l’exécution de code arbitraire.

Le prix en est la rigueur. Si le lecteur refuse un fichier – un opcode qu’il n’implémente pas, un protocole plus récent que ce que Python 2 pouvait écrire, un entier trop large pour 64 bits –, il le dit et nomme l’issue de secours

python2 contrib/mm21-export.py /var/lib/mailman/lists/announce/config.pck \
    > /root/announce.json
pepsi-list import mailman21 --json /root/announce.json --list announce

Ce script tourne sur l”ancien serveur, avec le Python auquel ce serveur faisait déjà confiance, et exporte le même dictionnaire en JSON. Les deux voies passent ensuite par la même correspondance : elles ne peuvent donc pas être en désaccord sur le sens du fichier. Une migration ne doit jamais être bloquée par le fait que notre analyseur est plus strict que celui qui a écrit le fichier.

3.9.4. Des renommages d’en-têtes qu’un utilisateur remarquera

Pepsi émet X-Pepsi-List-* là où Mailman émettait X-Mailman-* ; la table de correspondance est dans Listes de diffusion. C’est le coût réel pour un utilisateur qui migre, parce que les règles procmail et Sieve sont écrites contre ces noms, et cela vaut la peine de le leur dire avant la bascule plutôt qu’après.