84 lines
6.7 KiB
Markdown
84 lines
6.7 KiB
Markdown
# VPS memory-node — Objectif A : nœud mémoire persistante (10/07/2026)
|
||
|
||
**Statut** : en production. Le VPS Contabo (`contabo-vps-qbt`, tailnet 100.94.90.119) réplique en continu la mémoire du NAS : miroir git `nas-runbooks`, données NyoraNotes et context-hub, avec snapshots restic versionnés.
|
||
|
||
## Architecture — PULL depuis le VPS (pas push depuis le NAS)
|
||
Choix imposé par deux constats du 10/07 :
|
||
1. Pas de sudo/cron direct sur le NAS pour Claude (décision Nabil 10/07, définitive : le mot de passe sudo n'est pas transmis ; les crons NAS passent par le **Planificateur de tâches DSM en root** — Nabil crée les tâches, Claude écrit les scripts ; le root ponctuel se fait en session interactive avec Nabil).
|
||
2. **NAS→VPS port 22 KO par le tailnet** (timeout), alors que VPS→NAS fonctionne. Cause : Tailscale Synology en mode userspace. Conséquence jour J : le « delta final NAS→VPS » se fera en **pull depuis le VPS**.
|
||
|
||
Tout tourne donc sur le VPS, user **`claude-oversight`** (cron) :
|
||
|
||
| Quoi | Script | Cadence |
|
||
|---|---|---|
|
||
| Miroir git + rsync données | `/opt/memory-node/bin/memory-sync.sh` | horaire (h+17) |
|
||
| Snapshot restic | `/opt/memory-node/bin/backup-push.sh` | quotidien 03:30 |
|
||
| Vérif intégrité + restauration test | `/opt/memory-node/bin/backup-verify.sh` | hebdo dim. 04:00 |
|
||
|
||
Échec de job → alerte Telegram (bot hermes-perso → Nabil) via `notify-telegram.sh`.
|
||
|
||
## Contenu répliqué
|
||
- `/opt/memory-node/git/nas-runbooks.git` : miroir bare, pull horaire depuis Gitea (`100.86.197.88:3232`, token Gitea lecture `vps-memory-node-mirror`, credentials dans la config du remote, home 700).
|
||
- `/opt/memory-node/data/nyora-notes/` et `data/context-hub/` : rsync `--delete` depuis `/volume1/docker/…`.
|
||
- **Exclusions délibérées** : `.env`, `*.bak`, `@eaDir`, `.DS_Store` — aucun secret répliqué sur le VPS ; les `.env` se récupèrent via le backup USB.
|
||
- Snapshots restic : `/opt/restic-repo` (rétention 14 j + 8 sem., `forget --prune` à chaque push).
|
||
|
||
## Mot de passe restic — emplacements (jamais dans ce repo)
|
||
- **Maître** : NAS `/volume1/docker/scripts/.restic-password` (chmod 600, Best0f).
|
||
- **Copie runtime** : VPS `/opt/memory-node/.restic-pass` (chmod 600, claude-oversight) — nécessaire car restic s'exécute sur le VPS.
|
||
- Les deux fichiers contiennent la même valeur. Si rotation : regénérer sur le NAS, recopier sur le VPS, `restic init` d'un nouveau repo (l'ancien devient illisible).
|
||
|
||
## Accès VPS
|
||
- **Tailscale SSH uniquement** (port 22 tailnet ; 22 public filtré par ufw, 2222/22222 fermés). `root` = mode `check` (ré-auth web périodique) ; `claude-oversight` = accept.
|
||
- `claude-oversight` : **sudoers scopé** (`/etc/sudoers.d/claude-oversight`) — start/stop/restart de qbittorrent-nox, docker, tailscaled + journalctl/status. PAS de NOPASSWD:ALL.
|
||
- Connexion interactive claude-oversight → alerte Telegram (`/etc/profile.d/claude-oversight-login-alert.sh`).
|
||
- Docker 29 + compose v5 installés (prérequis doublure jour J), aucun conteneur lancé.
|
||
|
||
## Accès NAS depuis le VPS (le seul sens qui marche)
|
||
Clé `id_ed25519` de claude-oversight autorisée pour Best0f (port 22222) mais **bridée par forced-command** `~/.ssh/vps-memory-pull.sh` :
|
||
- source exigée 127.0.0.1 (= proxy userspace Tailscale ; un `from="100.94.90.119"` classique ne marche PAS, le NAS voit 127.0.0.1) ;
|
||
- seule commande admise : `rsync --server --sender` (lecture seule) sur `nyora-notes/` et `context-hub/`.
|
||
|
||
## Vérifications rapides
|
||
```bash
|
||
ssh claude-oversight@100.94.90.119 # depuis le Mac (tailnet)
|
||
tail /opt/memory-node/log/memory-sync.log # rc=0 attendu
|
||
restic -r /opt/restic-repo --password-file /opt/memory-node/.restic-pass snapshots --compact
|
||
git -C /opt/memory-node/git/nas-runbooks.git log --oneline -1 # doit suivre Gitea à 1 h près
|
||
```
|
||
|
||
## Restauration (perte du NAS)
|
||
1. `git clone /opt/memory-node/git/nas-runbooks.git` → savoir complet.
|
||
2. `restic restore latest --target /tmp/r` → données NyoraNotes/context-hub datées.
|
||
3. Relancer les services sur le VPS avec ces données (Docker déjà prêt).
|
||
|
||
## Reste à faire (hors Objectif A)
|
||
- Renommer le nœud tailnet NAS `ahmed---yesmine` → `nas` (Nabil, console admin Tailscale).
|
||
|
||
---
|
||
|
||
# Incident mot de passe — audit de purge (10–11/07/2026)
|
||
|
||
L'ex-mot de passe sudo Best0f (périmé, non remplacé : root NAS = Planificateur DSM + sessions interactives) a été purgé de partout où il traînait. **Anti-pattern racine** : le skill Hermes `nas-executor` (09/06/2026) l'avait **hardcodé en `SSHPASS="…"` (10×)** — de là il s'est propagé dans les backups de skills, la base d'état de l'agent, le repo git et le backup USB. Règle : un skill lit ses secrets depuis l'env/.env, jamais en littéral.
|
||
|
||
## Emplacements scannés — PROPRES
|
||
Arbre + historique git `nas-runbooks` ; historiques git `hermes-skills`, `hermes-platform`, `linux-mcp-nas`, `nabil-brain`, `claude-cowork-nas` ; vault NyoraNotes (md + SQLite via strings) ; context-hub (données + SQLite) ; `data/` hermes-tt et hermes-nyora ; *.md racine `/volume1/docker`, clone STALE, `claude_contexte/` ; pingvin ; historiques shell Best0f (inexistants) ; USB `_memoire/` ; VPS `/opt/memory-node/`.
|
||
|
||
## PURGÉS (10–11/07)
|
||
- Mémoire Claude (Mac) : 3 fichiers réécrits sans la valeur.
|
||
- `hermes-perso/data/backups/skills-20260609-214432/…/nas-executor/` : `SKILL.md` + `references/dsm-api-access.md` (11 occ. → `[REDACTED-purge-20260711]`).
|
||
- `hermes-perso/data/state.db.corrupt-20260709-231035` (407 Mo) : rédaction binaire à longueur constante, 0 occ. restante.
|
||
- Repo Gitea `hermes-perso` HEAD : commit `64fdcc5` (`SSHPASS` → `$NAS_SSH_PASSWORD`). Le repo était en retard sur le live.
|
||
|
||
## RÉSIDUELS — session interactive root requise
|
||
- `linux-mcp-nas/audit.log` (root:root 600, invérifiable sans root) — l'historique avait été scrubbé le 08/07, à confirmer/`sed` si besoin.
|
||
- **Backup USB** (Best0f sans écriture) : 4 fichiers skills (sets 04/07 et 10/07) + `state.db.corrupt` (set 10/07) — versions non purgées.
|
||
- `/volume1/@docker/volumes/` : non scannable sans root.
|
||
|
||
## RÉSIDUEL ACCEPTÉ (à trancher)
|
||
- Historique git `hermes-perso` : le commit `574faf1` (intro du skill) contient le mot de passe. Réécriture d'historique = lourde ; mot de passe **périmé** + repo privé LAN → **acceptation documentée recommandée**.
|
||
|
||
## Constats connexes (hors purge, à corriger)
|
||
- Le skill **live** `nas-executor` (hermes-perso) hardcode **un autre secret actif** (`SSHPASS=…`, 3×) — même anti-pattern, à passer en variable d'env.
|
||
- L'arbre courant de `nas-runbooks` contient encore des secrets famille `2L2u519w*` en clair (bestof/DSM dans HEBERGEMENT-SITES-STATIQUES.md, cin-search-tt…) : la **rotation totale** demandée par l'audit mcp-nas du 08/07 reste à faire.
|