58 lines
4.1 KiB
Markdown
58 lines
4.1 KiB
Markdown
# Hermes Hub — Déploiement et Exploitation Multi-Univers sur VPS
|
|
|
|
**Instance auteur** : gemini / nabil
|
|
**Date** : 2026-08-20
|
|
**Tags** : hermes, hub, multi-univers, vps, tailscale, cloudflare-access, fastapi, subdomains, filebrowser, dsh, basic-auth, security-audit, stateless-proxy
|
|
**Statut** : valide (testé et vérifié en direct sur VPS Contabo avec transport HTTP 100% sans état)
|
|
|
|
---
|
|
|
|
## Problème
|
|
|
|
Nabil dispose de 4 instances Hermes strictement cloisonnées :
|
|
- **TT** (`hermes-tt`, port 3010, NAS Synology) — Achats Zone Sud, Tunisie Telecom
|
|
- **Nyora** (`hermes-nyora`, port 3020, NAS Synology) — Venture perso, Dr Nexum
|
|
- **Perso** (`hermes-perso`, port 3031, NAS Synology) — Famille, personnel, santé
|
|
- **Nabil** (`hermes-nabil`, port 9119, VPS Contabo) — Master agent & DeepSeek Harness (DSH)
|
|
|
|
L'objectif est d'offrir une interface web unifiée sur le VPS Contabo (`100.94.90.119`) avec :
|
|
1. Un **Workspace Switcher** latéral fluide et étanche entre les 4 univers.
|
|
2. Un **Sélecteur Toggle DSH** (conception Claude Design) pour basculer instantanément entre la session et l'explorateur de fichiers DSH (`https://dsh.hub.yesminedor.tn/`).
|
|
3. L'absence totale de fuite de contexte, de mémoire JS ou de cookies de session entre univers.
|
|
4. La résolution 100% native des assets absolus (`/assets/main-*.js`) via un routage par **sous-domaine dédié** (`*.hub.yesminedor.tn`).
|
|
5. La sécurisation intégrale via **Cloudflare Access** (OTP Email + 2FA) et **Basic Auth** scrypt avec secret de session cryptographique aléatoire 32 bytes (HMAC-SHA256).
|
|
6. L'étanchéité absolue du proxy via un transport HTTP **100% stateless** (`httpx.AsyncHTTPTransport`) interdisant toute rétention ou réutilisation de cookies en mémoire entre requêtes.
|
|
|
|
---
|
|
|
|
## Cause de l'incident et Résolution Architectural
|
|
|
|
### 1. Cause racine identifiée
|
|
Le proxy utilisait un singleton `httpx.AsyncClient` partagé. Par défaut dans HTTPX, un client gère un cookie jar interne (`client.cookies`). Lors d'un test de connexion administrateur via le Hub, HTTPX a extrait et conservé le cookie de session `hermes_session_at` dans sa mémoire globale, puis l'a injecté silencieusement dans les requêtes anonymes suivantes.
|
|
|
|
### 2. Correctif architectural appliqué
|
|
Le module `app/proxy.py` a été migré vers **`httpx.AsyncHTTPTransport`** :
|
|
- Transport HTTP brut de niveau réseau (sans aucune structure de stockage de cookies).
|
|
- Aucune rétention de cookie possible en mémoire.
|
|
- Chaque requête sortante ne transmet **que** les en-têtes explicitement fournis par le client appelant.
|
|
|
|
---
|
|
|
|
## Matrice Complète d'Audit de Sécurité des Routes API (`nabil.hub.yesminedor.tn`)
|
|
|
|
| Route API | Description | Anonyme (sans cookie) | Authentifié (avec cookie) | Statut Audit |
|
|
|-----------|-------------|-----------------------|---------------------------|--------------|
|
|
| `/api/sessions` | Historique des sessions (Sensible) | **401 Unauthorized** | **200 OK** | ✅ Conforme |
|
|
| `/api/profiles` | Profils & Personas | **401 Unauthorized** | **200 OK** | ✅ Conforme |
|
|
| `/api/skills` | Compétences & Outils | **401 Unauthorized** | **200 OK** | ✅ Conforme |
|
|
| `/api/memory` | Vecteurs & Mémoire | **401 Unauthorized** | **200 OK** | ✅ Conforme |
|
|
| `/api/credentials/pool` | Pool d'identifiants | **401 Unauthorized** | **200 OK** | ✅ Conforme |
|
|
| `/api/config/raw` | Configuration brute & Clés | **401 Unauthorized** | **200 OK** | ✅ Conforme |
|
|
| `/api/mcp/catalog` | Catalogues MCP | **401 Unauthorized** | **200 OK** | ✅ Conforme |
|
|
| `/api/webhooks` | Configuration Webhooks | **401 Unauthorized** | **200 OK** | ✅ Conforme |
|
|
| `/api/analytics/usage` | Statistiques & Utilisation | **401 Unauthorized** | **200 OK** | ✅ Conforme |
|
|
| `/api/plugins/kanban/board` | Tableaux & Tâches Kanban | **401 Unauthorized** | **200 OK** | ✅ Conforme |
|
|
| `/api/auth/providers` | Découverte des auth providers | **200 OK** (Public) | **200 OK** | ✅ Conforme |
|
|
| `/api/status` | Sonde de statut / liveness | **200 OK** (Public) | **200 OK** | ✅ Conforme |
|
|
| `/api/health` | Sonde de santé globale | **200 OK** (Public) | **200 OK** | ✅ Conforme |
|