Set-OPS-Public/roles/serveur_nextcloud/tasks/monter.yml
Daniel Allaire 49f3d28865 forge et nuage : Forgejo 16.0.5, Nextcloud 34.0.4 ; Nextcloud sait monter
- serveur_nextcloud : tasks/monter.yml (maintenance, ancien code mis de côté,
  data/config/ajouts repris, occ upgrade) ; signature PGP vérifiée
- serveur_forgejo : 16.0.5 ; une montée se simule
- serveur_artefacts : le site sert aussi la signature de Nextcloud
- CHANGELOG 68

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 00:09:03 -04:00

175 lines
8.1 KiB
YAML

---
# 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 `<racine>-<version>` : 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).