4.4 KiB
4.4 KiB
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, filebrowser, dsh, mcp-vps
Statut : valide (testé et vérifié en direct sur VPS Contabo)
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 :
- Un Workspace Switcher latéral fluide et étanche entre les 4 univers.
- Un Sélecteur Toggle DSH (conception Claude Design) pour basculer instantanément entre la session et l'explorateur de fichiers DSH (
/u/nabil/files/). - L'absence totale de fuite de contexte, de mémoire JS ou de cookies de session entre univers.
- 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 VPS ↔ NAS : maillage Tailscale (
100.86.197.88NAS ↔100.94.90.119VPS). - Communication interne VPS : raccordement de
hermes-hubà deux réseaux Docker :dsh_vps_net: pour joindredsh-vps-filebrowser:8080ethermes-nabil:9119.mcp-vps: pour être joint directement par le conteneurcloudflared-mcp-vpsviahttp://hermes-hub:8080.
- Communication VPS ↔ NAS : maillage Tailscale (
- Port Hermes Hub : Port 8088 bindé sur
127.0.0.1pour diagnostics SSH locaux, mais le tunnel Cloudflare passe en direct conteneur-à-conteneur sur le réseaumcp-vps. - Port Hermes Perso : Port 3031 fixé définitivement sur le NAS (port 3030 bloqué et purgé).
- Sécurité & Auth : Authentification Cloudflare Access en amont du tunnel Cloudflare (
hub.yesminedor.tn -> http://hermes-hub:8080). - Filebrowser DSH : Conteneur existant
dsh-vps-filebrowser, image épinglée en SemVerfilebrowser/filebrowser:v2.32.0, configuré avecauth.method=noauthetbaseurl=/u/nabil/files. - Montage DSH : Volume nommé
dsh_vps_workspacemonté sur/srv(Read-Write). - UID/GID : Hub exécuté sous
1026:100, Filebrowser sous1001:1001(dsh-agent).
Ce qui NE fonctionne PAS
| Tentative | Erreur obtenue / Risque | Raison de l'échec / Solution adoptée |
|---|---|---|
| Déploiement sur port 8080 | Conflit de port / Page blanche | Port 8080 déjà occupé par qbittorrent sur le VPS. Port 8088 réservé et bindé sur 127.0.0.1. |
| Ingress Cloudflare vers 127.0.0.1:8088 | 502 Bad Gateway | cloudflared tourne dans le réseau Docker mcp-vps. Bind loopback refuse les paquets non-locaux. hermes-hub raccordé à mcp-vps (http://hermes-hub:8080). |
| TemplateResponse("index.html", context) | 500 TypeError: unhashable dict | Signature Starlette dépréciée. Remplacée par TemplateResponse(request, "index.html", context). |
| Dépendances non figées | Régression silencieuse au build | Versions exactes figées dans requirements.txt via pip freeze. |
Tag :latest sur Filebrowser |
Risque de régression | Image SemVer épinglée : filebrowser/filebrowser:v2.32.0. |
Solution validée & Déploiement Réel
1. Dépôt & Code source
- Dépôt Gitea :
http://192.168.100.33:3232/bolbol/hermes-hub.git(branchemain, commitb6ce978). - Emplacement sur VPS :
/home/dsh-agent/hermes-hub.
2. Configuration Cloudflare Tunnel Ingress (Action Nabil)
Dans le dashboard Cloudflare Zero Trust / Tunnels (mcp-vps) :
- Hostname :
hub.yesminedor.tn - Service Type :
HTTP - URL :
hermes-hub:8080(ouhttp://hermes-hub:8080)
Preuves Directes de Fonctionnement (Vérification interne mcp-vps)
# Test exécuté depuis linux-mcp-vps sur le réseau partagé mcp-vps :
OK [HTTP 200] -> http://hermes-hub:8080/ (9385 bytes)
OK [HTTP 200] -> http://hermes-hub:8080/api/health (45 bytes)
OK [HTTP 200] -> http://hermes-hub:8080/api/universes (1927 bytes)
OK [HTTP 200] -> http://hermes-hub:8080/u/nabil/files/ (6112 bytes)