Files
nas-runbooks/common/hermes-hub-deploiement.md
T

4.6 KiB

Hermes Hub — Déploiement et Exploitation Multi-Univers sur VPS

Instance auteur : gemini / nabil
Date : 2026-08-19
Tags : hermes, hub, multi-univers, vps, tailscale, cloudflare-access, fastapi, filebrowser, dsh
Statut : valide


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, local loopback, VPS Contabo) — Master agent & DeepSeek Harness (DSH)

L'objectif est d'offrir une interface web unifiée sur le VPS Contabo 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 de dialogue et l'explorateur de fichiers DSH (/u/nabil/files/).
  3. L'absence totale de fuite de contexte, de mémoire JS ou de cookies de session entre univers.
  4. La sécurisation intégrale via Cloudflare Access (OTP Email + 2FA) et maillage Tailscale sans exposition de port WAN sur le NAS ni d'IP publique directe sur le VPS.

Contexte et contraintes

  • Réseau : Communication exclusive via le maillage Tailscale (100.86.197.88 NAS ↔ 100.94.90.119 VPS).
  • Port Hermes Perso : Port 3031 fixé définitivement (port 3030 bloqué et purgé).
  • Sécurité & Auth : Authentification Cloudflare Access en amont du tunnel Cloudflare (hub.yesminedor.tn).
  • Filebrowser DSH : Image épinglée en SemVer filebrowser/filebrowser:v2.32.0 (jamais :latest), lancée avec --noauth (délégué à Cloudflare Access) et thème sombre (--branding.theme=dark).
  • Montage DSH : Montage Read-Write strict sur /home/dsh-agent/dsh-vps/workspace vers /srv (la racine utilisateur avec clés SSH et wrappers reste protégée).
  • UID/GID : Hub exécuté sous 1026:100, Filebrowser sous : (1001:1001).

Ce qui NE fonctionne PAS

Tentative Erreur obtenue / Risque Raison de l'échec / Solution adoptée
Tunnel WireGuard wg-easy 0 B reçus, timeout wg-easy décommissionné le 08/07/2026. Remplacé nativement par Tailscale (44 ms).
Port 3030 pour hermes-perso Port bloqué / conflit Processus docker-proxy orphelin sur l'hôte NAS. Port 3031 fixé et 3030 bloqué via iptables.
Tag :latest sur Filebrowser Risque de régression Règle de gouvernance : tag SemVer exact fixé sur filebrowser/filebrowser:v2.32.0.
Auth interne filebrowser.db Double login inutile Cloudflare Access + 2FA constitue le garde-fou unique suffisant. Filebrowser démarré avec --noauth.
Montage de la racine /home/dsh-agent Fuite de clés SSH Restriction stricte au seul sous-dossier workspace/.

Solution validée

1. Dépôt & Code source

  • Dépôt Gitea : http://192.168.100.33:3232/bolbol/hermes-hub.git
  • Stack : FastAPI + Async Streaming Proxy (httpx) + Design Tokens + Sélecteur Toggle DSH (Claude Design).

2. Déploiement sur VPS Contabo (100.94.90.119)

# 1. Cloner le dépôt
git clone http://bolbol:PASSWORD@100.86.197.88:3232/bolbol/hermes-hub.git ~/hermes-hub
cd ~/hermes-hub

# 2. Configurer l'environnement (.env)
cp .env.example .env
# Définir HUB_SECRET (openssl rand -hex 32) et les UIDs dsh-agent

# 3. Lancer le stack Hub + Filebrowser
docker compose up -d --build

3. Routage & Cloudflare Tunnel

  • Ingress Cloudflare Tunnel (cloudflared) : hub.yesminedor.tn -> http://127.0.0.1:8080
  • Application Cloudflare Access : politique Email OTP autorisée.

Vérification

# 1. Vérification santé Hub
curl -fsS http://127.0.0.1:8080/api/health
# Résultat attendu : {"status":"healthy","universes_configured":4}

# 2. Vérification connectivité multi-univers
curl -fsS http://127.0.0.1:8080/api/universes

# 3. Test du proxy Filebrowser
curl -fsS -I http://127.0.0.1:8080/u/nabil/files/
# Résultat attendu : HTTP/1.1 200 OK

Pièges spécifiques

  • Cloisonnement des cookies : L'attribut Path des en-têtes Set-Cookie émis par les backends est réécrit à la volée vers Path=/u/{universe_id}/ pour interdire toute collision entre univers sous le même domaine.
  • Purge mémoire front-end : À chaque changement d'univers, l'iframe charge d'abord about:blank pour détruire le state DOM/JS résiduel avant de monter le nouvel univers.