# Trouve-KA — Runbook d'exploitation Author: Simon-Pierre Boucher — Contact: contact@spboucher.ai Architecture : voir `docs/architecture.md`. Résumé : **M2M32** (hub : Postgres+Redis docker, API/web/workers/scheduler/enrichment natifs pm2, ngrok), **M2M32b** (OpenSearch docker, heap 8 G), **m4mc** (embeddings+reranker), satellites de crawl (M2M32c, M4BP48, M1M32, m4ma). Tout le trafic inter-nodes passe par des **tunnels ssh système sur 127.0.0.1** (contournement du blocage « réseau local » macOS, qui filtre par binaire : python non signé bloqué, ssh/curl Apple exempts). ## Auto-guérison (rien à faire dans la plupart des cas) | Mécanisme | Où | Cadence | |---|---|---| | `io.trouveka.boot` (boot.sh) | tous les nodes | au démarrage du node | | `io.trouveka.watchdog` (watchdog.sh) | M2M32 | toutes les 2 min | | Passe de flotte (heal tous les satellites) | M2M32 | ~30 min | | `io.trouveka.backup-pg` / `backup-os` / `pull` | M2M32 / M2M32b | quotidien 03:30–04:40 | | Rétention PG (crawl_attempts 30 j, search_queries 180 j) | scheduler tk-scheduler | quotidien | Prouvé en conditions réelles : API tuée → ressuscitée en 40 s; reboot complet de m4ma → tunnels+worker revenus sans intervention. Journaux : `~/trouveka-watchdog.log`, `~/trouveka-boot.log`, `~/trouveka-backups/backup.log`, `~/trouveka-launchd.log` sur chaque node. ## Clés SSH dédiées (jamais de clé à accès complet sur un node) | Clé | Détenue par | Autorisée sur | Pouvoir exact | |---|---|---|---| | `trouveka_tunnel` (par node) | chaque node | M2M32, M2M32b | port-forwarding seulement | | `trouveka_heal` | M2M32 | tous les satellites | exécuter `boot.sh` uniquement | | `trouveka_pull` | M2M32 ↔ M2M32b | l'autre node | `tar` du dossier de backups uniquement | ⚠️ Toute invocation ssh opérationnelle utilise `ControlMaster=no`, `IdentitiesOnly=yes`, `IdentityAgent=none` — sans quoi le multiplexage/agent d'une session humaine court-circuite les restrictions. ## Pannes et remèdes - **Recherche en panne / site public muet** : attendre 2-4 min (watchdog). Sinon : `ssh M2M32 'sh ~/trouve-ka/scripts/ops/boot.sh'` puis `tail ~/trouveka-watchdog.log`. - **Un node ne crawle plus** : `ssh M2M32` puis `/usr/bin/ssh -i ~/.ssh/trouveka_heal -o IdentitiesOnly=yes -o IdentityAgent=none -o ControlMaster=no -o ControlPath=none simon-pierreboucher@ heal` (IP dans `~/.trouveka-fleet`). - **Après reboot d'un node : Tailscale absent** (app GUI, exige une session). Le moteur n'en dépend PAS (tout passe par le LAN). Pour retrouver l'accès distant direct : ouvrir une session (écran/VNC) une fois, ou passer par `ssh -J M2M32 simon-pierreboucher@`. - **Transactions Postgres zombies** (verrous, autovacuum bloqué) : `SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE usename='trouveka' AND now()-xact_start > interval '5 minutes';` (les timeouts serveur limitent déjà ça à ≤5 min). ## Restauration après sinistre - **Postgres perdu** (dumps : `~/trouveka-backups/pg/` sur M2M32, miroir sur M2M32b `~/trouveka-backups/pg-mirror/`) : `docker exec -i trouve-ka-postgres-1 pg_restore -U trouveka -d trouveka --clean --if-exists < trouveka-YYYYMMDD.dump` - **OpenSearch perdu** (snapshots : `~/trouveka-os-snapshots/` sur M2M32b, miroir sur M2M32 `~/trouveka-backups/os-mirror/`) : recréer le container avec `path.repo=/mnt/snapshots` + le volume, puis `PUT _snapshot/trouveka-fs` (même corps que backup-os.sh) et `POST _snapshot/trouveka-fs/daily-YYYYMMDD/_restore`. Si les deux copies sont perdues : le moteur se reconstruit par recrawl (Postgres garde URLs/domaines/priorités — c'est lui le capital). - **Un node de crawl perdu** : rien à restaurer — réinstaller le rôle : `SUDO_PW=... sh ~/trouve-ka/scripts/ops/install-node.sh crawler` + clé tunnel (voir mémoire projet). ## Déploiement de code ``` rsync -az --delete --exclude .env --exclude .venv --exclude .venv-embed \ --exclude node_modules --exclude .next --exclude __pycache__ --exclude .git \ /Users/simon-pierreboucher/Desktop/trouve-ka/ :trouve-ka/ # CHEMIN ABSOLU ! ssh M2M32 'pm2 restart tk-api tk-crawler-1 tk-crawler-2 tk-enrichment tk-scheduler' # web : cd ~/trouve-ka/apps/web && pnpm build && pm2 restart tk-web # satellites : heal (boot.sh relance le worker avec le nouveau code après pkill) ```