6. Configuration¶
Tous les composants de Pepsi lisent un seul fichier de configuration de style INI (le format est partagé avec les outils GNU Taler). La référence exhaustive des options réside dans l’unique page de manuel pepsi.conf(5) et dans les chapitres par programme sous Programmes.
6.1. Format de fichier¶
Un fichier est une suite d’en-têtes [SECTION], chacun suivi d’affectations OPTION = VALUE. Les noms de section et d’option sont insensibles à la casse (par convention en majuscules) ; # ou % commence un commentaire ; une valeur peut être entre guillemets doubles pour préserver les espaces qui l’entourent.
Trois directives composent plusieurs fichiers — important pour garder les secrets hors de la configuration lisible par tous :
@inline@ FILEInclure un autre fichier, relativement au fichier courant.
@inline-matching@ GLOBInclure chaque fichier correspondant à un glob shell.
@inline-secret@ SECTION FILEFusionne une section depuis un fichier à mode restreint (typiquement des identifiants). Une directive termine la section dans laquelle elle apparaît : écrivez-la donc après la dernière option de cette section ; une option placée en dessous n’appartiendrait à aucune section et le fichier ne se chargerait pas. Un fragment qui ne peut pas être lu ne produit qu’un avertissement, ce qui fait paraître non définies les options qu’il porte ;
pepsi-setup runconfie chaque fragment au compte de service censé le lire.
Les options à valeur de chemin subissent une expansion $ depuis la section [PATHS] ou l’environnement ($VAR, ${VAR}, ${VAR:-default}). Les types de valeur sont booléen (YES/NO), nombre, durée (unités h/m/s uniquement — voir la mise en garde ci-dessous), chemin et mode unix (octal).
Avertissement
Les valeurs duration sont analysées par jiff::SignedDuration, qui n’accepte que les heures/minutes/secondes et en dessous. Une unité calendaire telle que 5 d ou 2 weeks ne s’analyse pas. Pour des fenêtres d’un jour ou plus, écrivez l’équivalent en heures (120 h) ou utilisez une option entière lorsqu’il en existe une (par exemple [pepsi-srs] MAX_AGE_DAYS).
6.1.1. Valeurs par défaut livrées : config.d¶
Sous le fichier de l’opérateur, il y a encore une couche. Chaque *.conf de ${DATADIR}/config.d (/usr/share/pepsi/config.d sur une installation par paquet) est analysé avant pepsi.conf : ces fichiers fournissent donc des valeurs par défaut que pepsi.conf redéfinit option par option. Ils appartiennent au paquet : redéfinissez ce que vous voulez dans pepsi.conf plutôt que de les éditer, sans quoi une mise à niveau écartera la modification.
Deux sont livrés, et ce sont les deux formes auxquelles cette couche est destinée.
vacation.confUne configuration qui se livre comme du texte plutôt que comme une valeur — les avis
[pepsi-vacation-default-message]en dix langues sur lesquels pepsi-stage-vacation se rabat. RedéfinirENdanspepsi.conflaisse les neuf autres en place.thunderbird.confUne valeur par défaut qu’un opérateur doit pouvoir défaire en une étape :
[pepsi] CRYPTO_ALLOW_DOWNGRADE = yes, de sorte que le S/MIME soit chiffré enEnvelopedDataAES-256-CBC. Thunderbird ne sait pas lire l”AuthEnvelopedDataAES-256-GCM que produit la valeur par défaut du code de Pepsi, et échoue en silence lorsqu’il essaie (voir Interopérabilité des clients). La valeur par défaut du code resteAuthEnvelopedData: supprimer le fichier rétablit donc immédiatement le chiffrement authentifié — ce qui est la raison pour laquelle ceci réside dansconfig.det non dans les sources.
6.3. Ingress et listeners¶
[pepsi-ingress] contient la politique d’acceptation des messages (HOSTNAME, ACCEPTED_DOMAINS, MAX_MESSAGE_SIZE, MAX_CONNECTIONS, DMARC_ENFORCE, paramètres DNS). Chaque section [pepsi-ingress-listener-<name>] lie une socket :
SERVE = tcp(avecBIND_TO/PORT),unix(avecUNIXPATH) ousystemd(activation par socket,FD_INDEX).MODE = plain|starttls|tlssélectionne la sécurité du transport ;starttls/tlsexigentTLS_CERTetTLS_KEY.
Déclarez autant de listeners que nécessaire — par exemple un listener MX sur 25 avec STARTTLS opportuniste et un listener de soumission sur 465 avec TLS implicite.
6.4. Le pipeline d’étapes¶
Le pipeline est entièrement câblé à partir des sections [stage-<name>]. Le nom de l’étape est un label choisi par l’opérateur ; le PROGRAM de la section sélectionne le binaire, et NEXT_STAGE/BOUNCE_STAGE connectent le graphe :
PROGRAM(obligatoire) Le binaire de l’étape (trouvé sur le
PATHsauf s’il est absolu). Un même binaire peut servir plusieurs étapes — il lit ses options depuis la section où le message se trouve actuellement.NEXT_STAGE(facultatif) Où un message avance en cas de succès. Une étape terminale sans
NEXT_STAGEsupprime le message remis.BOUNCE_STAGE(facultatif) Où un message ayant échoué de façon permanente (ou, avec
ORIGINATE_SUCCESS_DSN, remis avec succès) est acheminé pour générer un DSN — habituellement une étapepepsi-stage-bounce.PARALLELISM/MAX_MESSAGES/QUEUE_LIMIT(facultatif) Le dimensionnement du pool de workers que le dispatcher applique à cette étape : le plafond de processus workers concurrents (
PARALLELISM, par défaut 4, démarrés à la demande et récupérés à l’inactivité), le nombre de messages qu’un worker traite avant d’être recyclé (MAX_MESSAGES, par défaut 1000), et combien de messages sont pipelinés vers un worker à la fois (QUEUE_LIMIT, par défaut 4, de sorte que la capacité en vol de l’étape estQUEUE_LIMIT × PARALLELISMtandis que le nombre de processus et de connexions reste fixé parPARALLELISM). Voir pepsi-dispatch.FUSION(facultatif) Indique si un prédécesseur peut exécuter cette étape dans son propre processus worker au lieu de rendre la ligne au dispatcher. Vaut
YESpar défaut lorsquePROGRAMest l’une des étapes rapides sans corps (pepsi-stage-+if,discard,auto-whitelist,block-language,check-whitelist,srs,listouedit-settings) etNOsinon ;[pepsi] ALLOW_FUSION = NOdésactive la fusion globalement.
Les nouveaux messages entrent toujours à [stage-init], qui doit exister. Chaque programme lit ses propres options depuis sa section ; celles-ci sont documentées par programme sous Programmes.
6.4.1. Contraintes d’ordre¶
Le graphe du pipeline est à dessiner par vous, mais cinq ordonnancements ne sont pas des choix libres, et se tromper sur l’un d’eux produit du courrier qui paraît correct. pepsi-setup avertit pour trois d’entre eux : une étape de signature DKIM qui mène à une étape de chiffrement, une étape de déchiffrement qui mène à une étape ARC, et une étape de déchiffrement sans remise locale en aval.
Le chiffrement vient avant la signature DKIM. La chaîne sortante recommandée est
submission → … → encrypt → srs → dkim-sign → relay
pepsi-stage-encrypt réécrit le corps, et DKIM doit signer les octets réellement transmis. Signer d’abord donne un message dont la signature DKIM ne vérifie pas chez le destinataire — ce qui est pire que pas de signature du tout, car une signature cassée est un signal négatif plus fort pour un MTA récepteur qu’une signature absente.
Tout ce qui lit le corps vient avant le chiffrement. La barrière du péage à l’envoi (pepsi-stage-anti-spam) et la détection de langue (pepsi-stage-detect-language) veulent toutes deux du texte clair, et l’obtiennent toutes deux, parce que le chiffrement vient en dernier sur le chemin sortant — ce qui est la raison de l’ordre ci-dessus.
SRS est destiné au courrier réexpédié, et inoffensif sur la fin de relais sortante. Il réécrit un expéditeur situé dans le domaine de quelqu’un d’autre — du courrier que cet hôte réexpédie — afin que SPF passe au saut suivant. L’expéditeur nul et un expéditeur déjà dans le domaine SRS sont laissés tels quels, de sorte qu’avec SRS_DOMAIN réglé sur le domaine principal (la valeur par défaut de l’assistant) le courrier de nos propres utilisateurs passe inchangé, et une fin de relais partagée par le courrier réexpédié et le courrier soumis peut l’exécuter avant la signature, dans l’ordre que vérifie pepsi-setup : encrypt → srs → dkim-sign → relay. Un utilisateur d’un domaine servi supplémentaire est lui aussi réécrit ; cela coûte l’alignement SPF pour son domaine, mais DMARC passe toujours grâce à la signature DKIM alignée que dkim-sign ajoute ensuite.
ARC vient avant le déchiffrement. La chaîne entrante recommandée est
init = arc → decrypt → aliases → (anti-spam / language / …) → local delivery
Un ensemble ARC scelle le message tel qu’il est arrivé. pepsi-stage-decrypt réécrit le corps : déchiffrer d’abord ferait donc décrire à l”AMS scellé des octets que personne d’autre n’a jamais vus — une affirmation portant sur un message qui n’a jamais existé.
Le déchiffrement exige une remise locale en aval. Déchiffrer invalide la signature DKIM de l’expéditeur, ce qui est sans conséquence pour un message sur le point d’être classé dans une boîte aux lettres de cet hôte et ne l’est pas pour un message relayé plus loin. L’étape ne s’exécute donc que pour les destinataires que cet hôte sert et scinde un message comportant les deux sortes ; pepsi-setup avertit lorsqu’aucun pepsi-stage-relay-to-maildir ni pepsi-stage-relay-to-lmtp n’est atteignable depuis une étape de déchiffrement, car une telle étape est soit inutile soit nuisible.
L’image miroir de la règle sortante s’applique aussi : tout ce qui lit le corps vient après le déchiffrement, raison pour laquelle les étapes de contenu se situent là où elles sont. Notez que l’étape de déchiffrement charge tout le corps du message pour chaque message qui la traverse (son Load est fixé par étape, et le fait qu’un message soit protégé ne se voit pas dans les colonnes d’enveloppe) : le placement est donc autant une question de performance que de correction.
6.5. Exemples concrets¶
Chaque exemple ci-dessous est un pipeline complet et minimal pour une tâche, sans classification de langue, signature ARC/DKIM ni filtrage de spam — juste les sections partagées, un listener et les étapes qui font le travail. Ils partagent tous la même ossature :
[pepsi](uniquementKEY_DIRici — DKIM/ARC ne sont pas utilisés dans ces exemples),[pepsi-postgres]pour la base de données, et[pepsi-ingress]plus une socket[pepsi-ingress-listener-*].
Les listeners règlent MODE = starttls/tls mais pas de TLS_CERT/TLS_KEY : pepsi-setup remplit automatiquement les chemins certbot (voir Installation). Réglez-les explicitement, ou passez --no-certbot, pour gérer le certificat vous-même.
Chacun est une configuration réelle et autonome — pour superposer ARC, SRS, signature DKIM ou filtrage de spam par-dessus, insérez les étapes correspondantes entre init et l’étape de remise comme le montre l’exemple pepsi.conf.
6.5.1. Entrée minimale (relais vers un smarthost)¶
Un MX de bordure qui accepte le courrier pour nos domaines et remet chaque message à un unique smarthost amont authentifié. init est l’étape de relais ; le smarthost nous authentifie, donc aucune réécriture SRS n’est nécessaire ici
[pepsi]
KEY_DIR = /var/pepsi/keys
[pepsi-postgres]
CONFIG = postgres:///pepsi
[pepsi-ingress]
HOSTNAME = mail.example.org
ACCEPTED_DOMAINS = example.org
[pepsi-ingress-listener-mx]
SERVE = tcp
BIND_TO = 0.0.0.0
PORT = 25
MODE = starttls
# init: relay every accepted message to the upstream smarthost. A successful
# delivery is terminal (no NEXT_STAGE).
[stage-init]
PROGRAM = pepsi-stage-relay-to-smarthost
SERVER_NAME = mail.example.org
# The upstream smarthost (one [...-mta-*] section per route; CATCH_ALL takes
# everything not matched by a DOMAINS list).
[pepsi-stage-relay-to-smarthost-mta-upstream]
HOST = smtp.relay.example.net
PORT = 587
MODE = starttls
AUTH = plain
USERNAME = relayuser
PASSWORD = changeme
CATCH_ALL = yes
6.5.2. Sortie minimale (relais direct vers Internet)¶
Un hôte de soumission/relais qui accepte le courrier de nos propres utilisateurs et le remet directement au MX de chaque destinataire. Le listener fait confiance à un réseau local (MYNETWORKS), de sorte que ces soumissions sont marquées d’origine locale et autorisées à relayer vers n’importe quel domaine ; le courrier sortant conserve son propre expéditeur d’enveloppe, il n’y a donc pas d’étape SRS
[pepsi]
KEY_DIR = /var/pepsi/keys
[pepsi-postgres]
CONFIG = postgres:///pepsi
[pepsi-ingress]
HOSTNAME = mail.example.org
ACCEPTED_DOMAINS = example.org
[pepsi-ingress-listener-submission]
SERVE = tcp
BIND_TO = 0.0.0.0
PORT = 587
MODE = starttls
# Trust submissions from this network without authentication (use SASL_TYPE /
# TLS_AUTH_CLIENT instead for roaming users).
MYNETWORKS = 10.0.0.0/8
# init: deliver directly to each recipient's mail exchanger. Terminal.
[stage-init]
PROGRAM = pepsi-stage-relay-to-internet
SERVER_NAME = mail.example.org
# Read by pepsi-setup to build the SPF record listing our sending hosts, and
# to check each address's PTR against SERVER_NAME above. PUBLIC_IP belongs in
# the relay *stage's* section: pepsi-setup finds it by walking [stage-*] and
# keeping the sections whose PROGRAM is a relay, never by the program's own
# section name.
PUBLIC_IP = 203.0.113.7 2001:db8::25
6.5.3. Remise locale minimale (relais vers Maildir)¶
Un MX qui remet le courrier de notre domaine dans le Maildir/new/ des utilisateurs locaux. Chaque destinataire est dans ACCEPTED_DOMAINS (donc l’ingress l’accepte) et se résout en un compte local, d’où l’absence de NEXT_STAGE nécessaire — ajoutez-en un (une étape smarthost ou de rebond) si un destinataire de notre domaine peut ne pas avoir de boîte aux lettres locale
[pepsi]
KEY_DIR = /var/pepsi/keys
[pepsi-postgres]
CONFIG = postgres:///pepsi
[pepsi-ingress]
HOSTNAME = mail.example.org
ACCEPTED_DOMAINS = example.org
[pepsi-ingress-listener-mx]
SERVE = tcp
BIND_TO = 0.0.0.0
PORT = 25
MODE = starttls
# init: write each local recipient's copy into their Maildir via the setuid
# helper. Terminal for local recipients.
[stage-init]
PROGRAM = pepsi-stage-relay-to-maildir
SERVER_NAME = mail.example.org
Un déploiement de staging qui ne touche jamais au réseau remplace l’étape de remise par pepsi-stage-discard (voir pepsi-stage-discard).
6.6. Configuration en base de données¶
Le fichier décrit ci-dessus est la couche de base. Par-dessus, Pepsi lit un ensemble de redéfinitions gérées par l’administrateur depuis la table pepsi.config_override, de sorte qu’un déploiement en fonctionnement puisse être reconfiguré sans éditer de fichiers et sans redémarrage.
Rien de tout cela n’est activé par défaut. Sans lignes dans cette table, un déploiement se comporte exactement comme le dit son fichier de configuration — il n’y a aucune configuration implicite cachée dans la base de données, et supprimer toutes les redéfinitions ramène le système au comportement du fichier.
6.6.1. La chaîne de portées¶
Cinq couches, la précédence la plus faible d’abord :
Couche |
Écrite par |
S’applique à |
|---|---|---|
le fichier de configuration |
l’opérateur, avec un éditeur de texte |
tout |
|
|
tout |
|
|
les messages dont l’adresse pertinente est à ce domaine |
|
|
les messages dont l’adresse pertinente est exactement celle-là |
|
le titulaire du compte, par e-mail |
les messages vers/depuis cette seule adresse |
Les couches supérieures redéfinissent les inférieures option par option, jamais section par section. Une option qu’aucune couche ne mentionne conserve sa valeur du fichier : une redéfinition est donc toujours un amendement ciblé plutôt que le remplacement d’une section entière.
L”« adresse pertinente » est la même que celle qu’emploie la couche de paramètres par adresse : l”expéditeur d’enveloppe pour un message d’origine locale, sinon chaque destinataire d’enveloppe. Lorsque les destinataires d’un message se résolvent en configurations différentes pour l’étape sur le point de s’exécuter, le message est scindé en une ligne par configuration distincte, exactement comme pour pepsi.settings.
Les couches domain: et address: ne contiennent que des sections [stage-*] : une étape les consulte pour la section qu’elle exécute, message par message. Toute autre section est lue une fois par processus et voit le fichier plus la couche global, de sorte que pepsi-config refuse d’en stocker une surcharge à portée restreinte et que pepsi-setup run signale toute ligne de ce genre comme une erreur.
6.6.2. Pourquoi pepsi.settings est une table distincte¶
Les deux n’ont pas la même autorité d’écriture :
pepsi.settingsest écrite par les titulaires de comptes, depuis leur propre boîte aux lettres, via pepsi-stage-edit-settings, restreinte aux sections d’étape que l’opérateur a inscrites dansEDITABLE_STAGES;config_overridedéfinit le pipeline et n’est modifiable qu’à travers le rôle de base de donnéespepsi-config.
Les fusionner placerait des lignes modifiables par les utilisateurs dans la même table que la définition du serveur de messagerie, où un bogue dans une vérification d’espace de noms cesse d’être une fuite de redéfinition pour devenir « un utilisateur a reconfiguré le MTA ». PostgreSQL applique la séparation : pepsi-setup accorde INSERT/UPDATE/DELETE sur config_override au seul rôle pepsi-config, les révoque de chaque compte de service, et vérifie les deux contre la base de données en service après chaque installation. Un worker d’étape analyse du courrier hostile pour vivre ; il peut lire la configuration et ne peut pas la modifier.
6.6.3. Ce qui reste dans le fichier de configuration¶
Certaines sections ne sont jamais lues depuis la base de données, quelles que soient les lignes existantes. Une redéfinition qui en nomme une est ignorée à l’exécution et refusée à l’écriture :
[pepsi],[pepsi-postgres],[PATHS]Nécessaires pour trouver et ouvrir la base de données en premier lieu, et — pour
[pepsi]— foyer de la politique cryptographique réservée à l’administrateur.[pepsi-httpd],[pepsi-httpd-listener-*],[pepsi-httpd-cert-*]Le serveur qui sert l’interface de configuration doit toujours pouvoir démarrer, quoi que dise la base de données.
[pepsi-ingress-listener-*]Les sockets d’écoute sont liées au démarrage, souvent sous activation par socket et avant l’abandon des privilèges.
[pepsi-secure-link]Son
PEPPERest le secret côté serveur qui rend inutile une base de données volée (voir Le portail de repli par lien sécurisé). Une base de données capable de le remplacer pourrait discrètement faire en sorte que le prochain message stocké soit un message que l’attaquant peut ouvrir — la même catégorie de chose que l’abaissement de la politique cryptographique.[pepsi-admin]Décide qui peut administrer le serveur et comment la surface d’administration atteint la base de données ; un avis de la base de données à ce sujet serait un moyen de s’octroyer la console.
[pepsi-crypto],[pepsi-srs],[pepsi-origin]Chacune détient une clé côté serveur qui existe pour que la base de données seule ne suffise pas : les clés de chiffrement de clés (et laquelle d’entre elles enveloppe les nouvelles clés privées), la clé SRS qui autorise le relais vers n’importe quelle adresse, et la clé de preuve d’origine contre laquelle un rebond ou une demande de paiement qui revient est vérifié. Une base de données capable d’en remplacer une pourrait faire en sorte que la prochaine clé enveloppée en soit une qu’un attaquant peut ouvrir, ou qu’un rebond forgé soit relayé ou payé. Le reste de chaque section suit le même sort.
[pepsi-wizard]Ici pour une troisième raison : ce n’est pas du tout de la configuration, mais la trace que l’assistant de configuration initiale garde des réponses qu’on lui a données — que le questionnaire du navigateur dépose comme lignes brouillon dans cette table même. Les brouillons sont invisibles pour tout lecteur, mais une ligne non brouillon écrite à la main atterrirait sinon dans la configuration effective de chaque processus. Rien ne lit la section à l’exécution : la réponse sûre est donc que la base de données ne la fournit jamais non plus.
La ligne de partage est « nécessaire avant qu’une connexion à la base de données n’existe, limite de sécurité, ou lieu d’un secret côté serveur ». Les listeners sont délibérément du second côté : si la base de données pouvait déplacer une socket d’écoute ou changer son matériel TLS, une compromission de la base de données deviendrait une compromission des ports propres du serveur de messagerie.
Important
Ajouter un port de soumission est une opération éditeur-de-texte-et-redémarrage. Il en va de même du changement du certificat TLS d’un listener, de la connexion à la base de données, ou de la politique cryptographique de [pepsi]. Aucune interface d’administration ne peut les modifier, et aucune ne devrait laisser croire qu’elle le peut.
Les identifiants ne sont jamais stockés dans la base de données, quelle que soit la section où ils se trouvent. Une option dont le nom la désigne comme telle — contenant PASS, SECRET, TOKEN, CREDENTIAL, CLIENT_ID ou PEPPER, la règle qui masque une valeur partout où une configuration est affichée — est refusée par pepsi-config set et par l’API d’administration, et ignorée si une ligne pour elle existe malgré tout. La règle couvre aussi le fichier d’où un identifiant est lu et le point de terminaison auquel il est envoyé (TOKEN_FILE, TOKEN_ENDPOINT), puisqu’une base de données capable de les changer peut rediriger l’identifiant. Mettez-les dans le fichier ou dans un fragment secrets.d.
De même, une surcharge domain: ou address: n’est acceptée que pour une section [stage-*] (voir plus haut : rien d’autre ne lit ces couches), et refusée pour toute autre section plutôt que stockée là où rien ne la lira.
Deux autres options ne vivent que dans le fichier pour une raison plus simple — elles sont lues pour ouvrir la base de données elle-même, avant qu’une surcouche ne puisse exister : [pepsi-ingress] DB_POOL_SIZE et [pepsi-dispatch] DB_POOL_SIZE.
6.6.4. Rechargement à chaud, et ce qui exige un redémarrage¶
Chaque écriture dans la table déclenche une notification config_changed. Ce qui se passe ensuite dépend de la section :
[stage-*]— appliqué sans redémarrage.pepsi-dispatchfait deux choses lorsque la notification arrive : il reconstruit sa propre vue du pipeline à partir de la surcouche — quelles étapes existent, et pour chacune sonPROGRAM, sonPARALLELISM, sonMAX_MESSAGESet sonQUEUE_LIMIT— et il met ses workers d’étape hors service (aucun message n’est interrompu : un worker ne reçoit plus de travail et se termine une fois ses messages en cours traités), de sorte que leurs remplaçants lisent les nouvelles valeurs. Le message suivant est routé et exécuté avec la nouvelle configuration, ce qui rend l’ajout, la modification et la suppression d’une étape applicables à chaud. Le seul écueil : si le graphe rechargé ne s”analyse pas, le dispatcher s’arrête et sort avecEX_CONFIGplutôt que de router selon un pipeline que ses workers ne partagent plus. L’unité livrée le relance (Restart=always, en espaçant les tentatives jusqu’à une par minute), de sorte qu’il reprend de lui-même une fois la configuration corrigée. Une surcouche qui ne peut pas être lue (une erreur de base de données) est un cas différent : le dispatcher conserve son graphe d’étapes actuel et retente le rechargement, plutôt que d’abandonner chaque étape définie uniquement dans la base de données.- Tout le reste — exige un redémarrage du composant qui le lit.
[pepsi-ingress],[pepsi-srs],[pepsi-tlsrpt]et les autres sont lus une fois au démarrage. La valeur est stockée et prend effet au prochain démarrage de ce programme.pepsi-configindique après chaque écriture ce qui s’applique.
Un composant qui manque une notification — parce que son listener était déconnecté — relit la surcouche lorsque le listener se reconnecte : une notification perdue coûte donc de la latence et non de la correction.
6.6.5. Les secrets restent dans des fichiers¶
La base de données ne stocke que la référence @inline-secret@, jamais une valeur secrète, de sorte que chaque fragment de secrets.d reste la propriété de l’unique lecteur qui en a besoin : une étape non privilégiée peut lire son propre secret et rien d’autre. Des valeurs chiffrées en base de données de données donneraient à chaque lecteur une clé qui ouvre tout.
6.6.6. Modifier la surcouche¶
pepsi-config set stage-relay MAX_LIFETIME '48 h'
pepsi-config set --scope domain:example.org stage-relay DELAY_DSN_AFTER '4 h'
pepsi-config unset stage-relay MAX_LIFETIME
pepsi-config list
Chaque écriture est d’abord validée en construisant la configuration que produirait la modification et en y faisant passer le véritable analyseur de l’étape propriétaire — la même vérification que pepsi-stage-edit-settings applique à une redéfinition reçue par e-mail. Une valeur qui empêcherait un programme de démarrer est refusée avec le message d’erreur propre à ce programme, et rien n’est stocké.
Si une mauvaise ligne parvient malgré tout dans la table, ce qui se passe dépend de sa gravité. Une ligne qui ne peut pas être représentée dans la configuration (une portée inconnue, une section réservée au fichier, un nom mal formé) est journalisée bruyamment et ignorée ; une surcouche qui ne peut pas du tout être lue, ou dont le texte fusionné ne s’analyse pas, est journalisée et le programme s’exécute sur le seul fichier de configuration. Une valeur bien formée mais que le programme lui-même rejette — une durée inanalysable, un NEXT_STAGE ne nommant aucune étape — n’est pas ignorée : elle fait partie de la configuration effective, et le programme échoue dessus exactement comme il le ferait sur la même valeur dans le fichier. pepsi-setup run vérifie les deux (voir Validation).
6.6.7. D’où vient une valeur¶
pepsi-config dump --origin
pepsi-config dump --origin --scope address:user@example.org
annote chaque valeur effective avec la couche qui l’a posée (file, ou la portée en base de données), et chaque section selon qu’un changement s’y applique à chaud ou exige un redémarrage.
6.6.8. La sauvegarder¶
Les deux moitiés sont sauvegardées par des outils différents, à dessein :
ce qui est dans la base de données — les redéfinitions — est couvert par
pg_dumpavec le reste du schéma ;ce qui ne peut pas l’être, parce qu’il doit exister avant qu’une connexion à la base de données n’existe — le fichier de configuration et les fragments
secrets.d— est couvert parpepsi-config export, qui écrit une unique archive chiffrée par mot de passe.
L’archive consigne le mode, le propriétaire et le groupe de chaque fichier par nom, et pepsi-config import les restaure ; il refuse plutôt que de deviner lorsqu’un compte nommé n’existe pas sur la machine cible. Une archive qui perdrait la propriété casserait tous les lecteurs non privilégiés ou rendrait silencieusement un secret lisible par tous.
6.7. Validation¶
Validez toujours une configuration avant de vous y fier
pepsi-setup -c /etc/pepsi/pepsi.conf check # against live DNS
pepsi-config -c /etc/pepsi/pepsi.conf dump # effective values
pepsi-setup run refuse de changer quoi que ce soit si la configuration est invalide : il vérifie que [stage-init] existe, que chaque NEXT_STAGE/BOUNCE_STAGE se résout, que la configuration PROGRAM de chaque étape s’analyse, et que les domaines et les valeurs PUBLIC_IP sont bien formés.
Il valide aussi la surcouche de la base de données : une surcharge stockée doit nommer une portée réelle, ne doit pas nommer une section réservée au fichier (qui serait silencieusement ignorée), ne doit rien mettre d’autre qu’une section [stage-*] dans une portée domain: ou address:, et doit nommer une section d’étape qui existe — dans le fichier ou définie par la surcouche elle-même, puisque le dispatcher charge sans redémarrage une étape ajoutée avec pepsi-config set. La configuration qu’elle produit doit ensuite satisfaire encore l’analyseur propre à chaque étape concernée : la couche global par-dessus le fichier, et la chaîne de chaque portée domain:/address: par-dessus celle-ci, chacune exécutant les analyseurs des étapes qu’elle touche.