--- - name: Resoudre l'annuaire (role partage) ansible.builtin.include_role: name: resoudre_annuaire when: serveur_postfix_mode != "relais" - name: Adopter la connexion annuaire pour Postfix ansible.builtin.set_fact: serveur_postfix_ldap_serveur: "{{ resoudre_annuaire_uri }}:{{ resoudre_annuaire_port }}" serveur_postfix_ldap_base: "{{ resoudre_annuaire_users_dn }}" serveur_postfix_ldap_bind_dn: "{{ resoudre_annuaire_bind_dn }}" serveur_postfix_ldap_bind_password: "{{ resoudre_annuaire_bind_password }}" no_log: true when: serveur_postfix_mode != "relais" - name: Exiger le mot de passe de bind LDAP (Vault) ansible.builtin.assert: that: - serveur_postfix_ldap_bind_password | length > 0 fail_msg: "serveur_postfix_ldap_bind_password requis (via Ansible Vault, ex. vault_openldap_admin)." when: serveur_postfix_mode != "relais" - name: Exiger le nœud mail-store (remise LMTP) ansible.builtin.assert: that: - serveur_postfix_mailstore_hote | length > 0 fail_msg: "serveur_postfix_mailstore_hote requis (FQDN du nœud Dovecot qui héberge les boîtes)." when: serveur_postfix_mode != "relais" - name: Installer debconf-utils (requis par le module debconf) ansible.builtin.apt: name: debconf-utils state: present update_cache: true cache_valid_time: 3600 - name: Préconfigurer Postfix (debconf, installation non interactive) ansible.builtin.debconf: name: postfix question: "{{ item.question }}" vtype: "{{ item.vtype }}" value: "{{ item.value }}" loop: - { question: "postfix/main_mailer_type", vtype: "select", value: "Internet Site" } - { question: "postfix/mailname", vtype: "string", value: "{{ serveur_postfix_domaine }}" } loop_control: label: "{{ item.question }}" - name: Installer Postfix ansible.builtin.apt: name: "{{ serveur_postfix_paquets }}" state: present update_cache: true - name: Assurer le répertoire etc du chroot Postfix ansible.builtin.file: path: /var/spool/postfix/etc state: directory owner: root group: root mode: "0755" - name: Fournir la résolution de noms au chroot Postfix (plancher /etc/hosts) ansible.builtin.copy: src: "{{ item }}" dest: "/var/spool/postfix{{ item }}" remote_src: true owner: root group: root mode: "0644" loop: - /etc/hosts - /etc/resolv.conf - /etc/nsswitch.conf - /etc/services notify: Recharger postfix # --- Pont de certificat step_ca (déposé par client_pki) --- - name: TLS — créer le répertoire des certificats ansible.builtin.file: path: "{{ serveur_postfix_tls_dir }}" state: directory owner: root group: root mode: "0755" when: serveur_postfix_tls_actif | bool - name: TLS — déployer le script de synchronisation du certificat ansible.builtin.template: src: setops-postfix-cert-sync.sh.j2 dest: /usr/local/sbin/setops-postfix-cert-sync owner: root group: root mode: "0755" when: serveur_postfix_tls_actif | bool - name: TLS — déployer les unités de synchronisation (service + path) ansible.builtin.template: src: "{{ item.s }}" dest: "{{ item.d }}" owner: root group: root mode: "0644" loop: - { s: "setops-postfix-cert-sync.service.j2", d: "/etc/systemd/system/setops-postfix-cert-sync.service" } - { s: "setops-postfix-cert-sync.path.j2", d: "/etc/systemd/system/setops-postfix-cert-sync.path" } loop_control: label: "{{ item.d | basename }}" when: serveur_postfix_tls_actif | bool - name: TLS — synchroniser le certificat maintenant ansible.builtin.command: /usr/local/sbin/setops-postfix-cert-sync changed_when: false when: - serveur_postfix_tls_actif | bool - not ansible_check_mode - name: TLS — activer la surveillance du certificat (renouvellement) ansible.builtin.systemd: name: setops-postfix-cert-sync.path enabled: true state: started daemon_reload: true when: - serveur_postfix_tls_actif | bool - not ansible_check_mode - name: TLS — vérifier que le certificat est en place ansible.builtin.stat: path: "{{ serveur_postfix_tls_dir }}/cert.pem" register: serveur_postfix_cert when: serveur_postfix_tls_actif | bool - name: TLS — exiger le certificat (intégration client_pki requise sur ce nœud) ansible.builtin.assert: that: - serveur_postfix_cert.stat.exists | default(false) fail_msg: >- Aucun certificat step_ca ({{ serveur_postfix_tls_source_cert }}). Le nœud Postfix doit porter l'intégration client_pki. Déploie-la, puis relance. when: - serveur_postfix_tls_actif | bool - not ansible_check_mode # --- Configuration --- - name: Déployer la carte LDAP des boîtes ansible.builtin.template: src: ldap-mailboxes.cf.j2 dest: /etc/postfix/ldap-mailboxes.cf owner: root group: postfix mode: "0640" no_log: true # contient le mot de passe de bind LDAP notify: Recharger postfix # REDEMARRER, PAS RECHARGER — ET POSTFIX LE DIT LUI-MEME (2026-08-30). # # `main.cf` porte `inet_protocols`, et ce parametre-la ne se change PAS a chaud. Sur une # machine nee en `all` et passee en `ipv4`, le rechargement rend : # # warning: ignoring inet_protocols parameter value change # warning: to change inet_protocols, stop and start Postfix # fatal: :::submission: Address family for hostname not supported # # Le `master` garde donc son ancienne valeur, tente d'ouvrir `:::submission` en IPv6, et # meurt. Le service tombe en `failed` APRES avoir accepte une configuration valide — # `postfix check` ne dit rien, parce que la configuration EST valide ; c'est la # transition qui ne l'est pas. # # MEME FAMILLE QUE `nginx-restart-si-changement-d-ecoute` : un rechargement ne reapplique # pas un changement d'ECOUTE. Ce qui vit dans le processus maitre — protocoles, adresses, # ports — exige qu'il reparte. # # On redemarre donc sur tout changement de `main.cf`. C'est plus large que le seul # `inet_protocols`, et c'est voulu : distinguer ligne par ligne ce qui se recharge de ce # qui se redemarre demanderait de tenir a jour une liste que Postfix ne publie pas. when: serveur_postfix_mode != "relais" - name: Déployer main.cf ansible.builtin.template: src: main.cf.j2 dest: /etc/postfix/main.cf owner: root group: root mode: "0644" notify: Redémarrer postfix - name: Activer la soumission :587 (clients authentifiés, SASL Dovecot distant) ansible.builtin.blockinfile: path: /etc/postfix/master.cf marker: "# {mark} SETOPS SUBMISSION 587" block: | submission inet n - y - - smtpd -o syslog_name=postfix/submission -o smtpd_tls_security_level=encrypt -o smtpd_sasl_auth_enable=yes -o smtpd_sasl_type=dovecot -o smtpd_sasl_path=inet:{{ serveur_postfix_sasl_hote }}:{{ serveur_postfix_sasl_port }} -o smtpd_sasl_security_options=noanonymous -o smtpd_client_restrictions=permit_sasl_authenticated,reject -o smtpd_relay_restrictions=permit_sasl_authenticated,reject when: serveur_postfix_submission_actif | bool notify: Redémarrer postfix - name: Valider la configuration Postfix ansible.builtin.command: postfix check changed_when: false when: not ansible_check_mode - name: Activer et démarrer Postfix when: not ansible_check_mode ansible.builtin.systemd: name: "{{ serveur_postfix_service }}" enabled: true state: started daemon_reload: true