Set-OPS-Public/playbooks/groupes/serveur_debian.yml
Daniel Allaire c6a7150c60 les depots tiers passent par le cache, et le tenant n a plus le sien
Deux mouvements d une seule doctrine : le site fournit tout ce dont un
tenant a besoin pour venir au monde.

1. LES DEPOTS TIERS. Grafana, Icinga, Smallstep et Collabora ne publient
qu en HTTPS ; apt-cacher-ng ne relaie pas un tunnel, et le socle pose donc
Acquire::https::Proxy DIRECT. Chaque machine sortait elle-meme sur
Internet. Le cache declare desormais un Remap par fournisseur, et chaque
role demande en {{ ..._depot_schema }}:// - http des qu un cache est
declare, https sinon. Le TLS n est rompu nulle part : il est TERMINE au
cache, qui est notre machine, et l integrite vient des signatures.

  avant : 4 fournisseurs en HTTPS direct, 14 machines sortant seules
  apres : 0 source en HTTPS direct, 0 erreur apt sur 14 machines

Trois lecons. Le remap appartient au cache qui SORT : pose sur un cache
chaine, il tente le HTTPS a travers son amont et rend 503. apt_repository
AJOUTE au lieu de remplacer, donc l ancienne ligne https sortait toujours.
Et la liste des fournisseurs ne se devine pas - j en avais trois, l audit
en a revele un quatrieme.

2. LE CACHE DU TENANT. Sa ligne portait son propre retrait depuis toujours
- service MUTUALISABLE, un ecosysteme au premier age peut pointer sur celui
de son hote. Retiree. Ce qu on perd, dit franchement : plus de trafic
inter-zone et plus de charge sur site-cache-01, contre un service de moins
a poser, superviser et reproduire.

3. UN ROLE QU ON RETIRE DOIT DEFAIRE CE QU IL A FAIT. Le retrait a montre
que rien ne nettoie derriere. Le fichier apt visait un cache eteint en
ecrasant le plancher qui fonctionnait - le defaut deja paye a quinze
machines. Et les sondes du cache restaient, le porteur poussant pour des
services qu Icinga ne definit plus (404). Le socle retire le premier,
client_sante derive les sondes attendues et retire les orphelines.

P65 refuse tout role visant un depot relaye en https ecrit en dur. Sa
limite est dite : elle empeche une regression sur ce qui est connu, elle ne
decouvre pas l inconnu.

Mesure : Icinga 87 OK sur 96, prouver 65 OK, lint 0 defaut.

Reste, et c est dit : apt-cacher-ng tourne toujours sur forge-01 que plus
aucun plan ne declare.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-10 14:53:48 -04:00

177 lines
9.1 KiB
YAML

