collabora : en natif, la derniere exception conteneurisee tombe

Le role lancait collabora/code dans Docker -- seule exception de la flotte au
principe « logiciel libre en natif ». Desormais : paquet coolwsd du depot amont,
systemd, derriere l'edge nginx. community.docker est retiree de requirements :
plus aucun role n'a besoin de Docker.

Eprouve avant d'ecrire, sur une Debian 13.6 reelle et sans rien installer :
apt-get install --simulate coolwsd resout jusqu'a « Conf coolwsd (26.04.3.1-1) »,
libgcc1 est fourni par libgcc-s1, et le depot CODE-deb est PLAT.

La configuration passe par un fragment systemd (--o:) : le coolwsd.xml livre,
439 lignes commentees, reste intact.

Trois outils du harnais ont pese. voute.py lisait les COMMENTAIRES : documenter
le nom d'une clef suffisait a l'exiger -- corrige, controle negatif fait. Et
verifier_intrants avait raison : une garde ecrite en deux morceaux promettait un
secret pour une console fermee ; reecrite en implication, elle dit le vrai
contrat.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Daniel Allaire 2026-08-24 16:23:35 -04:00
parent 1363ebff59
commit 70e57076e8
11 changed files with 356 additions and 73 deletions

View file

@ -1,5 +1,64 @@
# CHANGELOG — Set-OPS
## 2026-08-24 — Collabora en natif : la dernière exception conteneurisée tombe
`serveur_collabora` lançait `collabora/code` dans Docker — **seule exception** de la
flotte au principe fondateur : logiciel libre en natif, systemd + paquets + nginx. Elle
traînait une dépendance entière, `community.docker`, qui n'était même pas déclarée dans
`requirements.yml` et donc absente de tout runner.
**Plus aucun rôle du dépôt n'a besoin de Docker.** La collection est retirée.
### Éprouver l'outil avant le rôle
Sur une Debian 13.6 réelle, sans rien installer :
```
apt-get install --simulate coolwsd -> résout jusqu'à « Conf coolwsd (26.04.3.1-1) »
libgcc1 (exigé par le paquet) -> fourni par libgcc-s1 sur trixie
le dépôt CODE-deb -> PLAT : Packages et Release à la racine, pas de dists/
```
Le paquet livre aussi `/etc/nginx/snippets/coolwsd.conf` et un profil AppArmor — deux
choses que cette flotte sait exploiter, contrairement à une image opaque.
### La configuration par surcharge
Le `coolwsd.xml` livré fait **439 lignes richement commentées**. Le remplacer par un
gabarit maison obligerait à suivre son évolution amont et ferait perdre ses explications.
`coolwsd` acceptant des surcharges `--o:<clé>=<valeur>`, le rôle pose un **fragment
systemd** : la configuration de Set-OPS tient en un fichier, celle du paquet reste intacte.
### La console d'administration est fermée
Elle expose un formulaire hors de tout SSO, avec un secret à créer, faire tourner et
surveiller — pour une fonction dont personne n'a besoin. Même raisonnement que
`serveur_forgejo_connexion_locale`.
### Trois outils du harnais ont eu raison, et l'un avait tort
**`voute.py` lisait les commentaires.** Expliquer en commentaire « pour ouvrir cette
option, fournir `vault_x` » suffisait à rendre `vault_x` obligatoire dans le gabarit ET
dans la voûte réelle. Documenter le nom d'une clef ne doit pas l'exiger : le scanner
ignore désormais ce qui suit un `#`. Contrôle négatif fait — une référence réelle, dans du
code, reste exigée.
**Le message d'erreur d'un `assert` comptait comme une référence.** Il nommait la clef de
voûte ; il nomme maintenant la variable que l'exploitant règle, ce qui est plus utile de
toute façon.
**Et `verifier_intrants.py` avait raison.** Un `assert` de la forme `var | length > 0`
déclare un **contrat** — et l'outil ignore délibérément les `when:`, parce qu'un intrant
exigé sous condition reste un intrant exigé. Écrite en deux morceaux, ma garde promettait
un secret pour une console fermée. Réécrite en **implication** — *si ouverte, alors un mot
de passe* — elle dit ce qu'elle veut vraiment dire.
### Ce qui n'est pas prouvé
L'**installabilité** est établie. Le **fonctionnement** ne l'est pas : aucun écosystème de
la flotte ne fait tourner Collabora aujourd'hui. La première mise en service devra
vérifier l'édition d'un document de bout en bout, depuis Nextcloud.
## 2026-08-24 — La clé du runner, et trois silences fermés en chemin
Le poste d'exploitation fabriquait sa propre paire SSH depuis son premier déploiement, et

