diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a2ff69..4b4e333 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,85 @@ # CHANGELOG — Set-OPS +## 2026-09-14 (22) — L'edge du site est debout, et quatre replis silencieux l'ont retarde + +`site-edge-01` est nee, deployee, et sert `forge`, `observatoire` et `vigie` en 443. Le +chemin jusque-la a traverse quatre defauts qui ont tous la MEME forme : un repli qui rend +un succes au lieu d'un refus. + +### 1. Le gabarit dore porte une adresse d'avant le renumerotage + + Failed to update apt cache after 5 retries + Acquire::http::Proxy "http://10.0.33.21:3142" + +Le fichier le dit lui-meme : *« Gere par Set-OPS pendant la FABRICATION DU GABARIT »*, +date du 2026-09-01, avec l'ancienne adresse du cache. Le socle ne le remplace que +`when artefacts_amorcage is defined` — et `site_inventaire.py` derivait `dns_amorcage` +sans deriver son JUMEAU. Les machines nees AVANT le renumerotage n'ont rien vu : +l'adresse etait juste, puis `client_artefacts` a pose un fichier qui trie apres. + +**La premiere machine neuve du site l'a revele.** Le site fournissait deja cette valeur a +ses locataires (`site_intrants.py`) ; il ne se la donnait pas a lui-meme. + +### 2. Une table de pattes tenue a la main, et un repli qui deplace au lieu d'omettre + +Le devis rendait « rien a faire », et le cache restait injoignable. `opnsense_if_zones` +associe chaque zone du site a sa patte de frontiere ; `site-publication` n'y etait pas, et +`_if_de()` retombe alors sur l'ANCIENNE PATTE PLATE. Les 20 regles de l'edge etaient +posees sur `vlan030` — syntaxiquement correctes, jamais rencontrees, puisque le trafic de +l'edge entre par `vlan037`. + +Le fichier documentait deja un incident identique, un mois plus tot, pour la patte de la +fabric : *« La regle etait syntaxiquement correcte et ne correspondait jamais. »* Ajoutee, +le devis a rendu **20 a creer, 20 a retirer** — le meme jeu de regles qui change de patte. + +### 3. Un registre facultatif qui faisait echouer un role + +`serveur_nginx` chargeait `applications.yml` ET `domaines.yml` sans condition. Un SITE ne +publie rien a l'Internet : son plan n'a pas le second. + + Could not find or access '.../SITE-Chezlepro/plan/domaines.yml' + +Le role releve desormais ce qui EXISTE avant de charger. Un registre absent laisse +`domaines_publics` indefini, et le filtre le traite deja comme vide. + +### 4. Le vhost genere faisait 43 octets, et le deploiement etait vert + +C'est le plus retors des quatre. `expositions_des_applications` resout, pour chaque nom +expose, l'edge de son domaine PARENT — et sans registre, retombe sur **le groupe de +l'application elle-meme** (`serveur_grafana`, `serveur_icingaweb2`). Jamais +`serveur_nginx`. Aucune exposition n'etait donc retenue, le fichier ne contenait que son +en-tete, et rien n'echouait. + +*Une derivation qui ne trouve rien ne se distingue pas d'une derivation qui n'a rien a +trouver.* Le site declare donc `plan/domaines.yml` : `genese.internal`, autorite +`auto-heberge`, edge `serveur_nginx`, sans DNSSEC — le TLD `internal.` est nie par la +racine signee, signer sous une chaine rompue ajoute du travail sans ajouter de preuve. + +Et `grafana` n'avait pas de `port:` : le vhost le disait dans son propre en-tete — *« une +application sans hote actif, ou sans port, est listee mais NON publiee »*. + +### Etat + + site-edge-01 10.37.37.11 deployee (174 taches, 66 changements) + nginx ecoute 80 et 443 + vhosts forge -> 10.37.33.11:443 + observatoire -> 10.37.36.11:3000 + vigie -> 10.37.36.11:8080 + frontiere 274 regles, devis muet + +### Ce qui reste, et c'est precis + +**Le certificat de l'edge ne porte encore que `site-edge-01.genese.internal`.** Il a ete +emis avant que les expositions existent, et `client_pki` rend `changed=0` : il ne compare +pas son jeu de SAN a celui qu'il derive maintenant. Tant que ce n'est pas fait, les trois +noms repondent sur un certificat qui ne les couvre pas. + +`forge` relaie par ailleurs en `http://10.37.33.11:443` — du clair vers un port TLS, d'ou +son `400`. L'amont d'une exposition deja servie en TLS doit etre `https://`. + +Deux corrections a faire, et aucune n'est une surprise : ce sont les deux dernieres +jointures entre le plan et ce que l'edge en tire. + ## 2026-09-14 (21) — Le site gagne un edge, et P23 a nomme le geste qui manque Le site servait trois applications web sans jamais les PUBLIER. L'observatoire, la vigie diff --git a/roles/serveur_nginx/tasks/main.yml b/roles/serveur_nginx/tasks/main.yml index ad4d340..67cbe4d 100644 --- a/roles/serveur_nginx/tasks/main.yml +++ b/roles/serveur_nginx/tasks/main.yml @@ -55,14 +55,41 @@ notify: Valider et recharger nginx # --- Vhosts derives des applications (champ expose) + domaines (edge) --- -- name: Charger les registres applications et domaines - ansible.builtin.include_vars: - file: "{{ item }}" +# LE REGISTRE DES DOMAINES PUBLICS EST FACULTATIF, ET IL A FALLU UN SITE POUR LE VOIR. +# +# `applications.yml` existe dans tout plan ; `domaines.yml` ne recense que les noms +# PUBLICS — ceux qu'un tenant publie a l'Internet. Un SITE n'en publie aucun : ses trois +# services web sont internes, et son plan n'a pas ce fichier. +# +# `include_vars` echouait alors sur le fichier absent, et l'edge du site ne se deployait +# pas : +# +# Could not find or access '.../SITE-Chezlepro/plan/domaines.yml' +# +# On releve donc d'abord ce qui EXISTE, puis on charge. Un registre absent laisse +# `domaines_publics` indefini, et `expositions_des_applications` le traite deja comme +# vide — la suite du role n'a pas besoin d'etre touchee. +- name: Quels registres du plan existent vraiment ? + ansible.builtin.stat: + path: "{{ item }}" loop: - "{{ setops_plan_dir }}/applications.yml" - "{{ setops_plan_dir }}/domaines.yml" + delegate_to: localhost + become: false + register: serveur_nginx_registres when: serveur_nginx_publier_expositions | bool +- name: Charger les registres applications et domaines + ansible.builtin.include_vars: + file: "{{ item.item }}" + loop: "{{ serveur_nginx_registres.results | default([]) }}" + loop_control: + label: "{{ item.item | basename }}" + when: + - serveur_nginx_publier_expositions | bool + - item.stat.exists | default(false) + - name: Lister les expositions destinees a cet edge ansible.builtin.set_fact: serveur_nginx_expositions: >- diff --git a/scripts/site_inventaire.py b/scripts/site_inventaire.py index 6a7dc5c..710a116 100755 --- a/scripts/site_inventaire.py +++ b/scripts/site_inventaire.py @@ -304,6 +304,29 @@ def inventaire() -> dict: communes["dns_amorcage"] = _resolveur if _cache_site: communes["setops_depot_binaires"] = f"http://{_cache_site}:3142/setops-binaires" + # L'AMORCAGE APT DES MACHINES DU SITE LUI-MEME (2026-09-14). + # + # `dns_amorcage` etait derive juste au-dessus ; son jumeau ne l'etait pas. Le + # socle n'ecrit `00-setops-amorcage-artefacts` que `when artefacts_amorcage is + # defined` — jamais, donc, pour une machine du site. Le fichier du GABARIT + # survivait alors intact. + # + # CE QUE CA A COUTE, mesure le 2026-09-14 sur `site-edge-01`, premiere machine + # du site creee depuis le renumerotage : + # + # Failed to update apt cache after 5 retries + # Acquire::http::Proxy "http://10.0.33.21:3142" <- adresse d'AVANT + # + # Le gabarit porte cette ligne depuis sa fabrication, le 2026-09-01. Les machines + # nees AVANT le renumerotage n'ont rien vu : l'adresse etait juste, puis + # `client_artefacts` a pose un fichier qui trie APRES et l'a emporte. Une machine + # NEUVE, elle, doit faire son premier `apt update` avec le seul fichier du + # gabarit — et il ment. + # + # LE SITE FOURNIT DEJA CETTE VALEUR A SES LOCATAIRES (`site_intrants.py`). Il ne + # se la donnait pas a lui-meme. C'est encore « le site revele ce que le tenant + # cache », a l'envers : ce que l'hebergeur pretait sans l'appliquer chez lui. + communes["artefacts_amorcage"] = f"{_cache_site}:3142" for cle in ("domaine_interne", "organisation", "dns_amorcage"): if intrants.get(cle): communes[cle] = str(intrants[cle])