# Veille Versions Stack NAS & VPS — Référentiel Baserow Ce document décrit le fonctionnement du dispositif de suivi et de veille automatisée des versions des conteneurs du NAS Synology et du VPS Contabo. > **Doctrine stricte** : Ce workflow ne fait **que détecter et notifier**. Aucune mise à jour n'est exécutée automatiquement. Toute opération de mise à jour fait l'objet d'un brief de cadrage, d'une exécution contrôlée avec sauvegardes et d'une validation par commandes réelles. --- ## 1. Architecture du Dispositif ```mermaid graph TD Trigger["Schedule Trigger (Lundi 08h00 Africa/Tunis)"] --> ReadBR["Lire Table Baserow (Table 1097 / Infra Stack)"] ReadBR --> SSHNAS["SSH Restreint NAS (n8n-versions-ro @ 192.168.100.33:22222)"] SSHNAS --> SSHVPS["SSH Restreint VPS (n8n-versions-ro @ tailscale-nyora-bridge:22223)"] SSHVPS --> MapItems["Préparer Mapping & Éléments (Fusion NAS & VPS)"] MapItems --> Registries["API Registres (Docker Hub & npm registry)"] Registries --> Analyze["Analyser Écarts & Versions (Boucle 11 items)"] Analyze --> UpdateBR["Mettre à jour Baserow (PATCH Table 1097)"] UpdateBR --> Filter["Filtrer Alertes (Si nouvel écart détecté)"] Filter -->|Nouvel écart| Telegram["Notification Telegram (ND_Telegram)"] Filter -->|À jour ou En pause| Silent["Silence (0 spam)"] ``` --- ## 2. Composants Techniques ### A. Référentiel Baserow (`infra_versions`) - **Workspace** : `187 (Perso)` - **Database** : `Infra Stack` (ID `317`) - **Table** : `infra_versions` (ID `1097`) - **URL** : `https://baserow.bolbol.tn/database/317/table/1097` - **Token API dédié** : `n8n-infra-versions` (Token ID `32`, scopé Workspace 187 Perso) - **Champs suivis** : - `conteneur` (Texte, clé primaire) : Nom du conteneur - `image_repo` (Texte) : Repository Docker Hub ou nom de package npm (ex: `@deepseek-ai/dsh`) - `methode_verif` (Single select) : `image_tag`, `exec_version` ou `npm_registry` - `emplacement` (Single select) : `NAS` ou `VPS` - `version_installee` (Texte) : Version réelle active sur l'hôte - `derniere_version_disponible` (Texte) : Dernière version stable publiée - `ecart` (Texte) : Statut de l'écart (`0`, `Installée: ... ➔ Dispo: ...`) - `criticite` (Single select) : `Critique`, `Important`, `Mineur` - `date_derniere_verification` (Date) : Date du dernier passage de veille - `date_derniere_maj_effective` (Date) : Date de la dernière MAJ appliquée - `statut` (Single select) : `À jour`, `Retard mineur`, `Retard à traiter`, `En pause` - `lien_runbook` (URL) : Lien vers le guide d'exploitation / runbook - `notes` (Texte long) : Particularités techniques (ex: image custom, base de données, pins) --- ### B. Accès SSH Restreint NAS (`n8n-versions-ro`) - **Compte DSM** : `n8n-versions-ro` (UID `1041`, membre du groupe `docker` `65538`). - **Clé SSH** : Clé Ed25519 dédiée (`/volume1/docker/scripts/id_ed25519_n8n_versions`). - **Restriction `authorized_keys`** : ```text command="/volume1/docker/scripts/versions-check.sh",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKDwuAwKnKiKskL+Vr4WYhn/uySlk5jyOHPh1R/P/9K0 n8n-versions-ro ``` - **Script exécutable** : `/volume1/docker/scripts/versions-check.sh` (mode 755) --- ### C. Accès SSH Restreint VPS (`n8n-versions-ro`) - **Compte VPS** : `n8n-versions-ro` (UID `1002`, GID `1002`, membre du groupe `docker`). - **Clé SSH dédiée** : `/volume1/docker/scripts/id_ed25519_n8n_versions_vps` - **Fingerprint réel** : `256 SHA256:fTDnqFouAhwApAsnQjuLoGjvZCNoHAwYC4gpGqRvygY n8n-versions-ro@vps (ED25519)` - **Clé publique** : `ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFdwCzUBTsBKNSRxhjwU82o9T2VbQn4HKbp+3mFyIQTq n8n-versions-ro@vps` - **Restriction `authorized_keys` VPS** (`/home/n8n-versions-ro/.ssh/authorized_keys`) : ```text command="/home/n8n-versions-ro/versions-check-vps.sh",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFdwCzUBTsBKNSRxhjwU82o9T2VbQn4HKbp+3mFyIQTq n8n-versions-ro@vps ``` - **Script exécutable VPS** : `/home/n8n-versions-ro/versions-check-vps.sh` (mode 755) - **Relais Réseau n8n ➔ VPS** : - OpenSSH standard écoute sur le port `22222` sur l'interface `tailscale0` du VPS (`100.94.90.119:22222`). - Sur le NAS, le conteneur `tailscale-vps-ssh-relay` (partageant l'espace réseau de `tailscale-nyora-bridge`) relaie le port `22223` vers `100.94.90.119:22222`. - Le conteneur `n8n` interroge directement `tailscale-nyora-bridge:22223`. --- ### D. Workflow n8n (`veille-versions-stack`) - **ID Workflow** : `zUWN5K4Q1A2JKFIS` - **Déclenchement** : Hebdomadaire (Lundi à 08h00 Africa/Tunis) + Webhook de test manuel `/webhook/test-veille-versions`. - **Canal Telegram** : Credential `ND_Telegram` (`OyOHh6jAzCDsiBux`), Chat ID `2084513684`. - **Export JSON** : [`veille-versions-stack.n8n.json`](file:///tmp/nas-runbooks/common/workflows/veille-versions-stack.n8n.json) --- ## 3. Table des 11 Conteneurs Suivis | Conteneur | Emplacement | Image Repo / Package | Méthode | Criticité | Particularités | |---|---|---|---|---|---| | `n8n` | NAS | `n8nio/n8n` | `exec_version` | Important | Image custom (docx, exceljs) | | `bifrost` | NAS | `maximhq/bifrost` | `image_tag` | Critique | Pin image, backup config.db/config.json | | `gitea` | NAS | `gitea/gitea` | `image_tag` | Important | Pin rootless, backup natif `gitea dump` | | `portainer` | NAS | `portainer/portainer-ce` | `image_tag` | Mineur | Pilote stacks, MAJ en priorité | | `vaultwarden` | NAS | `vaultwarden/server` | `image_tag` | Mineur | Pin alpine, backup db.sqlite3 | | `baserow` | NAS | `baserow/baserow` | `exec_version` | Important | Mode minimal, DNS dynamique Nginx | | `crowdsec` | NAS | `crowdsecurity/crowdsec` | `exec_version` | Important | Sécurité IDS/IPS DSM | | `tailscale-nyora-bridge` | NAS | `tailscale/tailscale` | `image_tag` | Mineur | Bridge HTTP/SOCKS5 | | `trilium` | NAS | `triliumnext/trilium` | `image_tag` | Mineur | `En pause` (exclu des alertes actives) | | `dsh-vps` | VPS | `@deepseek-ai/dsh` | `npm_registry` | Important | Build custom, version npm pinnée, patch binding `startup.js` | | `dsh-vps-filebrowser` | VPS | `filebrowser/filebrowser` | `image_tag` | Mineur | Compagnon Web UI, entrypoint `/bin/filebrowser` | --- ## 4. Procédure de Test et Validation 1. **Test d'exécution manuelle globale via webhook** : ```bash curl -s http://192.168.100.33:5678/webhook/test-veille-versions -H "Host: n8n.bolbol.tn" # Réponse attendue si tout est à jour : {"no_alert": true, "message": "Aucun nouvel ecart"} ``` 2. **Test d'interrogation SSH unitaire NAS** : ```bash ssh -p 22222 -i /volume1/docker/scripts/id_ed25519_n8n_versions -o BatchMode=yes n8n-versions-ro@127.0.0.1 "all" ``` 3. **Test d'interrogation SSH unitaire VPS** (depuis le conteneur `n8n`) : ```bash docker exec n8n ssh -p 22223 -i /tmp/id_vps_n8n -o BatchMode=yes n8n-versions-ro@tailscale-nyora-bridge "all" ``` --- ## 5. Incident du 14/09/2026 — Faux positif n8n & correctif appliqué ### Symptôme Le 14/09/2026, Nabil a remarqué que la ligne `n8n` de la table `infra_versions` affichait `statut = À jour` alors que le conteneur (installé en `2.36.5`) accusait en réalité un retard réel vers la version stable `2.38.7` (release GitHub "Latest" du 11/09/2026), avec une beta `2.39.5` également disponible. ### Cause racine Le nœud `Préparer Éléments & Mapping` interroge Docker Hub avec `page_size=25&ordering=last_updated`. Le nœud `Analyser Écarts & Versions` retenait ensuite simplement le **premier** tag de la liste filtrée (`candidateTags[0]`), en supposant implicitement que l'ordre renvoyé par l'API reflète la récence sémantique des versions. Cette hypothèse s'est révélée fausse pour `n8nio/n8n` : le projet a démarré une cadence de publication très dense de tags `v3-rc-*` et `v3-nightly-*` (plusieurs par jour, en préparation de la version 3.0 qui abandonne l'installation npm). Ces tags noient les 25 premières places de `ordering=last_updated` sans jamais correspondre au filtre strict `^[v]?[0-9]+\.[0-9]+\.[0-9]+$`. Résultat : `candidateTags` finissait vide, et le code retombait silencieusement sur l'ancienne valeur stockée (`origItem.current_disponible`) — d'où le faux "à jour" qui se perpétuait semaine après semaine sans jamais être corrigé automatiquement. Vérifié en direct sur l'API Docker Hub le 14/09/2026 : le tag `2.39.5` se trouvait en position **27** sur `ordering=last_updated`, hors de portée de `page_size=25`. ### Correctif appliqué par Claude Deux modifications dans le workflow `veille-versions-stack` (ID `zUWN5K4Q1A2JKFIS`) : 1. `page_size` porté de `25` à `100` dans `Préparer Éléments & Mapping`. 2. Sélection du tag remplacée dans `Analyser Écarts & Versions` : au lieu de `candidateTags[0]`, tri explicite des candidats par comparaison semver (`major.minor.patch` parsés en entiers) et sélection du maximum — robuste indépendamment de l'ordre renvoyé par l'API. Sauvegarde de la définition du workflow conservée avant modification (nœuds JSON complets) avant tout changement. ### Piège opérationnel découvert : édition directe en base ne suffit pas L'édition a été appliquée par `UPDATE workflow_entity SET nodes = ...` directement en Postgres (accès `docker exec n8n-DB psql`), sans passer par l'API n8n (aucune clé API n8n en clair disponible dans les secrets consultés). **Un test du workflow immédiatement après l'UPDATE a continué à produire l'ancien résultat (faux "à jour")**, alors même qu'une relecture de la ligne en base confirmait bien le nouveau code JSON. Cause : n8n garde en mémoire la définition des workflows actifs et ne la recharge pas automatiquement suite à une modification faite hors de son propre mécanisme de sauvegarde/API. **Correctif de contournement** : redémarrage du conteneur `n8n` (`docker restart n8n`) pour forcer le rechargement de tous les workflows actifs depuis la base. Confirmé efficace après coup. **Règle à retenir pour toute future édition directe en base d'un workflow n8n actif (par n'importe quel agent)** : une modification SQL de `workflow_entity.nodes` sur un workflow actif nécessite un `docker restart n8n` pour être réellement prise en compte à l'exécution — la relecture de la ligne en base ne suffit pas à garantir que le moteur en mémoire est à jour. ### Limite résiduelle connue (non corrigée) Le fix élève la fenêtre de recherche de 25 à 100 tags, ce qui règle le cas du 14/09/2026, mais reste théoriquement contournable si la cadence de tags `nightly`/`rc` de n8n s'intensifie encore avant la sortie de la 3.0 (dépassement de 100 tags "bruit" entre deux vraies releases). Aucune pagination multi-pages n'a été implémentée — jugé disproportionné pour un job hebdomadaire, à revisiter si le faux "à jour" réapparaît. ### Correction manuelle ponctuelle de la table Baserow En parallèle du correctif workflow, la ligne `n8n` (id `3`) de `infra_versions` a été corrigée manuellement le 14/09/2026 : `derniere_version_disponible = 2.39.5`, `statut = Retard mineur`, `ecart` précisant la distinction stable (`2.38.7`, cible réelle de mise à jour) vs beta (`2.39.5`, ne jamais cibler la beta en production). ### Dérive documentaire notée au passage (non corrigée) La ligne `bifrost` (id `4`) de la même table reste étiquetée `emplacement = NAS` alors que Bifrost tourne réellement sur le VPS depuis le 04/09/2026 (voir [[bifrost-routing]] / `migration-vps-bifrost-stub-forwarder-20260904.md`). Correction à faire séparément, hors périmète de cet incident. ### Ticket de suite `infra-2026-09-051` (Baserow, assigné à Gemini) : mise à jour effective NAS (n8n vers 2.38.7 stable + gitea/portainer/vaultwarden/crowdsec), avec vérification à froid de version et backup dédié obligatoires avant toute exécution.