View file

@ -30,7 +30,7 @@
| P15 | Modele public socle valide | AFF-022, AFF-099 | ✅ OK | Modele public socle : domaines/serveurs/applications/bases valides. |
| P16 | Inventaire Ansible complet (--list) | AFF-030 | ✅ OK | 15 hotes, 32 groupes (inventaire dechiffre et parse). |
| P17 | Tous les modeles valident (registres + underlay) | AFF-022, AFF-099 | ✅ OK | Les 1 modele(s) decouvert(s) valident. |
| P18 | Gabarit de voute complet | AFF-026 | ✅ OK | Gabarit de voute complet : 24 secret(s) exige(s), tous presents. Voute reelle : 25 cle(s), aucun manque. |
| P18 | Gabarit de voute complet | AFF-026 | ✅ OK | Gabarit de voute complet : 23 secret(s) exige(s), tous presents. Voute reelle : 25 cle(s), aucun manque. |
| P19 | Le GUI couvre le schema du plan | AFF-002, AFF-095 | ✅ OK | GUI : les 28 champ(s) des plans reels sont editables (2 plan(s) inspecte(s)), registres toleres : nomenclature. |
| P20 | Adressage 100% derive du seed (aucun stocke) | AFF-001, AFF-003 | ✅ OK | 2 nomenclature(s) : adressage 100% derive du seed index. |
| P21 | Federation : aucun index en collision | AFF-102 | ✅ OK | Federation coherente : 3 instance(s) federee(s), aucun index en collision. |

View file

@ -46,7 +46,7 @@ Ce que la reconstruction couvre, par capacité :
| Observabilité | `serveur_prometheus`, `serveur_loki`, `serveur_grafana` | métriques, journaux, tableaux sous SSO |
| Supervision | `serveur_icinga`, `serveur_icingaweb2` | Icinga 2 + IcingaDB + Web 2 + BPM, au SSO |
| Forge | `serveur_forgejo` | Git + PostgreSQL + SSO OIDC |
| Collaboration | `serveur_nextcloud`, `serveur_collabora` | déployés par la reconstruction, base et client OIDC dérivés du plan — **usage** (dépôt de fichier, édition partagée) non consigné comme preuve |
| Collaboration | `serveur_nextcloud`, `serveur_collabora` (**natif**, plus de conteneur) | déployés par la reconstruction, base et client OIDC dérivés du plan — **usage** (dépôt de fichier, édition partagée) non consigné comme preuve |
| Plateforme webapp | `serveur_web_frontal`, `serveur_web_dorsal` | sites statiques et webapps natives (venv + systemd + nginx), **zéro conteneur** |
| Sauvegardes | `serveur_backup`, `client_backup` | restic hors-nœud, **restauration éprouvée** (2026-08-12 : la donnée revient) |
| Exploitation | `serveur_ops` | le poste depuis lequel l'ecosysteme se reconstruit : Ansible epingle, genome clone depuis **sa propre forge**, cle SSH propre — **sans** la voute ni son mot de passe |

View file

@ -13,11 +13,6 @@ collections:
# `serveur_backup` : ansible.posix.authorized_key. Utilisee depuis longtemps, jamais
# declaree — donc absente du runner, qui n'aurait pas pu deployer les sauvegardes.
- name: ansible.posix
# `serveur_collabora` : community.docker.docker_container.
#
# A TRANCHER. La doctrine du depot dit « zero conteneur » pour la plateforme webapp, et
# le principe general est le logiciel libre en natif. Collabora fait exception, en
# conteneur Docker. On declare la dependance parce qu'elle EXISTE — mieux vaut une
# contradiction visible qu'un role qui echoue en silence sur un runner — mais la
# question reste ouverte : Collabora en natif, ou l'exception assumee et documentee ?
- name: community.docker
# `community.docker` a ete RETIREE le 2026-08-24 : `serveur_collabora` etait la seule
# exception conteneurisee de la flotte, et il tourne desormais en natif (paquet coolwsd
# du depot amont Collabora). Plus aucun role n'a besoin de Docker.