---
- name: Appliquer le groupe serveur_debian
hosts: serveur_debian
become: true
# Le verrou dpkg est tenu par les maj automatiques de Debian, par vagues, plusieurs
# minutes apres le premier demarrage. Pose ICI plutot que dans chaque role : toute
# tache apt du play en herite, y compris celles des roles inclus.
module_defaults:
ansible.builtin.apt:
lock_timeout: 300
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."
# Résolveur d'AMORÇAGE, posé avant `common_packages` — donc avant le premier `apt`.
# Sans lui, le déploiement échoue avant d'avoir commencé : le gabarit doré transporte
# un `/etc/resolv.conf` figé, et le `dns-nameservers` écrit par cloud-init reste sans
# effet faute de `resolvconf` (qu'on ne peut pas installer sans résolution — la boucle
# se referme). Mesuré le 2026-08-06 sur deux VM neuves.
#
# PASSAGE DE RELAIS : `client_resolveur` reprend ce fichier plus tard pour le basculer
# vers `127.0.0.1`. La garde ci-dessous le respecte — sans elle, chaque déploiement
# défairait la bascule, et deux rôles se disputeraient le même fichier sans fin.
# SOURCE D'ARTEFACTS D'AMORÇAGE, posée avant le premier `apt` — symétrique exacte du
# résolveur d'amorçage ci-dessous, et pour la même raison de fond : LA PREMIÈRE
# MACHINE D'UN ÉCOSYSTÈME N'A NI RÉSOLVEUR NI CACHE, ET C'EST ELLE QUI DOIT LES
# CONSTRUIRE.
#
# Mesuré le 2026-08-28 sur `ops-01`, première machine de la reconstruction de
# Chezlepro. Le socle restait bloqué sur son premier `apt update`, sans message qui
# parle de réseau :
#
# sortie Internet TCP 443 OK
# DNS UDP 53 -> 9.9.9.9 MUET
#
# Le DNS sortant est fermé PAR CONCEPTION — un tenant résout chez lui, son DNS ne
# traverse jamais la frontière. Or apt vise `deb.debian.org` PAR SON NOM, et le cache
# de l'écosystème n'existe pas encore.
#
# UN MANDATAIRE HTTP RÉSOUT CE QUE LE CLIENT NE PEUT PAS RÉSOUDRE : apt lui envoie
# l'URL absolue, et c'est LUI qui traduit le nom. La machine n'a donc besoin d'aucun
# DNS pour installer ses paquets — seulement d'une ADRESSE.
#
# C'EST DE LA FILIATION, PAS UNE RUSTINE (docs/filiation-emancipation.md). L'hébergeur
# nourrit la première machine de son locataire le temps que celui-ci monte son propre
# cache. L'emprunt est DÉCLARÉ — l'intrant nomme l'amont — et il s'efface de lui-même :
# `client_artefacts` écrit `00-setops-artefacts`, qui trie APRÈS ce fichier-ci, donc
# gagne dès que l'écosystème a sa propre source. Le plancher reste dessous, comme
# `/etc/hosts` reste sous le DNS.
#
# Aucun flux à ouvrir : `serveur_cache_site` accepte déjà le 3142 depuis
# `voisins_site`, qui résout les SUPERNETS des tenants — donc toute machine, pas
# seulement leur cache. Vérifié depuis `ops-01` : HTTP 200 en 0,158 s.
- name: Poser la source d'artefacts d'amorçage (avant tout apt)
ansible.builtin.copy:
dest: /etc/apt/apt.conf.d/00-setops-amorcage-artefacts
owner: root
group: root
mode: "0644"
content: |
// GÉNÉRÉ par Set-OPS (socle) — source d'artefacts d'AMORÇAGE, intrant
// `artefacts_amorcage`. Remplacé par `client_artefacts` (00-setops-artefacts,
// qui trie après) dès que l'écosystème a sa propre source.
//
// UNE ADRESSE, JAMAIS UN NOM : au moment où ce fichier sert, la machine n'a pas
// encore de résolveur, et le DNS sortant d'un tenant est fermé par conception.
Acquire::http::Proxy "http://{{ artefacts_amorcage }}";
// `DIRECT` est obligatoire : apt fait HÉRITER la valeur HTTPS de la valeur HTTP
// quand elle n'est pas définie, et enverrait les dépôts tiers en HTTPS dans un
// cache qui refuse les tunnels (mesuré le 2026-08-23).
Acquire::https::Proxy "DIRECT";
when:
- artefacts_amorcage is defined
- artefacts_amorcage | string | length > 0
# RETIRER CE QUI DESIGNE UN CACHE QUI N'EXISTE PLUS (2026-09-10).
#
# `client_artefacts` ecrit `00-setops-artefacts`, qui trie APRES le plancher et gagne.
# Quand l'ecosysteme cesse de declarer `serveur_artefacts` — parce qu'il s'en remet au
# cache du SITE — l'hote quitte le groupe, le role ne tourne plus, et PERSONNE ne
# retire son fichier. Il continuerait donc de viser un cache eteint, en ecrasant le
# plancher qui, lui, fonctionne.
#
# C'est le defaut deja paye : « quinze machines ont perdu apt d'un coup, et le
# deploiement ne pouvait plus atteindre la couche qui aurait repare le cache ». Un
# role qu'on retire doit pouvoir defaire ce qu'il a fait — ici, depuis le socle, qui
# est le seul a tourner dans les deux cas.
- name: Retirer la source d'artefacts de l'ecosysteme quand il n'en declare plus
ansible.builtin.file:
path: /etc/apt/apt.conf.d/00-setops-artefacts
state: absent
when: (groups['serveur_artefacts'] | default([])) | length == 0
- name: Lire le résolveur en place
ansible.builtin.slurp:
src: /etc/resolv.conf
register: serveur_debian_resolv_actuel
failed_when: false
changed_when: false
- name: Poser le résolveur d'amorçage (avant tout apt)
ansible.builtin.copy:
dest: /etc/resolv.conf
owner: root
group: root
mode: "0644"
content: |
# Géré par Set-OPS — résolveur d'amorçage (intrant `dns_amorcage`).
# Remplacé par `client_resolveur` lorsqu'il bascule vers le résolveur local.
{% for serveur in dns_amorcage.split(',') if serveur | trim %}
nameserver {{ serveur | trim }}
{% endfor %}
# L'AMORÇAGE NE DOIT PAS DÉFAIRE CE QUI EST DÉJÀ EN PLACE (2026-08-25).
#
# La garde ne protégeait que l'hôte du résolveur lui-même (`127.0.0.1`). Partout
# ailleurs, le socle réécrivait `/etc/resolv.conf` avec `dns_amorcage` — donc
# **défaisait la bascule** de `client_resolveur` à chaque passage.
#
# Ça ne s'était jamais vu chez un tenant : `dns_amorcage` y vaut l'adresse du
# résolveur du tenant, si bien que réécrire remettait la même valeur. La
# coïncidence masquait le défaut.
#
# Sur le site, les deux ont divergé quelques heures — l'amorçage pointait encore sur
# la frontière alors que `client_resolveur` avait basculé les machines sur
# `site-dns-01`. Chaque déploiement du socle les ramenait en arrière, en silence, et
# ça ne s'est vu qu'en retirant la règle de pare-feu vers la frontière : les cinq
# machines ont alors perdu la résolution d'un coup.
#
# On ne pose donc l'amorçage que si rien de sensé n'est déjà là : ni la loopback, ni
# un résolveur déclaré de cet écosystème.
vars:
serveur_debian_resolv_texte: >-
{{ serveur_debian_resolv_actuel.content | default('') | b64decode | string }}
serveur_debian_resolveurs_declares: >-
{{ (groups['serveur_resolveur'] | default([]))
| map('extract', hostvars, 'ansible_host') | select | list }}
when:
- dns_amorcage is defined
- dns_amorcage | string | length > 0
- "'127.0.0.1' not in serveur_debian_resolv_texte"
- serveur_debian_resolveurs_declares
| select('in', serveur_debian_resolv_texte) | list | length == 0
roles:
# LE PLANCHER AVANT LE PREMIER `apt` (2026-08-25).
#
# `hosts_statiques` venait APRÈS `common_packages`, qui commence par un `apt update`.
# Or apt vise le cache PAR SON NOM — `site-cache-01.<domaine>` — ce qui est voulu :
# une configuration agnostique de l'adressage.
#
# Le jour où les adresses changent, la boucle se referme : apt échoue faute de
# résoudre, donc le socle n'atteint jamais `hosts_statiques`, donc le plancher reste
# périmé, donc apt échoue. Mesuré le 2026-08-25 après le découpage du site en zones :
# cinq machines bloquées, `/etc/hosts` vide de toute entrée du site.
#
# Le résolveur d'amorçage est déjà une `pre_task` pour exactement cette raison. Le
# plancher est de la même nature : il ne s'installe pas, **il rend installable**.
- hosts_statiques
- common_packages
- qemu_guest_agent
# `cloud_init` N'EST PLUS APPLIQUE ICI (2026-09-09). Il reste au GABARIT, qui en a
# besoin : il est le seul chemin vers la premiere seconde d'un clone (P56). Mais sur
# une machine deja nee, le reinstaller n'a plus d'objet — et le durcissement le
# retire juste apres. Les garder tous les deux produisait un va-et-vient a chaque
# deploiement : le socle installe, le durcissement retire, deux `changed` par passage,
# et l'idempotence perdue. P63 garde les trois moities de cette decision.
- sudo_ansible
- chrony
- ssh_baseline
- systemd_ssh_auto
- motd