diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e3b71d..a74eef1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,49 @@ # CHANGELOG — Set-OPS +## 2026-10-04 (68) — Forgejo 16.0.5 et Nextcloud 34.0.4 ; Nextcloud apprend à monter, et vérifie sa signature + +**Demande de l'exploitant** : poursuivre le relevé des logiciels en retard (Forgejo 16.0.2, +Nextcloud 34.0.2). La frontière (OPNsense 26.7.4_1 -> 26.7.5), l'exploitant s'en charge par +son interface. + +**Forgejo savait monter** : binaire par version (`forgejo-`), lien vers la +courante, redémarrage au changement de lien, signature vérifiée. Seule la SIMULATION d'une +montée échouait — le lien vers un binaire pas encore copié. Corrigé (lien sauté en +simulation tant que le binaire n'est pas là). 16.0.5 vérifiée contre la clé épinglée +(`EB114F5E…`), dépôt du site garni, appliquée au site : API en 16.0.5, la forge sert le +génome (`make genome-etat`). + +**Nextcloud ne savait pas monter** — même défaut que Keycloak (67) : `creates: occ`, le code +restait celui de la version installée quelle que soit la version demandée. Et chez nous, +`data/` vit DANS le code. **Fait** : `tasks/monter.yml`, la mise à jour manuelle documentée +par Nextcloud — maintenance ; ancien code mis de côté sous `-` ; nouvelle +version extraite ; on y ramène `data/` (déplacée, pas copiée), la configuration, et tout ce +que la livraison n'apporte pas (à la racine, dans `apps/`, dans `themes/`) ; `occ upgrade` ; +php-fpm rechargé (cache d'opcodes revalidé toutes les 60 s) ; fin de maintenance. Refus d'une +rétrogradation et d'un saut de branche. En cas d'échec, le rôle dit comment revenir. La +reprise a été éprouvée sur des arborescences factices avant d'écrire : livré gardé neuf, +manquant repris, `config.php` et `data/` intacts. + +**Nextcloud installait sans vérifier.** Signature PGP vérifiée désormais +(`scripts/verifier_signature.py`, comme Keycloak et Forgejo) ; clé dans +`files/nextcloud-release.asc`, empreinte `28806A87…937A` (« Nextcloud Security »). Ancrage +relevé et sa réserve écrite dans le rôle : clé servie par nextcloud.com, identifiant publié +sur nextcloud.com/security, même clé sur keys.openpgp.org mais sans adresse vérifiée — toutes +sources de la même organisation. Le dépôt du site sert aussi la signature. + +**Appliqué chez les deux locataires**, chacun précédé d'une sauvegarde fraîche (fichiers et +base) : 34.0.2 -> 34.0.4, repris `alliance-logo.svg`, `apps/richdocuments`, `apps/user_oidc`, +`themes/alliance`. Relu chez chacun : `status.php` en 34.0.4 par l'edge, pas de maintenance ni +de mise à jour de base en attente, Collabora et OIDC actifs, thème en place, données dans le +nouveau code, `bureau` (Collabora) répond. Seule erreur : « Failed to connect to the app +store » pendant `occ upgrade` — `collab-01` n'a pas de sortie Internet, par conception. + +**À décider par l'exploitant** : les anciens codes (`/var/www/nextcloud-34.0.2`, ~950 Mo +chacun) restent pour le retour arrière ; les retirer une fois la version éprouvée. + +**Validation** : `ansible-lint` (0 violation), `make verifier` conforme (83/83), simulations +au site et chez les deux locataires. + ## 2026-10-03 (67) — Keycloak 26.7.5 et oauth2-proxy v7.15.5 ; deux montées qui n'auraient rien monté **Demande de l'exploitant** : mettre à jour Keycloak et oauth2-proxy, premiers du relevé des diff --git a/roles/serveur_artefacts/defaults/main.yml b/roles/serveur_artefacts/defaults/main.yml index daba60f..f31112d 100644 --- a/roles/serveur_artefacts/defaults/main.yml +++ b/roles/serveur_artefacts/defaults/main.yml @@ -172,5 +172,7 @@ serveur_artefacts_directs: url: "{{ serveur_keycloak_signature_url }}" - nom: "nextcloud-{{ serveur_nextcloud_version }}.tar.bz2" url: "{{ serveur_nextcloud_url }}" + - nom: "nextcloud-{{ serveur_nextcloud_version }}.tar.bz2.asc" + url: "{{ serveur_nextcloud_signature_url }}" - nom: "oauth2-proxy-{{ serveur_oauth2_proxy_version }}.tar.gz" url: "{{ serveur_oauth2_proxy_url }}" diff --git a/roles/serveur_forgejo/defaults/main.yml b/roles/serveur_forgejo/defaults/main.yml index 15cc009..b7476ea 100644 --- a/roles/serveur_forgejo/defaults/main.yml +++ b/roles/serveur_forgejo/defaults/main.yml @@ -1,6 +1,6 @@ --- # Version Forgejo : verifier/ajuster sur https://forgejo.org/download/ -serveur_forgejo_version: "16.0.2" +serveur_forgejo_version: "16.0.5" # 2026-10-03 : trois corrections apres 16.0.2, meme branche serveur_forgejo_url: >- https://codeberg.org/forgejo/forgejo/releases/download/v{{ serveur_forgejo_version }}/forgejo-{{ serveur_forgejo_version }}-linux-amd64 diff --git a/roles/serveur_forgejo/tasks/main.yml b/roles/serveur_forgejo/tasks/main.yml index fe65734..55a96af 100644 --- a/roles/serveur_forgejo/tasks/main.yml +++ b/roles/serveur_forgejo/tasks/main.yml @@ -272,6 +272,9 @@ dest: "{{ serveur_forgejo_binaire }}" state: link notify: Redemarrer forgejo + # En simulation, une NOUVELLE version n'a pas ete copiee : le lien n'aurait pas de cible + # (2026-10-03, premiere montee simulee). Une version deja posee, elle, se simule. + when: not (ansible_check_mode and not serveur_forgejo_binaire_present.stat.exists) # LES DEPOTS D'UNE INCARNATION PRECEDENTE (2026-09-30). Avant que le role ne cree # l'arborescence : ensuite, le repertoire ne serait plus vierge. La base, elle, a deja diff --git a/roles/serveur_nextcloud/defaults/main.yml b/roles/serveur_nextcloud/defaults/main.yml index 184e9ba..a959fa4 100644 --- a/roles/serveur_nextcloud/defaults/main.yml +++ b/roles/serveur_nextcloud/defaults/main.yml @@ -9,8 +9,26 @@ serveur_nextcloud_groupe: "serveur_nextcloud" serveur_nextcloud_utilisateur: "www-data" # --- Version ÉPINGLÉE (robustesse : pas de mise à jour surprise ; upgrade en escale) --- -serveur_nextcloud_version: "34.0.2" +# 34.0.4 (2026-10-03) : deux corrections apres 34.0.2, meme branche. La 35 existe ; une +# branche ne se saute pas (34 -> 35 -> 36), et `monter.yml` refuse d'en sauter une. +serveur_nextcloud_version: "34.0.4" serveur_nextcloud_url: "https://download.nextcloud.com/server/releases/nextcloud-{{ serveur_nextcloud_version }}.tar.bz2" + +# SIGNATURE DE L'ARCHIVE (2026-10-03) — Nextcloud signe ses publications (PGP detachee). +# Le role installait le code d'un service qui garde les fichiers des personnes sans rien +# verifier. Meme mecanique que Keycloak et Forgejo (`scripts/verifier_signature.py`). +# +# L'empreinte est une DECISION HUMAINE. Ce qui l'etaye, releve le 2026-10-03 : +# - la cle publique est servie par nextcloud.com (`/nextcloud.asc`), UID « Nextcloud +# Security » ; elle est dans `files/nextcloud-release.asc` ; +# - son identifiant long (D75899B9A724937A) est publie sur nextcloud.com/security ; +# - keys.openpgp.org detient la meme cle — mais SANS adresse verifiee ; +# - elle valide la signature de 34.0.4. +# Reserve, a connaitre : ces sources sont toutes de la meme organisation (nextcloud.com), +# sans toile de confiance tierce. L'ancrage vaut ce que vaut le controle de ce domaine. +# Un changement d'empreinte en amont fera ECHOUER le deploiement — c'est voulu. +serveur_nextcloud_signature_url: "{{ serveur_nextcloud_url }}.asc" +serveur_nextcloud_signature_empreinte: "28806A878AE423A28372792ED75899B9A724937A" serveur_nextcloud_racine: "/var/www/nextcloud" # --- PHP (Debian 13 = 8.4) + tuning EXIGÉ par Nextcloud (gotcha : 128M → pages blanches) --- diff --git a/roles/serveur_nextcloud/files/nextcloud-release.asc b/roles/serveur_nextcloud/files/nextcloud-release.asc new file mode 100644 index 0000000..22f68a0 --- /dev/null +++ b/roles/serveur_nextcloud/files/nextcloud-release.asc @@ -0,0 +1,52 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2 + +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 +M704NM/xbc23 +=ykUA +-----END PGP PUBLIC KEY BLOCK----- diff --git a/roles/serveur_nextcloud/tasks/installer.yml b/roles/serveur_nextcloud/tasks/installer.yml index 6afcad0..7879b20 100644 --- a/roles/serveur_nextcloud/tasks/installer.yml +++ b/roles/serveur_nextcloud/tasks/installer.yml @@ -77,6 +77,60 @@ - not serveur_nextcloud_archive_present.stat.exists - not (serveur_nextcloud_cache_present.stat.exists | default(false)) +# LA SIGNATURE, MEME CHEMIN QUE L'ARCHIVE : le depot du site d'abord, l'amont ensuite. +- name: Prendre la signature Nextcloud au dépôt du site, avant de sortir sur Internet + ansible.builtin.get_url: + url: "{{ setops_depot_binaires }}/nextcloud-{{ serveur_nextcloud_version }}.tar.bz2.asc" + dest: "{{ serveur_nextcloud_cache_local }}/nextcloud-{{ serveur_nextcloud_version }}.tar.bz2.asc" + mode: "0644" + timeout: 30 + force: true + delegate_to: localhost + become: false + failed_when: false + when: + - setops_depot_binaires | default('') | length > 0 + - not serveur_nextcloud_archive_present.stat.exists + +- name: La signature Nextcloud est-elle dans le cache du contrôleur ? + ansible.builtin.stat: + path: "{{ serveur_nextcloud_cache_local }}/nextcloud-{{ serveur_nextcloud_version }}.tar.bz2.asc" + register: serveur_nextcloud_asc_present + delegate_to: localhost + become: false + when: not serveur_nextcloud_archive_present.stat.exists + +- name: Récupérer la signature détachée de l archive Nextcloud + ansible.builtin.get_url: + url: "{{ serveur_nextcloud_signature_url }}" + dest: "{{ serveur_nextcloud_cache_local }}/nextcloud-{{ serveur_nextcloud_version }}.tar.bz2.asc" + mode: "0644" + force: true + delegate_to: localhost + become: false + when: + - not serveur_nextcloud_archive_present.stat.exists + - not ((serveur_nextcloud_asc_present.stat.exists | default(false)) + and (serveur_nextcloud_asc_present.stat.size | default(0)) > 0) + +- name: Vérifier la signature de l archive Nextcloud contre l empreinte épinglée + ansible.builtin.command: + argv: + - python3 + - "{{ role_path }}/../../scripts/verifier_signature.py" + - --artefact + - "{{ serveur_nextcloud_cache_local }}/nextcloud-{{ serveur_nextcloud_version }}.tar.bz2" + - --signature + - "{{ serveur_nextcloud_cache_local }}/nextcloud-{{ serveur_nextcloud_version }}.tar.bz2.asc" + - --cle + - "{{ role_path }}/files/nextcloud-release.asc" + - --empreinte + - "{{ serveur_nextcloud_signature_empreinte }}" + delegate_to: localhost + become: false + changed_when: false + when: not serveur_nextcloud_archive_present.stat.exists + - name: Déposer le tarball Nextcloud sur l hôte depuis le cache ansible.builtin.copy: src: "{{ serveur_nextcloud_cache_local }}/nextcloud-{{ serveur_nextcloud_version }}.tar.bz2" @@ -84,6 +138,12 @@ mode: "0644" when: not serveur_nextcloud_archive_present.stat.exists +# UNE AUTRE VERSION EN PLACE ? Alors on MONTE, avant que l'extraction ci-dessous ne +# constate un `occ` present et ne fasse rien — ce qu'elle faisait jusqu'au 2026-10-03, +# laissant le code de l'ancienne version sous le numero de la nouvelle. +- name: Monter Nextcloud si une autre version est en place + ansible.builtin.include_tasks: monter.yml + - name: Extraire Nextcloud dans /var/www (si absent) ansible.builtin.unarchive: src: "/tmp/nextcloud-{{ serveur_nextcloud_version }}.tar.bz2" diff --git a/roles/serveur_nextcloud/tasks/monter.yml b/roles/serveur_nextcloud/tasks/monter.yml new file mode 100644 index 0000000..d0832b2 --- /dev/null +++ b/roles/serveur_nextcloud/tasks/monter.yml @@ -0,0 +1,175 @@ +--- +# MONTER NEXTCLOUD D'UNE VERSION A UNE AUTRE (2026-10-03). +# +# Le role savait INSTALLER, pas monter : l'extraction portait `creates: occ`, et une machine +# deja installee gardait son code quelle que soit la version demandee. Cette procedure suit +# la mise a jour manuelle documentee par Nextcloud : +# +# maintenance ON -> ancien code mis de cote -> nouveau code extrait -> on y ramene +# `data/` (qui vit DANS le code chez nous), la configuration, et tout ce que l'ancien +# repertoire portait EN PLUS de la livraison (applications ajoutees, theme, logo) -> +# `occ upgrade` -> php-fpm recharge -> maintenance OFF. +# +# L'ANCIEN CODE RESTE, sous `-` : c'est le retour arriere. Le retirer est un +# geste humain, une fois la nouvelle version eprouvee. +# +# REFUSE : une RETROGRADATION (Nextcloud ne sait pas descendre), et un SAUT de branche +# (34 -> 36 interdit : il faut passer par 35). +- name: Montée — Nextcloud est-il déjà installé ? + ansible.builtin.stat: + path: "{{ serveur_nextcloud_racine }}/occ" + register: serveur_nextcloud_occ_present + +- name: Montée — quelle version est en place ? + ansible.builtin.command: + argv: [php, "{{ serveur_nextcloud_racine }}/occ", status, --output=json] + become: true + become_user: "{{ serveur_nextcloud_utilisateur }}" + register: serveur_nextcloud_statut + changed_when: false + check_mode: false + when: serveur_nextcloud_occ_present.stat.exists + +- name: Montée — comparer à la version demandée + ansible.builtin.set_fact: + serveur_nextcloud_en_place: >- + {{ (serveur_nextcloud_statut.stdout | from_json).versionstring + if (serveur_nextcloud_occ_present.stat.exists and serveur_nextcloud_statut.rc | default(1) == 0) + else '' }} + +- name: Montée — décider + ansible.builtin.set_fact: + serveur_nextcloud_a_monter: >- + {{ serveur_nextcloud_en_place | length > 0 + and serveur_nextcloud_en_place != serveur_nextcloud_version }} + +- name: Montée — refuser une rétrogradation ou un saut de branche + ansible.builtin.assert: + that: + - serveur_nextcloud_version is version(serveur_nextcloud_en_place, '>') + - (serveur_nextcloud_version.split('.')[0] | int) - (serveur_nextcloud_en_place.split('.')[0] | int) <= 1 + fail_msg: >- + Nextcloud {{ serveur_nextcloud_en_place }} en place, {{ serveur_nextcloud_version }} + demandé. Nextcloud ne rétrograde pas, et ne saute pas de branche : monter d'une + branche à la fois (34 -> 35 -> 36). + when: serveur_nextcloud_a_monter | bool + +- name: Montée — remplacer le code et mettre à jour la base + when: + - serveur_nextcloud_a_monter | bool + - not ansible_check_mode + vars: + serveur_nextcloud_ancien: "{{ serveur_nextcloud_racine }}-{{ serveur_nextcloud_en_place }}" + block: + - name: Montée — le répertoire de l'ancienne version est-il libre ? + ansible.builtin.stat: + path: "{{ serveur_nextcloud_ancien }}" + register: serveur_nextcloud_ancien_present + + - name: Montée — refuser d'écraser un ancien code déjà mis de côté + ansible.builtin.assert: + that: + - not serveur_nextcloud_ancien_present.stat.exists + fail_msg: >- + {{ serveur_nextcloud_ancien }} existe déjà : une montée précédente l'a laissé. + Le vérifier, puis le retirer à la main avant de recommencer. + + - name: Montée — passer en maintenance + ansible.builtin.command: + argv: [php, "{{ serveur_nextcloud_racine }}/occ", maintenance:mode, --on] + become: true + become_user: "{{ serveur_nextcloud_utilisateur }}" + changed_when: true + + - name: Montée — mettre l'ancien code de côté + ansible.builtin.command: + argv: [mv, "{{ serveur_nextcloud_racine }}", "{{ serveur_nextcloud_ancien }}"] + changed_when: true + + - name: Montée — extraire la nouvelle version + ansible.builtin.unarchive: + src: "/tmp/nextcloud-{{ serveur_nextcloud_version }}.tar.bz2" + dest: "/var/www/" + remote_src: true + owner: "{{ serveur_nextcloud_utilisateur }}" + group: "{{ serveur_nextcloud_utilisateur }}" + + # `data/` DANS le code (defaut du role) : on la DEPLACE, on ne la copie pas — meme + # systeme de fichiers, un renommage, quelle que soit sa taille. + - name: Montée — ramener les données + ansible.builtin.command: + argv: + - mv + - "{{ serveur_nextcloud_ancien }}/{{ serveur_nextcloud_data_dir | relpath(serveur_nextcloud_racine) }}" + - "{{ serveur_nextcloud_data_dir }}" + changed_when: true + when: serveur_nextcloud_data_dir.startswith(serveur_nextcloud_racine ~ '/') + + # LA CONFIGURATION, PUIS TOUT CE QUE LA LIVRAISON N'APPORTE PAS — a la racine, dans + # `apps/` et dans `themes/`. On ne remplace rien de livre : seul ce qui MANQUE est repris + # (applications installees, theme de l'organisation, logo pose a la racine). + - name: Montée — reprendre la configuration et ce que la livraison n'apporte pas + ansible.builtin.shell: | + set -euo pipefail + A="{{ serveur_nextcloud_ancien }}"; N="{{ serveur_nextcloud_racine }}" + cp -a "$A/config/." "$N/config/" + for d in . apps themes; do + [ -d "$A/$d" ] || continue + for e in "$A/$d"/* "$A/$d"/.[!.]*; do + [ -e "$e" ] || continue + b=$(basename "$e") + if [ "$d" = . ] && [ "$b" = "{{ serveur_nextcloud_data_dir | basename }}" ]; then continue; fi + if [ ! -e "$N/$d/$b" ]; then cp -a "$e" "$N/$d/"; echo "repris : $d/$b"; fi + done + done + args: + executable: /bin/bash + register: serveur_nextcloud_repris + changed_when: true + + - name: Montée — mettre à jour la base (occ upgrade) + ansible.builtin.command: + argv: [php, "{{ serveur_nextcloud_racine }}/occ", upgrade, --no-interaction] + become: true + become_user: "{{ serveur_nextcloud_utilisateur }}" + environment: + PGSSLMODE: "{{ serveur_nextcloud_pg_sslmode }}" + PGSSLROOTCERT: "{{ serveur_nextcloud_ca_racine }}" + register: serveur_nextcloud_upgrade + changed_when: true + + # php-fpm revalide son cache d'opcodes toutes les 60 s (`opcache.revalidate_freq`) : + # sans rechargement, la premiere minute servirait l'ancien code compile. + - name: Montée — recharger php-fpm (cache d'opcodes) + ansible.builtin.systemd: + name: "php{{ serveur_nextcloud_php_version }}-fpm" + state: reloaded + + - name: Montée — sortir de maintenance + ansible.builtin.command: + argv: [php, "{{ serveur_nextcloud_racine }}/occ", maintenance:mode, --off] + become: true + become_user: "{{ serveur_nextcloud_utilisateur }}" + changed_when: true + + - name: Montée — ce qui a été repris de l'ancienne version + ansible.builtin.debug: + msg: >- + Nextcloud {{ serveur_nextcloud_en_place }} -> {{ serveur_nextcloud_version }}. + Repris : {{ serveur_nextcloud_repris.stdout_lines | default([]) | join(', ') or 'rien' }}. + Ancien code gardé dans {{ serveur_nextcloud_ancien }} (retour arrière). + + # SI UNE ETAPE ECHOUE, ON DIT COMMENT REVENIR — et on ne devine pas a la place de + # l'exploitant : Nextcloud reste en maintenance, l'ancien code et les donnees sont intacts. + rescue: + - name: Montée — échec ; dire comment revenir en arrière + ansible.builtin.fail: + msg: >- + La montée de Nextcloud {{ serveur_nextcloud_en_place }} -> {{ serveur_nextcloud_version }} + a échoué à « {{ ansible_failed_task.name | default('?') }} ». Nextcloud est en + maintenance. Retour arrière, sur l'hôte : (1) si {{ serveur_nextcloud_racine }}/data + existe, `mv {{ serveur_nextcloud_racine }}/data {{ serveur_nextcloud_ancien }}/` ; + (2) `mv {{ serveur_nextcloud_racine }} {{ serveur_nextcloud_racine }}-echec-{{ serveur_nextcloud_version }}` + puis `mv {{ serveur_nextcloud_ancien }} {{ serveur_nextcloud_racine }}` ; + (3) `sudo -u {{ serveur_nextcloud_utilisateur }} php {{ serveur_nextcloud_racine }}/occ maintenance:mode --off`. + Si `occ upgrade` a déjà modifié la base, restaurer aussi la base (setops-restaurer).