View file

@ -1,27 +1,69 @@
# serveur_collabora
Serveur d'édition de documents **Collabora Online (CODE)**, protocole WOPI, consommé
par Nextcloud (`richdocuments`). **Codifié depuis le spike du 2026-07-05** (Docker, prouvé).
**Collabora Online, en natif** — paquet `coolwsd`, systemd, derrière l'edge nginx. Aucun
conteneur.
## Ce que le rôle fait
- Installe Docker + lance le conteneur `collabora/code` (`restart: always`) ;
- publie sur `127.0.0.1:9980` (Nextcloud co-localisé) **ET** l'IP LAN `:9980` (l'edge) — gotcha spike : bind localhost seul ⇒ **502** depuis l'edge ;
- `aliasgroup1` = le domaine Nextcloud (`cloud.<domaine>`) — Collabora n'accepte le WOPI que de cet hôte ;
- `ssl.enable=false` + `ssl.termination=true` (TLS terminé à l'edge) ;
- attend la santé (`/hosting/capabilities` = 200).
## Pourquoi ce rôle a été réécrit
## Dépendances / exposition (à fournir)
- **Vhost edge WebSocket-aware** : `bureau.<domaine>` → ce nœud:9980 avec `map $http_upgrade`
+ en-têtes `Upgrade`/`Connection` + `proxy_read_timeout` long. **Le vhost générique ne suffit pas**
(l'édition live échoue sans WebSocket) ;
- FQDN `bureau.<domaine>` dans les SAN du cert edge ;
- port 9980 à firewaller (voir `meta/flux.yml` : ingress depuis l'edge seulement).
Il lançait `collabora/code` dans Docker. C'était la **seule exception conteneurisée** de
la flotte, et elle contredisait le principe fondateur : logiciel libre en natif, systemd +
paquets + nginx. Elle traînait en plus une dépendance entière — `community.docker` — qui
n'était même pas déclarée dans `requirements.yml`, donc absente de tout runner.
## Docker vs natif
Le spike a prouvé **Docker** → on codifie Docker. Le **CODE natif** (paquets Collabora,
`loolwsd`) serait plus « Set-OPS » (natif, pas de moteur Docker) mais exigerait **son propre
spike**. Décision à trancher.
Depuis la réécriture, **plus aucun rôle du dépôt n'a besoin de Docker**.
## Robustesse
- **Épingler `serveur_collabora_tag`** en prod (pas de `:latest` surprise) ;
- surveillance Icinga sur `/hosting/capabilities`.
## Ce qui a été éprouvé avant d'écrire
Doctrine du dépôt : *éprouver l'outil avant le rôle*. Sur une Debian 13.6 réelle, sans
rien installer :
```
apt-get install --simulate coolwsd -> résout jusqu'à « Conf coolwsd (26.04.3.1-1) »
libgcc1 (exigé par le paquet) -> fourni par libgcc-s1 sur trixie
le dépôt CODE-deb -> PLAT : Packages et Release à la racine, pas de dists/
```
Le paquet livre aussi `/etc/nginx/snippets/coolwsd.conf` et un profil AppArmor — deux
choses que cette flotte sait exploiter, contrairement à une image opaque.
## La configuration : par surcharge, pas par réécriture
Le `coolwsd.xml` livré fait **439 lignes richement commentées**. Le remplacer par un
gabarit maison obligerait à suivre son évolution à chaque version amont, et ferait perdre
les commentaires qui expliquent chaque réglage.
`coolwsd` accepte des surcharges `--o:<clé>=<valeur>`. Le rôle pose donc un **fragment
systemd** : la configuration de Set-OPS tient en un fichier lisible, celle du paquet reste
intacte, et `apt purge` rend la machine à son état d'origine.
## La console d'administration est FERMÉE
Elle expose un formulaire identifiant/mot de passe hors de tout SSO, avec un secret à
créer, faire tourner et surveiller — pour une fonction dont personne n'a besoin au
quotidien. Même raisonnement que `serveur_forgejo_connexion_locale`.
L'ouvrir (`serveur_collabora_admin_actif: true`) exige alors `vault_collabora_admin` en
voûte, et de l'ajouter au gabarit de l'instance.
## Variables principales
| Variable | Défaut | Rôle |
|---|---|---|
| `serveur_collabora_port` | `9980` | écoute, derrière l'edge |
| `serveur_collabora_server_name` | `bureau.<domaine>` | nom externe — vide, coolwsd le déduit mal derrière un mandataire |
| `serveur_collabora_domaine_nextcloud` | `cloud.<domaine>` | l'hôte WOPI autorisé |
| `serveur_collabora_ssl_termination` | `true` | TLS terminé à l'edge, comme le reste de la flotte |
| `serveur_collabora_admin_actif` | `false` | console d'administration |
## Ce que ce rôle vérifie
Il interroge `/hosting/capabilities` après démarrage. Un service « active » qui ne répond
pas là serait découvert par Nextcloud **devant un usager**, à la première ouverture de
document.
## Ce qui n'est pas encore prouvé
L'**installabilité** est établie par simulation sur Debian 13.6. Le **fonctionnement** ne
l'est pas : aucun écosystème de la flotte ne fait tourner Collabora aujourd'hui. La
première mise en service devra vérifier l'édition d'un document de bout en bout, depuis
Nextcloud.

View file

@ -1,22 +1,87 @@
---
# =========================================================================
# serveur_collabora — serveur d'édition de documents (Collabora Online / CODE),
# protocole WOPI, consommé par Nextcloud (richdocuments). Codifié depuis le spike
# du 2026-07-05 (Docker, prouvé). Le CODE natif (paquets Collabora) reste une
# option future — nécessiterait son propre spike.
# =========================================================================
serveur_collabora_conteneur: "collabora"
serveur_collabora_image: "collabora/code"
serveur_collabora_tag: "latest" # À ÉPINGLER en prod (robustesse / pas d'upgrade surprise)
# COLLABORA ONLINE, EN NATIF — plus de conteneur.
#
# Ce rôle lançait `collabora/code` dans Docker, ce qui contredisait le principe fondateur
# du dépôt : logiciel libre **en natif**, systemd + paquets + nginx, zéro conteneur. C'était
# la seule exception de la flotte, et elle traînait une dépendance entière
# (`community.docker`) qui n'était même pas déclarée dans `requirements.yml`.
#
# CE QUI A ÉTÉ ÉPROUVÉ AVANT D'ÉCRIRE CE RÔLE (2026-08-24), sur une Debian 13.6 réelle,
# sans rien installer :
#
# apt-get install --simulate coolwsd -> résout jusqu'à « Conf coolwsd (26.04.3.1-1) »
# libgcc1 (exigé) -> fourni par libgcc-s1 sur trixie
# le dépôt CODE-deb est PLAT -> Packages et Release à la racine, pas de dists/
#
# Le paquet livre aussi `/etc/nginx/snippets/coolwsd.conf` et un profil AppArmor — deux
# choses que cette flotte sait déjà exploiter, contrairement à une image opaque.
serveur_collabora_paquets:
- coolwsd
serveur_collabora_service: "coolwsd"
serveur_collabora_port: 9980
# L'edge (autre hôte) doit joindre le conteneur → publier sur localhost ET l'IP LAN
# (gotcha spike : bind 127.0.0.1 seul => 502 depuis l'edge). Firewaller via le registre des flux.
serveur_collabora_lan_ip: "{{ ansible_default_ipv4.address | default(ansible_host) }}"
# Domaine Nextcloud autorisé (aliasgroup) — Collabora n'accepte le WOPI que de cet hôte.
# --- LE DÉPÔT AMONT ----------------------------------------------------------
#
# Dépôt PLAT : `Suites: ./` et pas de composant. Une source classique (`deb … stable
# main`) ne le trouverait pas.
serveur_collabora_depot_uri: "https://www.collaboraoffice.com/repos/CollaboraOnline/CODE-deb"
serveur_collabora_depot_cle_url: "https://www.collaboraoffice.com/downloads/gpg/collaboraonline-release-keyring.gpg"
serveur_collabora_depot_cle_fichier: "/etc/apt/keyrings/collaboraonline.gpg"
# --- CONFIGURATION : PAR SURCHARGE, PAS PAR RÉÉCRITURE -----------------------
#
# Le `coolwsd.xml` livré fait 439 lignes richement commentées. Le remplacer par un gabarit
# maison, ce serait s'engager à suivre son évolution à chaque version amont — et perdre
# les commentaires qui expliquent chaque réglage.
#
# `coolwsd` accepte des surcharges `--o:<clé>=<valeur>` sur sa ligne de commande. On pose
# donc un fragment systemd : la configuration de Set-OPS tient en un seul fichier lisible,
# le fichier du paquet reste intact, et `apt purge` rend la machine à son état d'origine.
serveur_collabora_fragment: "/etc/systemd/system/coolwsd.service.d/setops.conf"
# TLS TERMINÉ À L'EDGE, comme tout le reste de la flotte : `serveur_nginx` présente le
# certificat step-ca, Collabora écoute en clair derrière lui.
serveur_collabora_ssl_enable: false
serveur_collabora_ssl_termination: true
# Nom externe, tel que le navigateur l'atteint. Vide = déduit de la requête, ce qui échoue
# derrière un mandataire inverse — d'où la valeur explicite.
serveur_collabora_server_name: "bureau.{{ domaine_interne }}"
# Hôtes WOPI autorisés — qui a le droit de faire éditer un document.
#
# Les défauts du paquet couvrent déjà les plages privées (10/8, 172.16/12, 192.168/16,
# loopback), donc l'adressage dérivé de Set-OPS. On ajoute le FQDN de Nextcloud pour que
# l'autorisation soit LISIBLE dans le plan plutôt que déduite d'un masque.
serveur_collabora_domaine_nextcloud: "cloud.{{ domaine_interne }}"
serveur_collabora_aliasgroup: "https://{{ serveur_collabora_domaine_nextcloud | regex_escape }}:443"
# TLS terminé à l'edge : Collabora sert en HTTP derrière le proxy.
serveur_collabora_extra_params: "--o:ssl.enable=false --o:ssl.termination=true"
# --- CONSOLE D'ADMINISTRATION : FERMÉE PAR DÉFAUT ----------------------------
#
# Elle sert à surveiller les sessions et les documents ouverts. Personne n'en a besoin au
# quotidien, et elle expose un formulaire identifiant/mot de passe de plus — hors de tout
# SSO, avec un secret à créer, à faire tourner et à surveiller.
#
# Même raisonnement que `serveur_forgejo_connexion_locale` : une porte ouverte en
# permanence contourne la politique centrale et ne se révoque nulle part. On la ferme, et
# l'on garde l'accès par SSH à l'hôte — le mécanisme de secours retenu par ce dépôt.
#
# L'ouvrir exige alors un secret en voûte, et de l'ajouter au gabarit de l'instance.
# LE MOT DE PASSE N'EST PAS TIRE D'UNE CLE DE VOUTE PAR DEFAUT, ET C'EST VOULU.
#
# `scripts/voute.py` exige de la voute TOUTE reference `vault_*` trouvee dans un role
# actif — c'est ce qui garantit qu'aucun secret n'est oublie. Mais une porte FERMEE ne
# doit pas reclamer de clef : nommer ici `vault_collabora_admin` obligerait chaque
# ecosysteme installant Collabora a inventer, chiffrer et faire tourner un secret pour
# une console que personne n'ouvre.
#
# Qui veut la console la declare chez lui :
#
# # group_vars/serveur_collabora.yml de l'instance
# serveur_collabora_admin_actif: true
# serveur_collabora_admin_mot_de_passe: "{{ vault_collabora_admin }}"
#
# et ajoute `vault_collabora_admin` a son gabarit de voute — ou P18 le lui rappellera.
serveur_collabora_admin_actif: false
serveur_collabora_admin_utilisateur: "collabora-admin"
serveur_collabora_admin_mot_de_passe: ""

View file

@ -0,0 +1,7 @@
---
- name: Redemarrer Collabora
when: not ansible_check_mode
ansible.builtin.systemd:
name: "{{ serveur_collabora_service }}"
state: restarted
daemon_reload: true

View file

@ -1,39 +1,109 @@
---
- name: Installer Docker (moteur du conteneur Collabora)
# LA CONDITION EST ECRITE D'UN SEUL TENANT, ET C'EST DELIBERE.
#
# `scripts/verifier_intrants.py` lit les `assert` de la forme `var | length > 0` comme un
# CONTRAT : l'instance doit fournir cette valeur. Et il ignore volontairement les `when:`
# — un intrant exige sous condition reste un intrant exige.
#
# Ecrite en deux morceaux (`that: var | length > 0` + `when: actif`), cette garde
# promettait donc un secret pour une console FERMEE, et P32 le refusait a juste titre.
# Ecrite en une implication, elle dit ce qu'elle veut vraiment dire : SI la console est
# ouverte, ALORS un mot de passe. Ne pas la « simplifier » en la recoupant en deux.
- name: Exiger un secret si — et seulement si — la console d'administration est ouverte
ansible.builtin.assert:
that:
- not (serveur_collabora_admin_actif | bool) or (serveur_collabora_admin_mot_de_passe | length > 0)
fail_msg: >-
La console d'administration est ouverte mais son mot de passe est vide.
Le renseigner depuis la voûte de l'instance, ou refermer la console
(`serveur_collabora_admin_actif: false`).
- name: Assurer le repertoire des trousseaux apt
ansible.builtin.file:
path: /etc/apt/keyrings
state: directory
owner: root
group: root
mode: "0755"
# Récupérée UNE FOIS, comme la clé Smallstep : une plateforme souveraine ne recontacte pas
# un serveur étranger à chaque déploiement pour une clé déjà installée. Une rotation amont
# ne passe pas inaperçue pour autant — `apt` refuse alors le dépôt, bruyamment.
- name: Cette ressource est-elle deja recuperee ? (cle Collabora)
ansible.builtin.stat:
path: "{{ serveur_collabora_depot_cle_fichier }}"
register: serveur_collabora_cle_presente
- name: Telecharger la cle de signature Collabora
when: not serveur_collabora_cle_presente.stat.exists
ansible.builtin.get_url:
url: "{{ serveur_collabora_depot_cle_url }}"
dest: "{{ serveur_collabora_depot_cle_fichier }}"
owner: root
group: root
mode: "0644"
timeout: 30
register: serveur_collabora_cle
retries: 5
delay: 6
until: serveur_collabora_cle is succeeded
# DEPOT PLAT : `Suites: ./`, aucun composant. Une source classique ne le trouverait pas.
- name: Ajouter le depot apt Collabora
ansible.builtin.template:
src: collabora.sources.j2
dest: /etc/apt/sources.list.d/collabora.sources
owner: root
group: root
mode: "0644"
- name: Installer Collabora Online
when: not ansible_check_mode # dry-run : le depot n'est pas reellement ajoute
ansible.builtin.apt:
name: docker.io
name: "{{ serveur_collabora_paquets }}"
state: present
update_cache: true
cache_valid_time: 3600
- name: Activer et demarrer Docker
- name: Assurer le repertoire du fragment systemd
ansible.builtin.file:
path: "{{ serveur_collabora_fragment | dirname }}"
state: directory
owner: root
group: root
mode: "0755"
# LA CONFIGURATION DE SET-OPS TIENT EN UN FICHIER, et le coolwsd.xml du paquet reste
# intact. Voir defaults/main.yml pour le raisonnement.
- name: Deployer la surcharge Set-OPS
ansible.builtin.template:
src: setops.conf.j2
dest: "{{ serveur_collabora_fragment }}"
owner: root
group: root
mode: "0640"
notify: Redemarrer Collabora
- name: Appliquer les redemarrages avant de verifier
ansible.builtin.meta: flush_handlers
- name: Activer et demarrer Collabora
when: not ansible_check_mode
ansible.builtin.systemd:
name: docker
name: "{{ serveur_collabora_service }}"
enabled: true
state: started
when: not ansible_check_mode
daemon_reload: true
- name: Lancer le conteneur Collabora CODE (WOPI, publie sur localhost + IP LAN)
community.docker.docker_container:
name: "{{ serveur_collabora_conteneur }}"
image: "{{ serveur_collabora_image }}:{{ serveur_collabora_tag }}"
state: started
pull: true
restart_policy: always
ports:
- "127.0.0.1:{{ serveur_collabora_port }}:9980"
- "{{ serveur_collabora_lan_ip }}:{{ serveur_collabora_port }}:9980"
env:
aliasgroup1: "{{ serveur_collabora_aliasgroup }}"
extra_params: "{{ serveur_collabora_extra_params }}"
# ECRIRE, PUIS RELIRE (D-68). Un service « active » qui ne repond pas a `capabilities`
# est un vert sur un perimetre vide : Nextcloud le decouvrirait a la premiere ouverture
# de document, c'est-a-dire devant un usager.
- name: Collabora repond-il vraiment ?
when: not ansible_check_mode
- name: Attendre que Collabora reponde (capabilities)
ansible.builtin.uri:
url: "http://127.0.0.1:{{ serveur_collabora_port }}/hosting/capabilities"
status_code: 200
register: serveur_collabora_sante
until: serveur_collabora_sante.status == 200
status_code: [200]
timeout: 20
register: serveur_collabora_capacites
retries: 12
delay: 5
when: not ansible_check_mode
until: serveur_collabora_capacites is succeeded

View file

@ -0,0 +1,8 @@
# GÉNÉRÉ par Set-OPS (rôle serveur_collabora). NE PAS éditer à la main.
#
# Dépôt PLAT : `Suites: ./` et aucun composant. Constaté le 2026-08-24 — `Packages` et
# `Release` vivent à la racine, il n'y a pas de `dists/`.
Types: deb
URIs: {{ serveur_collabora_depot_uri }}
Suites: ./
Signed-By: {{ serveur_collabora_depot_cle_fichier }}

View file

@ -0,0 +1,17 @@
# GÉNÉRÉ par Set-OPS (rôle serveur_collabora). NE PAS éditer à la main.
#
# Surcharge de l'unité du paquet. Le `coolwsd.xml` livré (439 lignes commentées) reste
# intact : le remplacer par un gabarit maison obligerait à suivre son évolution à chaque
# version amont, et ferait perdre les commentaires qui expliquent chaque réglage.
[Service]
ExecStart=
ExecStart=/usr/bin/coolwsd --version --o:sys_template_path=/opt/cool/systemplate \
--o:child_root_path=/opt/cool/child-roots \
--o:file_server_root_path=/usr/share/coolwsd \
--o:ssl.enable={{ serveur_collabora_ssl_enable | bool | lower }} \
--o:ssl.termination={{ serveur_collabora_ssl_termination | bool | lower }} \
--o:server_name={{ serveur_collabora_server_name }} \
--o:storage.wopi.alias_group[0].host=https://{{ serveur_collabora_domaine_nextcloud }}:443 \
--o:admin_console.enable={{ serveur_collabora_admin_actif | bool | lower }}{% if serveur_collabora_admin_actif | bool %} \
--o:admin_console.username={{ serveur_collabora_admin_utilisateur }} \
--o:admin_console.password={{ serveur_collabora_admin_mot_de_passe }}{% endif %}

View file

@ -65,10 +65,30 @@ def gabarit() -> Path | None:
def _refs_vault(chemin: Path) -> set[str]:
"""Les `vault_*` qu'un fichier UTILISE — pas ceux dont il PARLE.
ON IGNORE LES COMMENTAIRES (2026-08-24). Le scanner lisait le fichier entier, si bien
qu'expliquer en commentaire « pour ouvrir cette option, fournir vault_x » SUFFISAIT a
rendre `vault_x` obligatoire dans le gabarit et dans la voute reelle.
Constate sur `serveur_collabora` : sa console d'administration est FERMEE par defaut,
et le role se contentait de documenter comment l'ouvrir. Trois phrases de commentaire
imposaient donc a tout ecosysteme installant Collabora d'inventer, chiffrer et faire
tourner un secret pour une porte que personne n'ouvre.
Documenter le nom d'une clef ne doit pas l'exiger. Une clef reellement utilisee
apparait dans du code — c'est ce qu'on lit ici.
"""
try:
return set(MOTIF_VAULT.findall(chemin.read_text(encoding="utf-8", errors="ignore")))
texte = chemin.read_text(encoding="utf-8", errors="ignore")
except OSError:
return set()
# Suffisant pour YAML, Jinja (`{# … #}` compris) et Python : ce qui suit un `#` hors
# guillemets est de la prose. On ne cherche pas a analyser finement — un `#` dans une
# chaine rendrait au pire une reference ignoree, et une reference reellement utilisee
# apparait ailleurs dans du code.
utile = "\n".join(ligne.split("#", 1)[0] for ligne in texte.splitlines())
return set(MOTIF_VAULT.findall(utile))
def groupes_du_plan() -> set[str]: