--- # Recuperee UNE FOIS. Sans garde, chaque deploiement recontactait le serveur du # fournisseur : cinq cles x quatorze hotes = soixante-dix allers-retours externes pour # des cles deja installees, et autant d'occasions qu'un tiers lent fasse tomber le # deploiement. Arbitrage rendu le 2026-08-09 : une plateforme souveraine ne depend pas # de six serveurs etrangers pour redeployer ce qu'elle possede deja. # # CONSEQUENCE ASSUMEE : une rotation de cle amont n'est plus recuperee toute seule. Elle # ne passe pas inapercue pour autant — `apt` refuse alors le depot, bruyamment. Pour # forcer le rafraichissement : supprimer le fichier et rejouer le role. - name: Cette ressource est-elle deja recuperee ? (Telecharger le trousseau de cles I) ansible.builtin.stat: path: "/tmp/icinga-archive-keyring.deb" register: telecharger_le_trousseau_de_cles_icinga_present - name: Telecharger le trousseau de cles Icinga when: not telecharger_le_trousseau_de_cles_icinga_present.stat.exists ansible.builtin.get_url: url: "{{ serveur_icinga_keyring_url }}" dest: "/tmp/icinga-archive-keyring.deb" mode: "0644" - name: Installer le trousseau de cles Icinga ansible.builtin.apt: deb: "/tmp/icinga-archive-keyring.deb" state: present - name: Ajouter le depot apt Icinga ansible.builtin.apt_repository: repo: "{{ serveur_icinga_depot_source }}" filename: icinga state: present - name: Installer Icinga 2, Icinga DB et Redis dedie ansible.builtin.apt: name: "{{ serveur_icinga_paquets }}" state: present update_cache: true - name: Resoudre la base de donnees depuis le registre (role partage) ansible.builtin.include_role: name: resoudre_base vars: resoudre_base_groupe: "{{ serveur_icinga_groupe }}" - name: Adopter les facts de base pour Icinga ansible.builtin.set_fact: serveur_icinga_entree: "{{ resoudre_base_entree }}" serveur_icinga_db_password: "{{ resoudre_base_db_password }}" serveur_icinga_db_host: "{{ resoudre_base_db_host }}" no_log: true # --- Identite TLS de l'API (5665) --- # ON NE TOUCHE PAS A `NodeName` — et il n'y a rien a corriger ici. # # `icinga2 api setup` ECRIT lui-meme NodeName d'apres `hostname -f`, puis nomme ses # certificats d'apres lui. Tant que `/etc/hosts` mettait le nom COURT en premier, # `hostname -f` rendait « mon-01 » et le certificat devenait invérifiable en appelant par # le nom complet. On a longuement tente d'aligner NodeName a la main, avant et apres # `api setup` : efface a chaque fois. # # LA CAUSE ETAIT AILLEURS. Depuis que `hosts_statiques` place le FQDN en premier # (2026-08-13), `hostname -f` rend le nom complet et Icinga s'emet spontanement un # certificat CN et SAN = FQDN. Rien a forcer : il suffisait que la machine sache # comment elle s'appelle. - name: Configurer l'API Icinga 2 ansible.builtin.command: cmd: icinga2 api setup creates: /etc/icinga2/features-enabled/api.conf notify: Redemarrer icinga2 - name: Activer la fonctionnalite icingadb dans Icinga 2 ansible.builtin.command: cmd: icinga2 feature enable icingadb creates: /etc/icinga2/features-enabled/icingadb.conf notify: Redemarrer icinga2 - name: Activer et demarrer le Redis Icinga DB when: not ansible_check_mode ansible.builtin.systemd: name: "{{ serveur_icinga_service_redis }}" enabled: true state: started - name: Importer le schema Icinga DB dans PostgreSQL (une fois) ansible.builtin.shell: cmd: >- PGPASSWORD='{{ serveur_icinga_db_password }}' psql -h {{ serveur_icinga_db_host }} -U {{ serveur_icinga_entree.proprietaire }} -d {{ serveur_icinga_entree.base }} -f {{ serveur_icinga_schema }} && touch /etc/icingadb/.schema-imported creates: /etc/icingadb/.schema-imported no_log: true - name: Deployer la configuration Icinga DB ansible.builtin.template: src: config.yml.j2 dest: "{{ serveur_icinga_config }}" owner: root group: icingadb mode: "0640" no_log: true notify: Redemarrer icingadb # `icinga2 api setup` active la fonctionnalite EN MEME TEMPS qu'il pose les certificats, # et sa garde `creates:` la saute des que le fichier existe. Consequence mesuree le # 2026-08-12 : apres un nettoyage des certificats, l'API restait DESACTIVEE — icinga2 # demarrait, se declarait `active`, et n'ecoutait sur rien. Exiger l'activation # separement rend l'etat independant de l'ordre des nettoyages. - name: API — exiger que la fonctionnalite soit activee ansible.builtin.command: cmd: icinga2 feature enable api creates: /etc/icinga2/features-enabled/api.conf notify: Redemarrer icinga2 - name: API — durcir l'ApiListener (aucune config ni commande acceptee) ansible.builtin.template: src: api.conf.j2 dest: /etc/icinga2/features-available/api.conf owner: root group: nagios mode: "0640" notify: Redemarrer icinga2 # --- Supervision des sauvegardes --- # La liste des detenteurs d'etat appartient a `client_backup`. On la LIT chez lui plutot # que de la recopier : deux listes finissent toujours par diverger, et la divergence se # lirait « tout va bien » des deux cotes. - name: Lire la liste des detenteurs d'etat chez client_backup ansible.builtin.include_vars: file: "{{ role_path }}/../client_backup/vars/main.yml" name: _catalogue_sauvegarde - name: Adopter la liste des detenteurs d'etat ansible.builtin.set_fact: client_backup_groupes_etat: "{{ _catalogue_sauvegarde.client_backup_groupes_etat }}" - name: Exiger le secret d'API du depot (Vault) ansible.builtin.assert: that: - serveur_icinga_api_motdepasse | length > 0 - serveur_icinga_hote_sauvegarde | length > 0 fail_msg: >- vault_icinga_api_depot requis, et un hote du groupe `serveur_backup` doit exister : sans l'un ou l'autre, les sauvegardes ne seraient surveillees par personne. - name: Deployer le compte d'API du depot de sauvegarde ansible.builtin.template: src: setops-api-users.conf.j2 dest: "{{ serveur_icinga_api_conf }}" owner: root group: nagios mode: "0640" no_log: true notify: Redemarrer icinga2 - name: Deployer les objets de supervision des sauvegardes ansible.builtin.template: src: setops-sauvegardes.conf.j2 dest: "{{ serveur_icinga_setops_conf }}" owner: root group: nagios mode: "0640" notify: Redemarrer icinga2 - name: Valider la configuration Icinga 2 avant de la rendre vivante ansible.builtin.command: cmd: icinga2 daemon -C changed_when: false - name: Activer et demarrer Icinga 2 et Icinga DB when: not ansible_check_mode ansible.builtin.systemd: name: "{{ item }}" enabled: true state: started loop: - "{{ serveur_icinga_service_icinga2 }}" - "{{ serveur_icinga_service_icingadb }}" # --- Publier l'AC vers le depot de sauvegarde --- # Le depot rapporte l'etat des instantanes a cette API et doit VERIFIER le pair. Il lui # faut donc cette AC — mais lui est un SERVICE et nous une APPLICATION : il se deploie # AVANT nous, et exiger son attente inverserait le graphe des couches (refuse par P08 le # 2026-08-12). C'est donc a NOUS de la lui porter, une fois que `icinga2 api setup` l'a # creee. Sens correct : l'application rejoint le service, jamais l'inverse. - name: Publier l'AC d'Icinga vers le depot de sauvegarde when: groups['serveur_backup'] | default([]) | length > 0 ansible.builtin.slurp: src: "{{ serveur_icinga_ca }}" register: serveur_icinga_ca_contenu - name: Deposer l'AC sur le depot de sauvegarde when: groups['serveur_backup'] | default([]) | length > 0 ansible.builtin.copy: content: "{{ serveur_icinga_ca_contenu.content | b64decode }}" dest: "{{ serveur_icinga_ca_destination_depot }}" owner: root group: root mode: "0644" delegate_to: "{{ groups['serveur_backup'] | first }}"