Courriel : pivot de Stalwart vers Postfix/Dovecot/rspamd
Stalwart trop jeune/volatil pour un pilier mail critique (config cassée 0.15→0.16, `config apply` annoncé non livré, API REST supprimée pour JMAP, gros backlog). Pivot vers la stack mature Postfix/Dovecot/rspamd, 100 % configurable par fichiers (alignée au modèle déclaratif Set-OPS). - Rôle serveur_stalwart retiré (Phase 1 prototypée ; git en garde la trace). - docs/courriel-conception.md mis à jour ; vault_stalwart_admin retiré. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
e3efbb5b1a
commit
e01adac67b
11 changed files with 59 additions and 228 deletions
20
CHANGELOG.md
20
CHANGELOG.md
|
|
@ -2,16 +2,18 @@
|
||||||
|
|
||||||
## 2026-07-02
|
## 2026-07-02
|
||||||
|
|
||||||
|
### Décidé
|
||||||
|
- **Service courriel : pivot de Stalwart vers Postfix + Dovecot + rspamd.** La Phase 1
|
||||||
|
Stalwart (`serveur_stalwart`) avait été prototypée et déployée (v0.16.11, install +
|
||||||
|
démarrage en mode récupération). Le prototypage a révélé un projet **trop jeune/volatil
|
||||||
|
pour un pilier mail critique** : config cassée entre 0.15 et 0.16, outil IaC
|
||||||
|
`stalwart config apply` **annoncé mais non livré** dans le binaire, API REST supprimée
|
||||||
|
(JMAP), gros backlog. Pivot vers la stack **mature Postfix/Dovecot/rspamd**, en prime
|
||||||
|
**100 % configurable par fichiers** (alignée au modèle déclaratif Set-OPS). Le rôle
|
||||||
|
`serveur_stalwart` est **retiré** (git en garde la trace) ; `docs/courriel-conception.md`
|
||||||
|
mis à jour. Réévaluer Stalwart ~2028.
|
||||||
|
|
||||||
### Ajouté
|
### Ajouté
|
||||||
- **Rôle `serveur_stalwart` — Phase 1 (install + démarrage).** Stalwart Mail Server
|
|
||||||
v0.16.11 (binaire unique natif, AGPL). Mécaniques réelles validées sur le binaire :
|
|
||||||
`config.json` = objet typé `{"@type":"RocksDb","path":…}` (DataStore seul), démarrage
|
|
||||||
IaC en **mode récupération** (`STALWART_RECOVERY_MODE` + `STALWART_RECOVERY_ADMIN`,
|
|
||||||
admin depuis la voûte `vault_stalwart_admin`). Install version-épinglée, user système,
|
|
||||||
unité systemd durcie (`CAP_NET_BIND_SERVICE`, `ProtectSystem`), EnvironmentFile pour le
|
|
||||||
secret. **Phase 2 à venir** (écouteurs SMTP/IMAP/JMAP, TLS step_ca, annuaire LDAP, DKIM —
|
|
||||||
provisionnés via l'API d'admin, le binaire n'ayant pas de CLI `apply`). Validé
|
|
||||||
statiquement ; déploiement réel à suivre.
|
|
||||||
- **`serveur_openldap` durci pour la prod : TLS via step_ca + organisation en intrant.**
|
- **`serveur_openldap` durci pour la prod : TLS via step_ca + organisation en intrant.**
|
||||||
- **TLS (LDAPS + STARTTLS)** : le certificat d'hôte step_ca (déposé par `client_pki`,
|
- **TLS (LDAPS + STARTTLS)** : le certificat d'hôte step_ca (déposé par `client_pki`,
|
||||||
`root:root 600`) est synchronisé vers un emplacement lisible par `openldap` (`/etc/ldap/tls`)
|
`root:root 600`) est synchronisé vers un emplacement lisible par `openldap` (`/etc/ldap/tls`)
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,8 @@
|
||||||
|---|---|
|
|---|---|
|
||||||
| Périmètre | **Vrai service de courriel** (boîtes utilisateurs, réception publique, IMAP) — pas un simple relais sortant. |
|
| Périmètre | **Vrai service de courriel** (boîtes utilisateurs, réception publique, IMAP) — pas un simple relais sortant. |
|
||||||
| Modèle | **Full self-host** : MX entrant **et** sortant chez Chezlepro, réputation d'IP propre. |
|
| Modèle | **Full self-host** : MX entrant **et** sortant chez Chezlepro, réputation d'IP propre. |
|
||||||
| Suite | **Stalwart Mail Server** (binaire unique Rust, AGPL ; SMTP/IMAP/JMAP/POP3 + anti-spam + DKIM intégrés). Adoptée et enveloppée par un rôle Set-OPS mince — pas de réimplémentation. |
|
| Stack | **Postfix (MTA) + Dovecot (IMAP/LMTP) + rspamd (antispam/DKIM)** — la stack libre **mature**, éprouvée depuis 20+ ans, **entièrement configurable par fichiers**. Trois rôles Set-OPS (`serveur_postfix`, `serveur_dovecot`, `serveur_rspamd`), comme on configure nginx/powerdns. |
|
||||||
| Identité | Boîtes/utilisateurs dans l'**OpenLDAP** existant (annuaire Stalwart → LDAP). Pas de comptes en double. |
|
| Identité | Boîtes/utilisateurs dans l'**OpenLDAP** existant (Postfix + Dovecot → LDAP). Pas de comptes en double. |
|
||||||
| DNS | Enregistrements publics dans la zone `chezlepro.ca` ; noms internes dans **PowerDNS**. |
|
| DNS | Enregistrements publics dans la zone `chezlepro.ca` ; noms internes dans **PowerDNS**. |
|
||||||
| PKI | **Deux CA distinctes** (voir §6) : Let's Encrypt pour les faces publiques, **step_ca** pour l'interne. |
|
| PKI | **Deux CA distinctes** (voir §6) : Let's Encrypt pour les faces publiques, **step_ca** pour l'interne. |
|
||||||
| Démarche | **Deux étapes** (voir §11) : **(A) fonctionnement INTERNE** d'abord (step_ca, LDAP, SMTP/IMAP internes, zéro dépendance publique) ; **(B) fonctionnement EXTERNE** ensuite (Namespro, Let's Encrypt, reprise du MX `.53`). |
|
| Démarche | **Deux étapes** (voir §11) : **(A) fonctionnement INTERNE** d'abord (step_ca, LDAP, SMTP/IMAP internes, zéro dépendance publique) ; **(B) fonctionnement EXTERNE** ensuite (Namespro, Let's Encrypt, reprise du MX `.53`). |
|
||||||
|
|
@ -19,6 +19,17 @@ Le rôle existant `serveur_sendmail` (relais sortant Postfix, sans boîtes) **re
|
||||||
courrier de notification système (via `client_smtp`/msmtp). Il ne fait pas partie de ce
|
courrier de notification système (via `client_smtp`/msmtp). Il ne fait pas partie de ce
|
||||||
service et ne le remplace pas.
|
service et ne le remplace pas.
|
||||||
|
|
||||||
|
> **Historique — pivot depuis Stalwart (2026-07-02).** On avait d'abord choisi Stalwart
|
||||||
|
> (binaire unique, moderne). Le prototypage a révélé un projet **jeune et volatil** :
|
||||||
|
> modèle de config **cassé entre 0.15 et 0.16**, outil IaC `stalwart config apply`
|
||||||
|
> **annoncé mais non livré** dans le binaire, API REST supprimée au profit de JMAP,
|
||||||
|
> backlog d'issues/PR important. Pour un **pilier critique souverain censé durer**, c'est
|
||||||
|
> trop précaire. On pivote vers la stack **mature Postfix/Dovecot/rspamd**, qui a en prime
|
||||||
|
> l'avantage d'être **100 % déclarable par fichiers** — donc parfaitement alignée avec le
|
||||||
|
> modèle Set-OPS (déclaratif, idempotent, exploitable sans IA). La Phase 1 Stalwart
|
||||||
|
> (rôle `serveur_stalwart`) est **retirée** ; git en garde la trace. Stalwart à réévaluer
|
||||||
|
> dans ~2 ans, une fois mûri et son `config apply` livré.
|
||||||
|
|
||||||
## 2. Prérequis IP publique — VÉRIFIÉ (recon DNS, 2026-07-02)
|
## 2. Prérequis IP publique — VÉRIFIÉ (recon DNS, 2026-07-02)
|
||||||
|
|
||||||
Le full self-host sortant exige un **PTR propre, forward-confirmed, hors blocklist**.
|
Le full self-host sortant exige un **PTR propre, forward-confirmed, hors blocklist**.
|
||||||
|
|
@ -56,28 +67,30 @@ Réserves :
|
||||||
│
|
│
|
||||||
┌───────────────┴───────────────┐
|
┌───────────────┴───────────────┐
|
||||||
▼ ▼
|
▼ ▼
|
||||||
┌───────────────────┐ ┌───────────────────┐
|
┌────────────────────┐ ┌───────────────────┐
|
||||||
│ mail-01 (PRIMAIRE) │ │ mail-02 (MX secours)│
|
│ mail-01 (PRIMAIRE) │ │ mail-02 (MX secours)│
|
||||||
│ Stalwart complet │◄──relais──│ Stalwart mode relais│
|
│ Postfix (MTA) │◄──relais──│ Postfix (relais) │
|
||||||
│ SMTP 25 / 587 / 465│ quand │ SMTP 25 seulement │
|
│ SMTP 25 / 587 / 465│ quand │ SMTP 25 seulement │
|
||||||
│ IMAP 993 / JMAP 443│ mail-01 │ file d'attente puis │
|
│ Dovecot (IMAP 993 │ mail-01 │ file d'attente puis │
|
||||||
│ antispam + DKIM │ est down │ transfert à mail-01 │
|
│ + LMTP + Sieve) │ est down │ transfert à mail-01 │
|
||||||
│ BOÎTES stockées │ └───────────────────┘
|
│ rspamd (spam + DKIM)│ └───────────────────┘
|
||||||
|
│ BOÎTES stockées │
|
||||||
└─────────┬──────────┘
|
└─────────┬──────────┘
|
||||||
│ (réseau interne, mTLS step_ca)
|
│ (réseau interne, mTLS step_ca)
|
||||||
┌───────┼─────────────┬──────────────┐
|
┌───────┼─────────────┬──────────────┐
|
||||||
▼ ▼ ▼ ▼
|
▼ ▼ ▼ ▼
|
||||||
OpenLDAP step_ca PowerDNS PostgreSQL
|
OpenLDAP step_ca PowerDNS PostgreSQL
|
||||||
(identité)(certs int.)(DNS interne)(métadonnées, option HA)
|
(identité)(certs int.)(DNS interne)(métadonnées, option)
|
||||||
```
|
```
|
||||||
|
|
||||||
- **mail-01 (primaire)** — Stalwart complet : réception `:25`, soumission authentifiée
|
- **mail-01 (primaire)** — **Postfix** (réception `:25`, soumission authentifiée `:587`/`:465`)
|
||||||
`:587`/`:465`, accès client IMAP `:993` + JMAP/web `:443`, anti-spam, **signature DKIM**,
|
+ **Dovecot** (IMAP `:993`, livraison LMTP, filtres Sieve, **hébergement des boîtes**,
|
||||||
**hébergement des boîtes**.
|
auth SASL) + **rspamd** (anti-spam, **signature DKIM**, greylisting). Auth des comptes via
|
||||||
- **mail-02 (MX de secours)** — Stalwart en mode relais, écoute seulement `:25`. Quand
|
**LDAP**.
|
||||||
mail-01 est indisponible, **accepte + met en file** l'entrant, puis **retransmet** au
|
- **mail-02 (MX de secours)** — **Postfix** en relais, écoute seulement `:25`. Quand mail-01
|
||||||
rétablissement → **zéro perte à l'entrée**. À placer idéalement sur un **lien/IP
|
est indisponible, **accepte + met en file** l'entrant, puis **retransmet** au rétablissement
|
||||||
indépendant** (autre site ou VPS), sinon la résilience est illusoire.
|
→ **zéro perte à l'entrée**. À placer idéalement sur un **lien/IP indépendant** (autre site
|
||||||
|
ou VPS), sinon la résilience est illusoire.
|
||||||
|
|
||||||
**Décision ouverte : emplacement du MX secours** (même cluster ? VPS ? autre site ?).
|
**Décision ouverte : emplacement du MX secours** (même cluster ? VPS ? autre site ?).
|
||||||
|
|
||||||
|
|
@ -135,15 +148,17 @@ _dmarc TXT "v=DMARC1; p=quarantine; rua=mailto:dmarc@chezlepro.
|
||||||
|
|
||||||
- **Nomenclature** : 2 fonctions, p. ex. `comm-mail` (primaire) + `comm-mx2` (secours) ;
|
- **Nomenclature** : 2 fonctions, p. ex. `comm-mail` (primaire) + `comm-mx2` (secours) ;
|
||||||
VMID / IP / VLAN dérivés comme le reste.
|
VMID / IP / VLAN dérivés comme le reste.
|
||||||
- **Rôles** :
|
- **Rôles** (config 100 % par fichiers, comme nginx/powerdns) :
|
||||||
- `serveur_stalwart` — mince : installe le binaire Stalwart, dépose la config
|
- `serveur_postfix` — MTA : `main.cf`/`master.cf`, TLS step_ca, cartes LDAP (domaines,
|
||||||
(annuaire LDAP, ACME public, DKIM, certs internes step_ca), unité systemd, règles
|
boîtes, alias), remise LMTP vers Dovecot, soumission `:587`/`:465`, milter rspamd.
|
||||||
nftables mail.
|
- `serveur_dovecot` — IMAP `:993` + LMTP + Sieve, stockage des boîtes, **auth SASL** (pour
|
||||||
- variante « relais » (ou paramètre du même rôle) pour le MX de secours.
|
la soumission Postfix), backend **LDAP**, TLS step_ca.
|
||||||
- **Intégrations** des nœuds mail : `client_ldap` (auth), `client_pki` (certs internes),
|
- `serveur_rspamd` — anti-spam, **signature DKIM**, greylisting ; branché à Postfix par milter.
|
||||||
`client_dns`.
|
- `serveur_postfix` en **mode relais** (paramètre) pour le MX de secours.
|
||||||
- **Secrets (voûte)** : clé/mots de passe d'admin Stalwart, éventuel secret ACME, clé
|
- **Intégrations** des nœuds mail : `client_ldap` (auth/annuaire), `client_pki` (certs
|
||||||
privée DKIM — via `vault_*`, câblés au rôle (comme les autres secrets).
|
internes), `client_dns`.
|
||||||
|
- **Secrets (voûte)** : bind LDAP, **clé privée DKIM**, éventuel secret ACME (Étape B) —
|
||||||
|
via `vault_*`, câblés aux rôles.
|
||||||
|
|
||||||
## 10. Décisions
|
## 10. Décisions
|
||||||
|
|
||||||
|
|
@ -151,7 +166,7 @@ _dmarc TXT "v=DMARC1; p=quarantine; rua=mailto:dmarc@chezlepro.
|
||||||
- ⬜ **Emplacement du MX de secours** (`.55` existe ; lien/PTR à cadrer) (§3).
|
- ⬜ **Emplacement du MX de secours** (`.55` existe ; lien/PTR à cadrer) (§3).
|
||||||
- ⬜ **Stockage** : embarqué v1 vs PostgreSQL dès le départ (§4).
|
- ⬜ **Stockage** : embarqué v1 vs PostgreSQL dès le départ (§4).
|
||||||
- ⬜ **Domaine(s)** desservi(s) : `chezlepro.ca` seul, ou multi-domaines (tenants) ?
|
- ⬜ **Domaine(s)** desservi(s) : `chezlepro.ca` seul, ou multi-domaines (tenants) ?
|
||||||
- ⬜ **Reprise du MX existant** : bascule directe de `.53` vers Stalwart, ou cohabitation transitoire ?
|
- ⬜ **Reprise du MX existant** : bascule directe de `.53` vers la nouvelle stack, ou cohabitation transitoire ?
|
||||||
|
|
||||||
## 11. Démarche en deux étapes
|
## 11. Démarche en deux étapes
|
||||||
|
|
||||||
|
|
@ -160,13 +175,13 @@ _dmarc TXT "v=DMARC1; p=quarantine; rua=mailto:dmarc@chezlepro.
|
||||||
But : prouver **toute la pile en interne**, en **code de prod**, dans le bac à sable.
|
But : prouver **toute la pile en interne**, en **code de prod**, dans le bac à sable.
|
||||||
Aucune dépendance au public.
|
Aucune dépendance au public.
|
||||||
|
|
||||||
1. **Pilier identité** : `serveur_openldap` (TLS **step_ca**) validé sur un nœud du bac à sable.
|
1. **Pilier identité** : `serveur_openldap` (TLS **step_ca**) — ✅ **déployé et prouvé** en bac à sable.
|
||||||
2. **`serveur_stalwart`** sur `mail-01` : TLS **step_ca** (mode `fichiers`), annuaire **LDAP**,
|
2. **`serveur_postfix` + `serveur_dovecot` + `serveur_rspamd`** sur `mail-01` : TLS **step_ca**,
|
||||||
DKIM interne, nftables mail.
|
annuaire/auth **LDAP**, DKIM interne, nftables mail.
|
||||||
3. **Prouver** : réception → boîte → accès **IMAP/JMAP** → envoi **intra-écosystème**, le tout
|
3. **Prouver** : réception → boîte → accès **IMAP** → envoi **intra-écosystème**, le tout en
|
||||||
en TLS interne, auth LDAP.
|
TLS interne, auth LDAP.
|
||||||
|
|
||||||
*(Étape actuelle : `serveur_openldap` écrit — reste à déployer/éprouver en bac à sable.)*
|
*(Étape actuelle : identité OK ; on démarre `serveur_postfix`.)*
|
||||||
|
|
||||||
### Étape B — Fonctionnement EXTERNE (transition prod, plus tard)
|
### Étape B — Fonctionnement EXTERNE (transition prod, plus tard)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,9 +38,6 @@ vault_forgejo_admin: ""
|
||||||
vault_forgejo_secret_key: ""
|
vault_forgejo_secret_key: ""
|
||||||
vault_forgejo_internal_token: ""
|
vault_forgejo_internal_token: ""
|
||||||
|
|
||||||
# --- Courriel (Stalwart) ---
|
|
||||||
vault_stalwart_admin: ""
|
|
||||||
|
|
||||||
# --- Observabilité / divers ---
|
# --- Observabilité / divers ---
|
||||||
vault_grafana_admin: ""
|
vault_grafana_admin: ""
|
||||||
vault_redis: ""
|
vault_redis: ""
|
||||||
|
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
---
|
|
||||||
- name: Appliquer le groupe serveur_stalwart
|
|
||||||
hosts: serveur_stalwart
|
|
||||||
become: true
|
|
||||||
gather_facts: true
|
|
||||||
|
|
||||||
pre_tasks:
|
|
||||||
- name: Vérifier que la cible est Debian
|
|
||||||
ansible.builtin.assert:
|
|
||||||
that:
|
|
||||||
- ansible_facts.distribution == "Debian"
|
|
||||||
fail_msg: "Ce playbook est prévu pour Debian."
|
|
||||||
|
|
||||||
roles:
|
|
||||||
- serveur_stalwart
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
---
|
|
||||||
# Stalwart Mail Server (binaire unique natif, AGPL). Rôle en 2 phases :
|
|
||||||
# Phase 1 (ce fichier) : installer + démarrer (mode récupération pour l'IaC).
|
|
||||||
# Phase 2 (à venir) : provisionner écouteurs/TLS/annuaire LDAP/DKIM.
|
|
||||||
# Cf. docs/courriel-conception.md.
|
|
||||||
|
|
||||||
serveur_stalwart_version: "0.16.11"
|
|
||||||
serveur_stalwart_arch: "x86_64-unknown-linux-gnu"
|
|
||||||
serveur_stalwart_url: "https://github.com/stalwartlabs/stalwart/releases/download/v{{ serveur_stalwart_version }}/stalwart-{{ serveur_stalwart_arch }}.tar.gz"
|
|
||||||
serveur_stalwart_binaire: "/usr/local/bin/stalwart"
|
|
||||||
|
|
||||||
serveur_stalwart_utilisateur: "stalwart"
|
|
||||||
serveur_stalwart_etc: "/etc/stalwart"
|
|
||||||
serveur_stalwart_data: "/var/lib/stalwart"
|
|
||||||
serveur_stalwart_store: "{{ serveur_stalwart_data }}/data"
|
|
||||||
serveur_stalwart_config: "{{ serveur_stalwart_etc }}/config.json"
|
|
||||||
serveur_stalwart_env: "{{ serveur_stalwart_etc }}/stalwart.env"
|
|
||||||
|
|
||||||
# DataStore de config.json. RocksDb embarqué par défaut (v1, cf. §4 du doc conception).
|
|
||||||
serveur_stalwart_store_type: "RocksDb"
|
|
||||||
|
|
||||||
# Mode récupération : expose l'API d'admin (port ci-dessous) pour provisionner les
|
|
||||||
# réglages (Phase 2). À basculer à false une fois la configuration chargée.
|
|
||||||
serveur_stalwart_recovery_mode: true
|
|
||||||
serveur_stalwart_recovery_port: 8080
|
|
||||||
|
|
||||||
# Identifiant admin de récupération. Le mot de passe vient de la voûte.
|
|
||||||
serveur_stalwart_admin_user: "admin"
|
|
||||||
serveur_stalwart_admin_password: "{{ vault_stalwart_admin | default('') }}"
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
---
|
|
||||||
- name: Redémarrer stalwart
|
|
||||||
ansible.builtin.systemd:
|
|
||||||
name: stalwart
|
|
||||||
state: restarted
|
|
||||||
daemon_reload: true
|
|
||||||
when: not ansible_check_mode
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
---
|
|
||||||
# Empreinte ressources du logiciel — dimensionnement VM derive (scripts/instancier.py).
|
|
||||||
# Sommee au socle SE + marge pour estimer coeurs/RAM/disque de la VM hote.
|
|
||||||
# Override possible par hote dans le plan (serveurs.yml: coeurs/memoire/disque).
|
|
||||||
setops_empreinte:
|
|
||||||
coeurs: 2
|
|
||||||
memoire_mo: 2048
|
|
||||||
disque_go: 10
|
|
||||||
|
|
@ -1,92 +0,0 @@
|
||||||
---
|
|
||||||
- name: Exiger le mot de passe admin Stalwart (Vault)
|
|
||||||
ansible.builtin.assert:
|
|
||||||
that:
|
|
||||||
- serveur_stalwart_admin_password | length > 0
|
|
||||||
fail_msg: "serveur_stalwart_admin_password est requis (via Ansible Vault : vault_stalwart_admin)."
|
|
||||||
|
|
||||||
- name: Créer l'utilisateur système stalwart
|
|
||||||
ansible.builtin.user:
|
|
||||||
name: "{{ serveur_stalwart_utilisateur }}"
|
|
||||||
system: true
|
|
||||||
home: "{{ serveur_stalwart_data }}"
|
|
||||||
create_home: false
|
|
||||||
shell: /usr/sbin/nologin
|
|
||||||
|
|
||||||
- name: Créer les répertoires stalwart
|
|
||||||
ansible.builtin.file:
|
|
||||||
path: "{{ item }}"
|
|
||||||
state: directory
|
|
||||||
owner: "{{ serveur_stalwart_utilisateur }}"
|
|
||||||
group: "{{ serveur_stalwart_utilisateur }}"
|
|
||||||
mode: "0750"
|
|
||||||
loop:
|
|
||||||
- "{{ serveur_stalwart_etc }}"
|
|
||||||
- "{{ serveur_stalwart_data }}"
|
|
||||||
- "{{ serveur_stalwart_store }}"
|
|
||||||
|
|
||||||
- name: Lire la version de Stalwart installée
|
|
||||||
ansible.builtin.command: "{{ serveur_stalwart_binaire }} --version"
|
|
||||||
register: serveur_stalwart_version_installee
|
|
||||||
changed_when: false
|
|
||||||
failed_when: false
|
|
||||||
|
|
||||||
- name: Installer le binaire Stalwart (absent ou version différente)
|
|
||||||
when: serveur_stalwart_version not in (serveur_stalwart_version_installee.stdout | default(''))
|
|
||||||
block:
|
|
||||||
- name: Télécharger l'archive Stalwart
|
|
||||||
ansible.builtin.get_url:
|
|
||||||
url: "{{ serveur_stalwart_url }}"
|
|
||||||
dest: "/tmp/stalwart-{{ serveur_stalwart_version }}.tar.gz"
|
|
||||||
mode: "0644"
|
|
||||||
|
|
||||||
- name: Extraire le binaire stalwart vers /usr/local/bin
|
|
||||||
ansible.builtin.unarchive:
|
|
||||||
src: "/tmp/stalwart-{{ serveur_stalwart_version }}.tar.gz"
|
|
||||||
dest: /usr/local/bin
|
|
||||||
remote_src: true
|
|
||||||
owner: root
|
|
||||||
group: root
|
|
||||||
mode: "0755"
|
|
||||||
notify: Redémarrer stalwart
|
|
||||||
|
|
||||||
- name: Nettoyer l'archive téléchargée
|
|
||||||
ansible.builtin.file:
|
|
||||||
path: "/tmp/stalwart-{{ serveur_stalwart_version }}.tar.gz"
|
|
||||||
state: absent
|
|
||||||
|
|
||||||
- name: Déployer config.json (DataStore)
|
|
||||||
ansible.builtin.template:
|
|
||||||
src: config.json.j2
|
|
||||||
dest: "{{ serveur_stalwart_config }}"
|
|
||||||
owner: "{{ serveur_stalwart_utilisateur }}"
|
|
||||||
group: "{{ serveur_stalwart_utilisateur }}"
|
|
||||||
mode: "0640"
|
|
||||||
notify: Redémarrer stalwart
|
|
||||||
|
|
||||||
- name: Déployer l'EnvironmentFile (secret admin de récupération)
|
|
||||||
ansible.builtin.template:
|
|
||||||
src: stalwart.env.j2
|
|
||||||
dest: "{{ serveur_stalwart_env }}"
|
|
||||||
owner: root
|
|
||||||
group: "{{ serveur_stalwart_utilisateur }}"
|
|
||||||
mode: "0640"
|
|
||||||
no_log: true
|
|
||||||
notify: Redémarrer stalwart
|
|
||||||
|
|
||||||
- name: Déployer l'unité systemd stalwart
|
|
||||||
ansible.builtin.template:
|
|
||||||
src: stalwart.service.j2
|
|
||||||
dest: /etc/systemd/system/stalwart.service
|
|
||||||
owner: root
|
|
||||||
group: root
|
|
||||||
mode: "0644"
|
|
||||||
notify: Redémarrer stalwart
|
|
||||||
|
|
||||||
- name: Activer et démarrer stalwart
|
|
||||||
when: not ansible_check_mode
|
|
||||||
ansible.builtin.systemd:
|
|
||||||
name: stalwart
|
|
||||||
enabled: true
|
|
||||||
state: started
|
|
||||||
daemon_reload: true
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
{"@type":"{{ serveur_stalwart_store_type }}","path":"{{ serveur_stalwart_store }}"}
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
{% if serveur_stalwart_recovery_mode %}
|
|
||||||
STALWART_RECOVERY_MODE=1
|
|
||||||
STALWART_RECOVERY_MODE_PORT={{ serveur_stalwart_recovery_port }}
|
|
||||||
STALWART_RECOVERY_ADMIN={{ serveur_stalwart_admin_user }}:{{ serveur_stalwart_admin_password }}
|
|
||||||
{% endif %}
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
# Géré par Set-OPS (rôle serveur_stalwart). Ne pas éditer à la main.
|
|
||||||
[Unit]
|
|
||||||
Description=Stalwart Mail Server
|
|
||||||
After=network-online.target
|
|
||||||
Wants=network-online.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=simple
|
|
||||||
User={{ serveur_stalwart_utilisateur }}
|
|
||||||
Group={{ serveur_stalwart_utilisateur }}
|
|
||||||
EnvironmentFile=-{{ serveur_stalwart_env }}
|
|
||||||
ExecStart={{ serveur_stalwart_binaire }} --config {{ serveur_stalwart_config }}
|
|
||||||
Restart=on-failure
|
|
||||||
RestartSec=5
|
|
||||||
LimitNOFILE=65536
|
|
||||||
# Autorise l'écoute sur les ports privilégiés (25/443/465/587/993) sans être root.
|
|
||||||
AmbientCapabilities=CAP_NET_BIND_SERVICE
|
|
||||||
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
|
|
||||||
NoNewPrivileges=true
|
|
||||||
ProtectSystem=strict
|
|
||||||
ReadWritePaths={{ serveur_stalwart_data }}
|
|
||||||
ProtectHome=true
|
|
||||||
PrivateTmp=true
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
Loading…
Reference in a new issue