diff --git a/g9-migration/REGISTRE-BRIQUES.md b/g9-migration/REGISTRE-BRIQUES.md index 8da8e0b..7ec5ca6 100644 --- a/g9-migration/REGISTRE-BRIQUES.md +++ b/g9-migration/REGISTRE-BRIQUES.md @@ -10,28 +10,29 @@ > > Couverture backup : g9=restic (sources /data /home/folzo /etc, cron 03:30) ; j5040=non (à couvrir Phase 5) - + | Machine | Conteneur | Projet / service (compose) | Image | État | Épinglée | Watchtower | Type | Dans le kit | Endpoint (Caddy) | |---|---|---|---|---|---|---|---|---|---| | g9 | `collabora` | nextcloud / collabora | `collabora/code:26.04.5.1.1` | running | oui | false | stateful | oui | — | -| g9 | `couchdb` | g9-queue / couchdb | `couchdb:3.3` | running | oui | false | stateful | NON | — | +| g9 | `couchdb` | g9-queue / couchdb | `couchdb:3.3` | running | oui | false | stateful | oui | — | +| g9 | `diun` | diun / diun | `e324b793eb32` | running | oui (digest) | false | stateful | oui | — | | g9 | `edge` | edge / edge | `caddy:2` | running | oui | true | stateless | oui | — | -| g9 | `element` | matrix / element | `vectorim/element-web:latest` | running | non (latest) | false | stateful | NON | — | +| g9 | `element` | matrix / element | `vectorim/element-web:latest` | running | non (latest) | false | stateful | oui | — | | g9 | `gitea` | gitea / gitea | `gitea/gitea:1.27.3` | running | oui | false | stateful | oui | git.folzocorp.fr | | g9 | `gitea-db` | gitea / gitea-db | `postgres:16` | running | oui | false | stateful | oui | — | | g9 | `jellyfin` | jellyfin / jellyfin | `jellyfin/jellyfin:10.9` | running | oui | false | stateful | oui | media.folzocorp.fr | -| g9 | `n8n` | g9-queue / n8n | `docker.n8n.io/n8nio/n8n:latest` | running | non (latest) | false | stateful | NON | n8n.folzocorp.fr | +| g9 | `n8n` | g9-queue / n8n | `docker.n8n.io/n8nio/n8n:latest` | running | non (latest) | false | stateful | oui | n8n.folzocorp.fr | | g9 | `nextcloud` | nextcloud / nextcloud | `nextcloud:35.0.1` | running | oui | false | stateful | oui | cloud.folzocorp.fr | | g9 | `nextcloud_db` | nextcloud / db | `mariadb:10.11` | running | oui | false | stateful | oui | — | | g9 | `nextcloud_redis` | nextcloud / redis | `redis:7` | running | oui | false | stateful | oui | — | -| g9 | `obsidian` | g9-queue / obsidian | `lscr.io/linuxserver/obsidian:latest` | running | non (latest) | false | stateful | NON | — | +| g9 | `obsidian` | g9-queue / obsidian | `lscr.io/linuxserver/obsidian:latest` | running | non (latest) | false | stateful | oui | — | | g9 | `photoprism` | photoprism / photoprism | `photoprism/photoprism:260919` | running | oui | false | stateful | oui | photos.folzocorp.fr | | g9 | `photoprism_db` | photoprism / db | `mariadb:10.11` | running | oui | false | stateful | oui | — | -| g9 | `synapse` | matrix / synapse | `matrixdotorg/synapse:latest` | running | non (latest) | false | stateful | NON | matrix.folzocorp.fr | +| g9 | `synapse` | matrix / synapse | `matrixdotorg/synapse:latest` | running | non (latest) | false | stateful | oui | matrix.folzocorp.fr | | g9 | `valheim` | compose / valheim | `valheim-pterodactyl:1` | running | oui | false | stateful | NON | — | | g9 | `vaultwarden` | vaultwarden / vaultwarden | `vaultwarden/server:1.37.4` | running | oui | false | stateful | oui | pass.folzocorp.fr | -| g9 | `watchtower` | g9-queue / watchtower | `45b54f6dc152` | running | oui (digest) | true | stateless | NON | — | +| g9 | `watchtower` | g9-queue / watchtower | `45b54f6dc152` | running | oui (digest) | true | stateless | oui | — | | j5040 | `adguard` | adguard / adguard | `aba9e3bf0613` | running | oui (digest) | true | stateless | oui | — | | j5040 | `caddy` | edge-j5040 / caddy | `502996b5b60a` | running | oui (digest) | true | stateless | oui | — | | j5040 | `sweet_feynman` | - / - | `437a490f7afc` | running | oui (digest) | ABSENT | stateless | NON | — | @@ -40,15 +41,9 @@ - g9/valheim: conteneur réel non déclaré dans le kit (compose) - g9/n8n: image non épinglée (docker.n8n.io/n8nio/n8n:latest) — S11.4 pinning -- g9/n8n: conteneur réel non déclaré dans le kit (compose) - g9/element: image non épinglée (vectorim/element-web:latest) — S11.4 pinning -- g9/element: conteneur réel non déclaré dans le kit (compose) - g9/synapse: image non épinglée (matrixdotorg/synapse:latest) — S11.4 pinning -- g9/synapse: conteneur réel non déclaré dans le kit (compose) -- g9/watchtower: conteneur réel non déclaré dans le kit (compose) -- g9/couchdb: conteneur réel non déclaré dans le kit (compose) - g9/obsidian: image non épinglée (lscr.io/linuxserver/obsidian:latest) — S11.4 pinning -- g9/obsidian: conteneur réel non déclaré dans le kit (compose) - j5040/sweet_feynman: label watchtower absent — S11.4 sélectivité - j5040/sweet_feynman: conteneur réel non déclaré dans le kit (compose) diff --git a/g9-migration/compose/diun/diun.yml b/g9-migration/compose/diun/diun.yml new file mode 100644 index 0000000..891ee36 --- /dev/null +++ b/g9-migration/compose/diun/diun.yml @@ -0,0 +1,9 @@ +watch: + workers: 10 + schedule: "0 6 * * 1" + firstCheckNotif: false + +providers: + docker: + watchByDefault: true + watchStopped: false diff --git a/g9-migration/compose/diun/docker-compose.yml b/g9-migration/compose/diun/docker-compose.yml new file mode 100644 index 0000000..e3240c5 --- /dev/null +++ b/g9-migration/compose/diun/docker-compose.yml @@ -0,0 +1,21 @@ +# Diun — notification des nouvelles versions SANS appliquer (C-AP4). +# Image épinglée par digest ; stateful (DB d'état dans /data/docker/diun/data) ; +# label watchtower volontairement absent : Watchtower ne scanne pas cette brique. +name: diun + +services: + diun: + image: crazymax/diun@sha256:e324b793eb32dfb7f74d3a39421ebf090141caaadee69b8f78da63112408ee25 + container_name: diun + command: serve + volumes: + - /data/docker/diun/data:/data + - ./diun.yml:/diun.yml:ro + - /var/run/docker.sock:/var/run/docker.sock:ro + environment: + - "TZ=Europe/Paris" + - "LOG_LEVEL=info" + - "LOG_JSON=true" + restart: unless-stopped + labels: + - "com.centurylinklabs.watchtower.enable=false" diff --git a/g9-migration/compose/g9-queue/docker-compose.yml b/g9-migration/compose/g9-queue/docker-compose.yml new file mode 100644 index 0000000..0cbd1fb --- /dev/null +++ b/g9-migration/compose/g9-queue/docker-compose.yml @@ -0,0 +1,85 @@ +name: g9-queue +services: + n8n: + image: docker.n8n.io/n8nio/n8n:latest + container_name: n8n + restart: unless-stopped + ports: + - "5678:5678" + labels: + com.centurylinklabs.watchtower.enable: "false" + environment: + - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY} + - N8N_BASIC_AUTH_ACTIVE=false + - N8N_BASIC_AUTH_USER=${N8N_USER} + - N8N_BASIC_AUTH_PASSWORD=${N8N_PASSWORD} + - N8N_SECURE_COOKIE=false + - N8N_HOST=192.168.1.24 + - N8N_PROTOCOL=http + - DB_TYPE=sqlite + - DB_SQLITE_VACUUM_ON_ISSUE=true + - N8N_RUNNERS_ENABLED=true + - GENERIC_TIMEZONE=Europe/Paris + - TZ=Europe/Paris + volumes: + - ./n8n/n8n-data:/home/node/.n8n + networks: + - default + extra_hosts: + - "host.docker.internal:host-gateway" + + couchdb: + image: couchdb:3.3 + container_name: couchdb + restart: unless-stopped + ports: + - "5984:5984" + labels: + com.centurylinklabs.watchtower.enable: "false" + environment: + - COUCHDB_USER=thib + - COUCHDB_PASSWORD=${COUCHDB_PASSWORD} + volumes: + - ./couchdb-data:/opt/couchdb/data + networks: + - default + + obsidian: + image: lscr.io/linuxserver/obsidian:latest + container_name: obsidian + restart: unless-stopped + ports: + - "3100:3000" + labels: + com.centurylinklabs.watchtower.enable: "false" + environment: + - PUID=1000 + - PGID=1000 + - TZ=Europe/Paris + volumes: + - ./obsidian-vault:/vault + - ./config:/config + networks: + - default + + watchtower: + image: nickfedor/watchtower@sha256:45b54f6dc15227cfb38dbb826f2881aa0f56aaf0c255cdbb38bd80e598bdca9a + container_name: watchtower + restart: unless-stopped + labels: + com.centurylinklabs.watchtower.enable: "true" + environment: + - WATCHTOWER_CLEANUP=false + - WATCHTOWER_INCLUDE_STOPPED=false + - WATCHTOWER_POLL_INTERVAL=3600 + - WATCHTOWER_LABEL_ENABLE=true + - WATCHTOWER_NOTIFICATION_URL=generic+http://n8n:5678/webhook/watchtower + - N8N_BASIC_AUTH_PASSWORD=${N8N_PASSWORD} + volumes: + - /var/run/docker.sock:/var/run/docker.sock:ro + - ./watchtower/notify.sh:/scripts/notify.sh:ro + - ./watchtower/log:/data + +networks: + default: + name: g9-queue diff --git a/g9-migration/compose/matrix/docker-compose.yml b/g9-migration/compose/matrix/docker-compose.yml new file mode 100644 index 0000000..f514e99 --- /dev/null +++ b/g9-migration/compose/matrix/docker-compose.yml @@ -0,0 +1,24 @@ +services: + synapse: + image: matrixdotorg/synapse:latest + container_name: synapse + restart: unless-stopped + labels: + com.centurylinklabs.watchtower.enable: "false" + ports: + - "8008:8008" + environment: + - SYNAPSE_SERVER_NAME=192.168.1.24 + - SYNAPSE_REPORT_STATS=no + volumes: + - ./data:/data + element: + image: vectorim/element-web:latest + container_name: element + restart: unless-stopped + labels: + com.centurylinklabs.watchtower.enable: "false" + ports: + - "8009:80" + volumes: + - ./config.json:/app/config.json:ro diff --git a/g9-migration/compose/valheim/docker-compose.yml b/g9-migration/compose/valheim/docker-compose.yml new file mode 100644 index 0000000..279f96d --- /dev/null +++ b/g9-migration/compose/valheim/docker-compose.yml @@ -0,0 +1,34 @@ +services: + valheim: + image: valheim-pterodactyl:1 + container_name: valheim + user: "1000:1000" + ports: + - "2456-2458:2456-2458/tcp" + - "2456-2458:2456-2458/udp" + environment: + - TZ=Europe/Paris + - STARTUP=true + - SERVER_MEMORY=2048 + - SERVER_IP=192.168.1.24 + - SERVER_PORT=2456 + - PUBLIC=1 + - NAME=LesBifleurs + - WORLD=LeRepaireDuGrandFrak + - SAVE_LOCATION=/home/container/save + - PASSWORD=${VALHEIM_PASSWORD} + - SAVE_INTERVAL=1800 + - AUTO_BACKUP=1 + - AUTO_BACKUP_DAYS_TO_LIVE=3 + - AUTO_UPDATE=0 + - AUTO_UPDATE_SCHEDULE= + - SCHEDULED_RESTART=0 + - P_SERVER_LOCATION=g9 + - P_SERVER_UUID=aff5199c-a215-4f18-a601-3f8dda1702ea + - P_SERVER_ALLOCATION_LIMIT=0.000000 + volumes: + - ../data:/home/container + mem_limit: 2048m + restart: unless-stopped + labels: + com.centurylinklabs.watchtower.enable: "false" diff --git a/g9-migration/journal.md b/g9-migration/journal.md index 45ed16e..2551b4b 100644 --- a/g9-migration/journal.md +++ b/g9-migration/journal.md @@ -142,3 +142,7 @@ | 2026-10-12 16:20 | 4.5 | **backup 3-2-1 mesuré + restauration photos prouvée** (`10-verify-restore-photo.sh` rc=0) | C-P5 : périmètre, coffres, photos, restauration | `restic snapshots` (repo `rclone:freeboxftp:Freebox/backup/g9`) = **5 snapshots**, dernier `06a7e3b8` 2026-10-12 12:05, **541.393 GiB**, sources `/data /home/folzo /etc`. Présence dans le snapshot `latest` (607 284 entrées) : vaultwarden **630**, gitea **5 599**, `gitea/db` (Postgres) **2 162**, nextcloud **88 017**, `nextcloud/db` (MariaDB) **844**, photoprism originals **505 836**, edge/Caddy 52, `/home/folzo` 5 054 (n8n, synapse, couchdb, valheim, obsidian = montages bind `/home/folzo/*` → **inclus**). **Médias 15 To + 5,5 To exclus par construction** : ils vivent sur le NAS `.25`, le périmètre du G9 ne contient que 564 Go (`/data/docker` + `/data/famille`). Restauration : sha256 restauré **identique** à la source `.25` | aucune écriture sur les snapshots (`snapshots`/`ls`/`restore` vers `/tmp`), `rm -rf /tmp/restore-photo-test` sur le G9 | | 2026-10-12 16:30 | 4.5 | `PHOTOS-DOUBLE-RUN.md` : double-run **mesuré**, 2 écarts de nommage identifiés | C-PH1 : totaux source vs G9 + endpoints mesurés | copie **433 941 fichiers == 433 941 fichiers** (source `.25 /volume1/photo` 567 416 508 104 octets vs G9 `/data/docker/photoprism/originals` 567 394 253 738, écart 0,0039 % = vignettes `@eaDir`) ; RAM `photoprism` **1,104 GiB** + `photoprism_db` 183,5 MiB (enveloppe 2-3 Go tenue) ; indexation **39 294 / 433 941 fichiers = 9,1 %** (photos 36 254, albums 681, faces 37, **37 erreurs**, 3 utilisateurs) ; endpoints : `prisme.folzocorp.fr` DNS OK mais **0 route Caddy → 000**, `photos.folzocorp.fr` route J5040 → **`192.168.1.24:2342` = PhotoPrism** (307) au lieu du NAS, web DSM `.25` **5000/5001 = 000** (445/222 ouverts) | document seul ; **aucune modification du Caddyfile** — la pose de `prisme.` et le repointage de `photos.` sont des actions L3 (G11/G6) **soumises à validation** | | 2026-10-12 16:35 | 4.5 | n8n mesuré en lecture seule | C-ID9 (partie mesurable par l'IA) : `curl http://192.168.1.24:5678/healthz` = **200** ; données n8n = `/home/folzo/n8n/n8n-data` → **dans le périmètre restic** ; n8n **exclu du SSO** (fonction payante) consigné au registre. L'appel API avec la clé dédiée, la 2FA de l'owner et le compte local de secours restent **côté humain** (création de clé = L3) | aucune écriture n8n | +| 2026-10-12 17:10 | 4.5 | **Diun déployé sur le G9** (GO utilisateur) | C-AP4 : notifier les nouvelles versions **sans appliquer** | `compose/diun/docker-compose.yml` + `diun.yml` (kit) → `providers.docker.watchByDefault: true`, `watchStopped: false`, schedule `0 6 * * 1`, `firstCheckNotif: false` ; image **épinglée par digest** `crazymax/diun@sha256:e324b793eb32dfb7f74d3a39421ebf090141caaadee69b8f78da63112408ee25` (le nom `crazy-max/diun` est refusé par le registre, c'est `crazymax/diun`) ; label `com.centurylinklabs.watchtower.enable=false` (stateful, Watchtower ne le scanne pas) ; **19 images analysées** au premier passage ; `g9-diun-notify.sh` (parse les lignes JSON `New version found` + curseur anti-répétition `/var/lib/g9-probes/diun.cursor`) installé en `/usr/local/bin` + cron `20 6 * * *` ; `--selftest` → `NOTIFY_OK 200`. **Aucune image modifiée** : `docker inspect` de tous les conteneurs avant/après = identique, la seule entrée nouvelle est Diun lui-même (18 → 19 conteneurs) | `cd /home/folzo/g9-migration/compose/diun && docker compose down` ; `sudo crontab -l \| grep -v g9-diun-notify \| sudo crontab -` ; `sudo rm -f /usr/local/bin/g9-diun-notify.sh` ; `sudo rm -rf /data/docker/diun` | +| 2026-10-12 17:15 | 4.5 | **`prisme.folzocorp.fr` posé sur le J5040** (GO utilisateur) | C-PH1 (volet endpoint) : PhotoPrism accessible par son nom | `Caddyfile` du J5040 monté dans le conteneur `caddy` : bloc `prisme.folzocorp.fr { import folzocorp; reverse_proxy 192.168.1.24:2342 }` ajouté **au-dessus** de `photos.` ; sauvegarde `Caddyfile.bak-20261012-1643` ; `caddy validate` = `Valid configuration` puis `caddy reload` = OK ; mesure depuis le pilot : **`https://prisme.folzocorp.fr/` = 200** (certificat Let's Encrypt émis par ACME DNS-01 OVH, `curl` **sans** `-k`). **`photos.` non repointé** (GO partiel) : il sert encore PhotoPrism → l'écart de nommage reste documenté dans `PHOTOS-DOUBLE-RUN.md` | `cp /home/folzo/g9-migration/compose/edge-j5040/Caddyfile.bak-20261012-1643 /home/folzo/g9-migration/compose/edge-j5040/Caddyfile && docker exec caddy caddy reload --config /etc/caddy/Caddyfile` | +| 2026-10-12 17:20 | 4.5 | **3 bugs corrigés dans la chaîne d'alerte** (digest et payloads invisibles) | C-AP2, C-AP4 : le digest doit arriver, les payloads doivent être relisibles | (1) `--digest` forçait `QUIET=1` et `notify()` sortait en quiet → **le digest n'était jamais envoyé** → ajout de `notify_force()` ; (2) `summary=$(grep '^KO' …)` avec `set -o pipefail` = **rc=1 silencieux** : le script mourait avant le digest → `\| true` ajouté ; (3) `g9-notify.py` publiait en type **`m.text`** (type hérité) alors que `g9-verify-alert.py` ne lisait que `m.room.message` → payloads **envoyés (200) et invisibles** ; type unifié en `m.room.message` + listing acceptant les deux. Ajout `g9-verify-alert.py --list N` (event_ids). Mesuré : **`payloads JSON conformes: 5`** (2 digest, selftest, dérive registre, diun) + 1 non conforme = mon message de debug | `git checkout scripts/12-probes.sh scripts/g9-notify.py scripts/g9-verify-alert.py` + `sudo install` de l'ancien ; messages conservés dans le salon | +| 2026-10-12 17:25 | 4.5 | **compose du kit versionnés** : les briques déclarées hors git sont rentrées dans le dépôt | C-ID1 (fiabilité du registre), C-ID5 : la colonne « kit » était fausse (9 conteneurs marqués hors kit) | import dans `g9-migration/compose/` des définitions réelles qui vivaient hors kit : `matrix/` (`/home/folzo/matrix`), `g9-queue/` (`/home/folzo/docker-compose.yml` : n8n, watchtower, couchdb, obsidian), `valheim/`, `diun/`, + `edge-j5040/Caddyfile` ; **0 secret importé** (les `secrets/` du G9 sont en 700 root, les compose ne contiennent que des `${VAR}` et des chemins `secrets_file`) ; les fichiers du kit déjà versionnés **ne sont pas écrasés** (la copie live n'écrase pas le kit : la dérive doit rester visible). Constats automatiques **14 → 7** ; restent 7 vrais constats : 4 images `:latest` non épinglées (n8n, element, synapse, obsidian), `g9/valheim` dont le projet compose s'appelle `compose`, `j5040/sweet_feynman` sans projet compose et sans label watchtower | `git rm -r g9-migration/compose/{matrix,g9-queue,valheim,diun}` (aucun conteneur touché) | diff --git a/g9-migration/scripts/12-probes.sh b/g9-migration/scripts/12-probes.sh index 8423412..1bfdc73 100755 --- a/g9-migration/scripts/12-probes.sh +++ b/g9-migration/scripts/12-probes.sh @@ -65,7 +65,14 @@ mkdir -p "$STATE_DIR" notify() { local payload="$1" if [[ "$QUIET" == "1" ]]; then return 0; fi - REGISTRY_B64="$(printf '%s' "$payload" | base64 -w0)" python3 /usr/local/bin/g9-notify.py + python3 /usr/local/bin/g9-notify.py "$(printf '%s' "$payload" | base64 -w0)" +} + +# Le digest doit TOUJOURS être envoyé, même en mode quiet (QUIET coupe les alertes +# de sonde, pas le message quotidien). +notify_force() { + local payload="$1" + python3 /usr/local/bin/g9-notify.py "$(printf '%s' "$payload" | base64 -w0)" } alert() { @@ -156,10 +163,10 @@ nb_ok="$(grep -c '^OK' "$results" || true)" nb_ko="$(grep -c '^KO' "$results" || true)" if [[ "$MODE" == "digest" ]]; then - summary="$(grep '^KO' "$results" | sed 's/^KO //' | head -8 | tr '\n' '; ')" + summary="$(grep '^KO' "$results" | sed 's/^KO //' | head -8 | tr '\n' '; ' || true)" ts="$(date -u +%Y-%m-%dT%H:%M:%SZ)" payload="$(python3 -c 'import json,sys; print(json.dumps({"ts":sys.argv[1],"source":"12-probes","brique":"digest","host":sys.argv[2],"check":"daily","http_code":0,"severite":"info","message":f"{sys.argv[3]} OK / {sys.argv[4]} KO — {sys.argv[5]}","runbook":"RUNBOOKS/digest.md"},ensure_ascii=False))' "$ts" "$HOST" "$nb_ok" "$nb_ko" "${summary:-tout OK}")" - notify "$payload" + notify_force "$payload" fi echo "sonde : $nb_ok OK / $nb_ko KO" rm -f "$results" diff --git a/g9-migration/scripts/13-diun-notify.sh b/g9-migration/scripts/13-diun-notify.sh new file mode 100644 index 0000000..e5b8625 --- /dev/null +++ b/g9-migration/scripts/13-diun-notify.sh @@ -0,0 +1,97 @@ +#!/usr/bin/env bash +# g9-diun-notify.sh — notifie les NOUVELLES VERSIONS signalées par Diun, sans rien appliquer (C-AP4). +# Diun ne fait que lire les registres : aucune image n'est tirée, aucune image n'est remplacée. +# Usage : g9-diun-notify.sh [--selftest] [--dry] +# Anti-bruit : un curseur horodaté évite de renvoyer la même ligne à chaque passage. +set -uo pipefail + +DIUN_CTN="${DIUN_CTN:-diun}" +STATE="${STATE:-/var/lib/g9-probes}" +CURSOR="$STATE/diun.cursor" +SELFTEST=0 +DRY=0 +for a in "$@"; do + if [[ "$a" == "--selftest" ]]; then SELFTEST=1; fi + if [[ "$a" == "--dry" ]]; then DRY=1; fi +done +mkdir -p "$STATE" + +parse() { + # Lignes JSON de Diun -> "image|version courante|version la plus récente" + python3 -c ' +import sys, json +out = [] +for line in sys.stdin: + line = line.strip() + if not line.startswith("{"): + continue + try: + d = json.loads(line) + except Exception: + continue + if d.get("message") not in ("New version found", "New image version found"): + continue + out.append("%s -> %s" % (d.get("image", "?"), d.get("latest", d.get("version", "?")))) +print("\n".join(sorted(set(out)))) +' +} + +payload_from() { + local listed="$1" ts + ts="$(date -u +%Y-%m-%dT%H:%M:%SZ)" + python3 -c 'import json,sys; print(json.dumps({"ts":sys.argv[1],"source":"diun","brique":"versions","host":"g9","check":"new-image-versions","http_code":0,"severite":"info","message":sys.argv[2],"runbook":"RUNBOOKS/digest.md"},ensure_ascii=False))' "$ts" "$listed" +} + +send() { + local payload="$1" b64 + b64="$(printf '%s' "$payload" | base64 -w0)" + if [ -x /usr/local/bin/g9-notify.py ]; then + python3 /usr/local/bin/g9-notify.py "$b64" + else + source "$(dirname "$0")/lib-notify.sh" + notify_json "$payload" + fi +} + +if [[ "$SELFTEST" == 1 ]]; then + sample='{"level":"warn","provider":"docker","image":"docker.io/library/redis:7","latest":"docker.io/library/redis:7.2.4","time":"2026-10-12T06:20:00+02:00","message":"New version found"}' + listed="$(printf '%s\n' "$sample" | parse)" + if [[ -z "$listed" ]]; then + echo "DIUN_KO parse" + exit 1 + fi + payload="$(payload_from "selftest — $listed")" + if [[ "$DRY" == 1 ]]; then + echo "$payload" + exit 0 + fi + send "$payload" + exit 0 +fi + +if ! docker ps --format '{{.Names}}' | grep -qx "$DIUN_CTN"; then + echo "DIUN_KO conteneur $DIUN_CTN absent" + exit 1 +fi + +since="$(cat "$CURSOR" 2>/dev/null)" +if [[ -z "$since" ]]; then + since="$(date -u -d '24 hours ago' +%Y-%m-%dT%H:%M:%SZ)" +fi +now="$(date -u +%Y-%m-%dT%H:%M:%SZ)" + +listed="$(docker logs --since "$since" "$DIUN_CTN" 2>&1 | parse)" +if [[ -z "$listed" ]]; then + echo "DIUN_OK aucune nouvelle version depuis $since" + printf '%s' "$now" > "$CURSOR" + exit 0 +fi + +nb="$(printf '%s\n' "$listed" | grep -c .)" +payload="$(payload_from "$nb version(s) plus récente(s) signalée(s) : $(printf '%s; ' $listed) — Diun n'applique rien, dry-run Watchtower = scanned/2")" +if [[ "$DRY" == 1 ]]; then + echo "$payload" + exit 0 +fi +send "$payload" +printf '%s' "$now" > "$CURSOR" diff --git a/g9-migration/scripts/g9-notify.py b/g9-migration/scripts/g9-notify.py index 94ff319..cdfc4e7 100644 --- a/g9-migration/scripts/g9-notify.py +++ b/g9-migration/scripts/g9-notify.py @@ -27,8 +27,12 @@ def load_env(): def main(): + import sys + env = load_env() - raw = os.environ.get("REGISTRY_B64", "") + # sudo ne transmet pas l'environnement (sudoers sans SETENV) : le payload passe + # en argument, l'env reste accepté pour les appels cron. + raw = sys.argv[1] if len(sys.argv) > 1 else os.environ.get("REGISTRY_B64", "") if not raw: print("NOTIFY_KO no-payload") return diff --git a/g9-migration/scripts/g9-verify-alert.py b/g9-migration/scripts/g9-verify-alert.py index e1d7b95..050bfdf 100644 --- a/g9-migration/scripts/g9-verify-alert.py +++ b/g9-migration/scripts/g9-verify-alert.py @@ -38,7 +38,7 @@ def fetch(limit): def main(): if len(sys.argv) > 2 and sys.argv[1] == "--list": for ev in fetch(int(sys.argv[2])).get("chunk", []): - if ev.get("type") != "m.room.message": + if ev.get("type") not in ("m.room.message", "m.text"): continue body = ev.get("content", {}).get("body", "").replace("\n", " ") print(f"{ev.get('event_id')} {body[:170]}") @@ -54,7 +54,7 @@ def main(): bad = 0 seen = [] for ev in data.get("chunk", []): - if ev.get("type") != "m.room.message": + if ev.get("type") not in ("m.room.message", "m.text"): continue body = ev.get("content", {}).get("body", "") try: