nas-runbooks/common/cin-search-tt-migration-doc...

5.9 KiB

Migration cin-search-tt : hors-Docker vers Docker + SMTP OVH -> Infomaniak

Contexte

Le 10/07/2026, Nabil signale que la migration SMTP globale vers Infomaniak (faite la veille) n'a pas couvert cin-search-tt car cette app tournait en dehors de la stack Docker, dans /volume1/web/cin-search-tt (Node.js standalone, jamais containerise).

Audit etendu a tout /volume1/web/ : 4 apps Node y etaient hebergees hors-Docker.

Etat trouve

App Etat Action
cin-search-tt SMTP sur ssl0.ovh.net, Baserow sur ancien alias nd.i234.me, jamais dockerise Migre vers Docker
rla Copie obsolete — la vraie version tourne deja proprement dans /volume1/docker/rla-api (Gotenberg/pptx-tt-api deja purges le 04/07) Archivee (doublon perime)
club-ia Projet termine (jamais deploye en prod) Archivee
weblinks Page HTML statique simple, aucune dependance Conservee en l'etat dans /volume1/web

Actions effectuees — cin-search-tt

  1. Copie du code (hors node_modules/zip) vers /volume1/docker/cin-search-tt
  2. .env corrige :
  3. Dockerfile ecrit (node:20-alpine, npm install --omit=dev)
  4. Image buildee via API Docker de Portainer (POST /api/endpoints/2/docker/build avec tar de contexte) car docker CLI absent du container mcp-nas (hardening 08/07)
  5. Stack deploye via API Portainer (POST /api/stacks/create/standalone/string) — pas de env_file: dans le compose (Portainer ne voit pas les chemins hote arbitraires), variables passees en environment: inline a la place
  6. Container cin-search-tt : port 3094->3000, reseau n8n, volume /volume1/docker/cin-search-tt/data:/app/data (persistance database.json)
  7. ports-registry.md mis a jour (edite via un container alpine ephemere + bind mount, car le fichier appartient a uid 1026 et mcp-nas n'a plus CAP_DAC_OVERRIDE)
  8. Reverse-proxy DSM cin.bolbol.tn -> localhost:3094 NON fait (hors scope API/Docker, a faire manuellement dans DSM Control Panel)
  9. Anciens dossiers archives dans /volume1/web/.archive/ : cin-search-tt.archived-20260710-migrated-to-docker, rla.archived-20260710-obsolete-superseded-by-docker-rla-api, club-ia.archived-20260710

Pieges decouverts (a capitaliser)

  • mcp-nas ne peut pas lancer docker/docker compose directement (binaire absent, SSH host indisponible depuis le hardening). Solution : API REST Portainer (/api/endpoints/{id}/docker/build pour build, /api/stacks/create/standalone/string pour deploy).
  • Portainer ne resout pas env_file: avec un chemin hote dans un stack deploye par API string — le moteur compose de Portainer tourne dans son propre filesystem (/data/compose/<id>/), pas celui de l'hote. Toujours utiliser environment: inline pour les stacks deployes ainsi.
  • Volume bind mounts en chemin absolu hote fonctionnent normalement (resolus par le daemon Docker, pas par Portainer) — contrairement a env_file:.
  • Ecriture de fichiers appartenant a uid 1026 depuis mcp-nas (root) : impossible, meme en root, a cause de cap_drop: [ALL] (pas de CAP_DAC_OVERRIDE). Contournement : creer un container ephemere (alpine) avec bind mount du dossier concerne via l'API Portainer, executer la commande d'ecriture dedans en root reel (container non-hardened), puis le supprimer.
  • Token Gitea GITEA_DEPLOY_TOKEN n'a pas le scope write:organization ni read:user — peut lire/ecrire du contenu de repos existants, mais pas creer de nouveaux repos ni lister les users/orgs. Creation de nouveaux repos = a faire manuellement dans l'UI Gitea.
  • /volume1/docker/ports-registry.md n'est pas versionne dans Gitea (pas de .git a la racine de /volume1/docker) — mise a jour uniquement in-place sur le NAS.

Reste a faire (hors scope automatisable)

  • Creer la regle reverse-proxy DSM cin.bolbol.tn -> localhost:3094
  • Creer le repo Gitea bolbol/cin-search-tt manuellement (token actuel insuffisant) et y pousser le code

Correctif post-deploiement (10/07/2026, meme session)

Nabil a signale "Echec de l'envoi email" apres mise en prod. Deux bugs distincts trouves via les logs container :

  1. SMTP code en dur dans server.js — le transporter nodemailer n'utilisait PAS config.smtp (qui lit le .env) mais des valeurs litterales : host: 'ssl0.ovh.net', user: 'contact@bolbol.tn', pass: '2L2u519wbolbol'. Corriger le .env seul ne changeait donc rien. Patch : les 3 champs (host/port/secure/auth) passes en process.env.SMTP_*. Le From des 2 sendMail() (etait contact@bolbol.tn, adresse OVH desormais coupee) change pour nabil.derouiche@ik.meInfomaniak rejette un From qui ne correspond pas au compte authentifie (meme contrainte deja documentee pour Baserow/Vaultwarden).
  2. BASEROW_API_URL en https:// echouait en interne (ECONNREFUSED 172.27.x.x:443) — sur le reseau Docker n8n, l'alias baserow.bolbol.tn resout directement vers le container Baserow qui n'ecoute qu'en HTTP (port 80, cf. ports-registry.md : 3888->80). Pas de TLS en interne. Corrige en http://baserow.bolbol.tn.

Piege a capitaliser : toujours verifier qu'un service qui lit un .env via config.js utilise vraiment ce module partout — un require('dotenv').config() en tete de fichier n'empeche pas des valeurs codees en dur ailleurs dans le meme fichier. Grep systematique sur host/user/pass/api url avant toute migration de credentials.

Piege reseau : https://<alias>.bolbol.tn ne fonctionne QUE depuis l'exterieur (WAN) ou un service hors du reseau Docker n8n (TLS termine par le reverse-proxy DSM). Un container sur le meme reseau n8n qu'un alias doit taper en http:// sur le port interne reel du service cible (verifier ports-registry.md), jamais supposer que le HTTPS est disponible en interne.