gabarit recapture : copie de travail preparee, nettoyee, convertie

modeleChezlepro (99999) clone en modeleChezlepro-travail (99998). L'original
n'a pas ete touche.

Deux defauts de mon propre outillage, trouves en l'utilisant :
- l'inventaire d'un seul hote ne porte aucun group_vars, donc aucun utilisateur
  de connexion : Ansible tentait le compte local. MODELE_HOTE passe desormais
  ansible_user.
- les playbooks ciblent hosts: modeles_vm, et un inventaire d'un seul hote
  place la machine dans all. La commande etait juste et la cible introuvable
  (« skipping: no hosts matched »). J'avais verifie l'affichage, pas l'effet.
  Les trois acceptent maintenant cible_modele.

Le nettoyage vide /etc/resolv.conf (il portait l'identite du reseau de
fabrication) et supprime les CLES D HOTE SSH — le gabarit transportait une cle
privee. Sur que parce que cloud-init les recree au premier demarrage, verifie
avant de l'ecrire.

Reste a faire, et ce n'est pas a moi : basculer proxmox_clone_* sur le nouveau
une fois qu'une VM en sera nee et aura fonctionne.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Daniel Allaire 2026-08-09 11:29:51 -04:00
parent ff3ca3bf26
commit 3618dfc129
6 changed files with 80 additions and 10 deletions

View file

@ -1,5 +1,41 @@
# CHANGELOG — Set-OPS
## 2026-08-09 — Gabarit recapturé sur copie de travail, sans toucher à l'original
`modeleChezlepro` (99999) cloné en `modeleChezlepro-travail` (99998), préparé, vérifié,
nettoyé, converti. **L'original n'a pas été touché** — il reste le gabarit en service tant
que le nouveau n'a pas produit une VM qui fonctionne.
**Deux défauts de mon propre outillage, trouvés en l'utilisant pour de vrai** — et c'est
tout l'intérêt de s'en servir plutôt que de le déclarer prêt :
- l'inventaire d'un seul hôte (`-i "<ip>,"`) ne porte **aucun `group_vars`**, donc aucun
utilisateur de connexion : Ansible tentait le compte local de l'opérateur. `MODELE_HOTE`
passe maintenant `ansible_user` (défaut `ansible`, le `ciuser` du gabarit) ;
- les playbooks ciblent `hosts: modeles_vm`, et un inventaire d'un seul hôte place la
machine dans `all`**pas** dans ce groupe. La commande était juste et la cible
introuvable : « skipping: no hosts matched », qui n'est pas une erreur. J'avais vérifié
l'affichage de la commande, pas son effet. Les trois playbooks acceptent désormais
`cible_modele`.
**Le nettoyage a gagné deux choses :**
`/etc/resolv.conf` est vidé — il portait `search chezlepro.ca` et
`nameserver 192.168.12.254`, l'identité du réseau de fabrication.
Et les **clés d'hôte SSH** sont supprimées. Le gabarit transportait une clé **privée** :
quiconque détient l'image détient de quoi se faire passer pour une VM qui n'aurait pas
régénéré la sienne. La suppression n'est sûre que parce que cloud-init les recrée au
premier démarrage — vérifié avant de l'écrire : les hôtes de la flotte portent des
empreintes toutes différentes.
L'exploitant a par ailleurs retiré `mtu=9000` des deux gabarits — le réglage mort relevé
plus tôt, qui ne se propageait pas aux clones.
**Ce qui reste à faire, et qui n'est pas à moi** : faire pointer
`proxmox_clone_source_nom` / `proxmox_clone_vmid_modele` sur le nouveau, une fois qu'une VM
en sera née et aura fonctionné. Tant que ce n'est pas fait, rien n'a changé pour la flotte.
## 2026-08-09 — `modeles_vm` : trois commandes qui ne pouvaient rien faire
Le groupe était **toujours vide**, et rien ne le signalait. `instancier` l'émet comme

View file

@ -187,10 +187,10 @@ lint: ansible-runtime ## Passe ansible-lint sur tout le depot
syntaxe: syntaxe-modele syntaxe-verification-modele syntaxe-nettoyage syntaxe-verification-hote syntaxe-groupes syntaxe-proxmox ## Verifie la syntaxe de TOUS les playbooks (modele, hote, groupes, proxmox)
syntaxe-modele: ansible-runtime ## Verifie la syntaxe du playbook de preparation du gabarit dore
ansible-playbook -i $(INVENTAIRE_MODELE) $(PLAYBOOK_PREPARER_MODELE) --syntax-check
ansible-playbook -i $(INVENTAIRE_MODELE) $(UTILISATEUR_MODELE) $(PLAYBOOK_PREPARER_MODELE) --syntax-check
syntaxe-verification-modele: ansible-runtime ## Verifie la syntaxe du playbook de verification du gabarit
ansible-playbook -i $(INVENTAIRE_MODELE) $(PLAYBOOK_VERIFIER_MODELE) --syntax-check
ansible-playbook -i $(INVENTAIRE_MODELE) $(UTILISATEUR_MODELE) $(PLAYBOOK_VERIFIER_MODELE) --syntax-check
syntaxe-nettoyage: ansible-runtime ## Verifie la syntaxe du playbook de nettoyage du gabarit
ansible-playbook -i $(INVENTAIRE_MODELE) $(PLAYBOOK_NETTOYER_MODELE) --syntax-check
@ -842,10 +842,10 @@ inventaire-production: ## Affiche le graphe de l'inventaire de production
.PHONY: _verifier-acces-modele _verifier-privileges-modele preparer-modele verifier-modele nettoyer-modele
_verifier-acces-modele: ansible-runtime _modele-requis
ansible -i $(INVENTAIRE_MODELE) $(CIBLE_MODELE) -m ping -e ansible_become=false
ansible -i $(INVENTAIRE_MODELE) $(CIBLE_MODELE) $(UTILISATEUR_MODELE) -m ping -e ansible_become=false
_verifier-privileges-modele: ansible-runtime _modele-requis
ansible -i $(INVENTAIRE_MODELE) $(CIBLE_MODELE) -b -m command -a "whoami"
ansible -i $(INVENTAIRE_MODELE) $(CIBLE_MODELE) $(UTILISATEUR_MODELE) -b -m command -a "whoami"
# Le gabarit dore n'est PAS un hote du tenant : sa configuration Proxmox le place sur le
# reseau de fabrication (192.168.12.x), pas dans le supernet. `instancier` emet donc
@ -877,18 +877,24 @@ INVENTAIRE_MODELE = $(if $(MODELE_HOTE),"$(MODELE_HOTE)$(,)",$(INVENTAIRE_LAB))
# Cible : la machine designee, ou le groupe si l'inventaire en contient un.
CIBLE_MODELE = $(if $(MODELE_HOTE),$(MODELE_HOTE),$(GROUPE_MODELE))
# Un inventaire d'UN SEUL HOTE (`-i "<ip>,"`) ne porte aucun `group_vars` : il faut donc
# lui donner l'utilisateur de connexion, sinon Ansible tente le compte local de
# l'operateur. Defaut `ansible`, qui est le `ciuser` du gabarit.
MODELE_UTILISATEUR ?= ansible
UTILISATEUR_MODELE = $(if $(MODELE_HOTE),-e ansible_user=$(MODELE_UTILISATEUR) -e cible_modele=$(MODELE_HOTE),)
preparer-modele: ansible-runtime _modele-requis _verifier-acces-modele _verifier-privileges-modele ## Prepare le gabarit dore (VM de reference clonee pour chaque hote)
ansible-playbook -i $(INVENTAIRE_MODELE) $(PLAYBOOK_PREPARER_MODELE)
ansible-playbook -i $(INVENTAIRE_MODELE) $(UTILISATEUR_MODELE) $(PLAYBOOK_PREPARER_MODELE)
verifier-modele: ansible-runtime _modele-requis ## Verifie le gabarit dore
ansible-playbook -i $(INVENTAIRE_MODELE) $(PLAYBOOK_VERIFIER_MODELE)
ansible-playbook -i $(INVENTAIRE_MODELE) $(UTILISATEUR_MODELE) $(PLAYBOOK_VERIFIER_MODELE)
nettoyer-modele: ansible-runtime _modele-requis ## Nettoie le gabarit avant capture — exige CONFIRMER=true
@if [[ "$(CONFIRMER)" != "true" ]]; then \
printf '%s\n' 'Refus: relancer avec CONFIRMER=true pour le nettoyage final du modele.'; \
exit 2; \
fi
ansible-playbook -i $(INVENTAIRE_MODELE) $(PLAYBOOK_NETTOYER_MODELE) -e template_cleanup_confirm=true
ansible-playbook -i $(INVENTAIRE_MODELE) $(UTILISATEUR_MODELE) $(PLAYBOOK_NETTOYER_MODELE) -e template_cleanup_confirm=true
.PHONY: _verifier-acces-hote _verifier-privileges-hote _attendre-hote faits verifier-hote

View file

@ -1,6 +1,11 @@
---
- name: Nettoyage final avant conversion en template Proxmox
hosts: modeles_vm
# Le gabarit n'est pas un hote du tenant : son adresse vit sur le reseau de
# fabrication, donc il ne peut pas venir du plan et le groupe `modeles_vm` reste vide.
# `MODELE_HOTE` passe alors `cible_modele`, et l'inventaire d'un seul hote (`-i "<ip>,"`)
# place la machine dans `all` — PAS dans `modeles_vm`. Sans cette indirection, la
# commande etait juste et la cible introuvable : « skipping: no hosts matched ».
hosts: "{{ cible_modele | default('modeles_vm') }}"
become: true
gather_facts: true

View file

@ -1,6 +1,11 @@
---
- name: Préparer le template Debian 13 Proxmox
hosts: modeles_vm
# Le gabarit n'est pas un hote du tenant : son adresse vit sur le reseau de
# fabrication, donc il ne peut pas venir du plan et le groupe `modeles_vm` reste vide.
# `MODELE_HOTE` passe alors `cible_modele`, et l'inventaire d'un seul hote (`-i "<ip>,"`)
# place la machine dans `all` — PAS dans `modeles_vm`. Sans cette indirection, la
# commande etait juste et la cible introuvable : « skipping: no hosts matched ».
hosts: "{{ cible_modele | default('modeles_vm') }}"
become: true
gather_facts: true

View file

@ -1,6 +1,11 @@
---
- name: Vérifier le template Debian 13 Proxmox
hosts: modeles_vm
# Le gabarit n'est pas un hote du tenant : son adresse vit sur le reseau de
# fabrication, donc il ne peut pas venir du plan et le groupe `modeles_vm` reste vide.
# `MODELE_HOTE` passe alors `cible_modele`, et l'inventaire d'un seul hote (`-i "<ip>,"`)
# place la machine dans `all` — PAS dans `modeles_vm`. Sans cette indirection, la
# commande etait juste et la cible introuvable : « skipping: no hosts matched ».
hosts: "{{ cible_modele | default('modeles_vm') }}"
become: true
gather_facts: true

View file

@ -69,6 +69,19 @@
# (playbooks/groupes/serveur_debian.yml, avant le premier apt).
# Un gabarit ne transporte aucune identite de reseau.
# Un gabarit ne doit transporter AUCUNE cle privee. Sans ce nettoyage, l'image porte la
# cle d'hote SSH de la machine de fabrication : quiconque detient l'image detient de quoi
# se faire passer pour n'importe quelle VM qui n'aurait pas regenere la sienne.
#
# La regeneration est faite par cloud-init au premier demarrage (module `ssh`, qui
# recree les cles absentes) — verifie le 2026-08-09 : les hotes de la flotte portent des
# empreintes toutes differentes. C'est cette regeneration qui rend la suppression sure ;
# la desactiver rendrait les VM sans cle d'hote, donc sans sshd.
- name: Supprimer les cles d hote SSH (regenerees par cloud-init au premier demarrage)
ansible.builtin.shell:
cmd: rm -f /etc/ssh/ssh_host_*
removes: /etc/ssh/ssh_host_ed25519_key
- name: Supprimer les historiques shell
ansible.builtin.file:
path: "{{ item }}"