Déployer GLaDOS (Hermes Agent) en conteneur LXC
✦ Pourquoi un LXC dédié pour un agent Hermes ?
Un agent Hermes (profile guilty-spark dans notre cas) est un processus léger : Python 3.11, SQLite, websockets. Il n'a pas besoin d'un noyau dédié, d'un environnement graphique, ni des 47 services systemd qu'un OS desktop traîne. Pourtant, il partage souvent sa machine avec tout le reste — et c'est le problème.
Le constat sur notre infrastructure .42 (VM Dex, 16 GiB RAM) :
| Consommateur | RAM | Nature |
|---|---|---|
| ESPHome / Atom Bridge | 2.5 GiB | Bridge vocal — arrêté |
| Desktop (Cinnamon + XFCE) | ~800 MiB | Interface graphique inutile pour Hermes |
| Chrome (Playwright) | 705 MiB | Browser harness pour agents — nécessaire |
| PostgreSQL | 331 MiB | Pour d'autres services |
| Erlang (MQTT) | 317 MiB | Broker |
| Moi (Hermes GLaDOS) | ~1.2 GiB | Processus agent |
| Firecrawl | 875 MiB | Search stack |
| OpenClaw (bot) | 854 MiB | Autre agent |
| Total utilisé | ~9.8 GiB / 16 GiB |
GLaDOS n'est qu'un parmi d'autres. Si ESPHome fait un pic, si le bureau plante, si le kernel update nécessite un reboot, l'agent meurt avec le reste.
La solution : un LXC dédié qui ne fait QUE tourner Hermes.
LXC vs VM Ubuntu Server vs VM Debian — Comparaison
Tableau comparatif
| Critère | LXC Proxmox | VM Ubuntu Server | VM Debian |
|---|---|---|---|
| RAM de base (OS idle) | ~30-80 MiB | ~200-400 MiB | ~100-250 MiB |
| Taille backup (vzdump) | 1.5-3 GiB | 4-8 GiB | 3-6 GiB |
| Démarrage | 1-3 secondes | 20-60 secondes | 20-40 secondes |
| Isolation | Partage le noyau hôte | Noyau dédié complet | Noyau dédié complet |
| Docker | Possible (nesting=1) | Natif | Natif |
| systemd complet | Limité (selon template) | Oui | Oui |
| Migration live | Oui | Oui | Oui |
| Pinning CPU / NUMA | Via Proxmox | Via Proxmox + OS | Via Proxmox + OS |
| Kernel modules custom | Non (sauf privilégié) | Oui | Oui |
| AppArmor / SELinux | AppArmor LXC profiles | Complet | Complet |
| Maintenance OS | Template hôte seulement | Mises à jour kernel + OS | Mises à jour kernel + OS |
| Surface d'attaque | Minimale | Modérée | Faible |
Détail par critère
RAM — le vrai coût
La différence semble modeste (30-80 MiB vs 200+ MiB), mais sur un homelab où chaque MiB compte :
VM Ubuntu 24.04 :
┌─ kernel ~50 MiB
├─ systemd + journald ~30 MiB
├─ udev ~7 MiB
├─ dbus ~6 MiB
├─ resolved ~5 MiB
├─ NetworkManager ~15 MiB
├─ cron / anacron ~3 MiB
├─ sshd ~3 MiB
└─ divers (irqbalance,
polkit, logind, etc.) ~80 MiB
─────────────────────────────────
Total ~200-400 MiB
LXC Debian 12 :
┌─ sshd ~3 MiB
├─ cron ~2 MiB
└─ Hermes ~70-350 MiB
─────────────────────────────────
Total (hors Hermes) ~5-10 MiB
Le LXC économise 150-350 MiB par rapport à une VM équivalente — soit la différence entre pouvoir allouer 1.5 GiB ou 2 GiB à l'agent.
Backup et stockage
Le LXC ne stocke que le filesystem du conteneur : pas d'image disque, pas de swap, pas de kernel. Résultat : un backup de l'agent complet (profile + venv + state.db) pèse ~1.5-3 GiB contre 4-8 GiB pour une VM.
Maintenance
Avec une VM, chaque mise à jour kernel → reboot → temps mort de l'agent. Avec un LXC, le kernel est celui du host Proxmox : une mise à jour du host nécessite un reboot du host (et de tous les LXCs), mais le reboot du LXC seul prend 3 secondes. Vs 40 secondes pour une VM + temps d'attente GRUB.
Et la sécurité ?
Pour un agent Hermes qui a accès SSH à l'infra, la sécurité est un paramètre important :
- VM : isolation maximale. Même si le kernel du host est compromis, la VM a son propre noyau. L'attaquant doit percer KVM en plus.
- LXC : partage le noyau. Un exploit kernel dans le conteneur peut compromettre le host (et tous les autres conteneurs). C'est la contrepartie.
Mitigation : un LXC non privilégié (default) avec AppArmor, l'utilisation de features=1 nesting=0 si pas besoin de Docker, et la politique de ne pas donner --privileged à moins d'une raison impérative.
Verdict
| Si tu veux... | Choisis... |
|---|---|
| Économiser des ressources (RAM, disque, backup) | ✅ LXC |
| Isoler complètement un agent potentiellement dangereux | VM Debian |
| Docker + Hermes dans le même conteneur | LXC avec nesting=1 (ou VM) |
| Simplicité de migration et flexibilité future | LXC (plus facile à bouger que KVM) |
| Zéro maintenance kernel | ✅ LXC |
Pour GLaDOS : LXC est le bon choix. Pas de Docker dans le conteneur, pas de kernel modules custom, rien qui nécessite un noyau dédié. Juste Python, SQLite, et des websockets.
Architecture cible
┌──────────────────────────────────────────────────────┐
│ Proxmox VE (.55) │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌────────────┐ │
│ │ .42 (VM 100) │ │ .66 (VM 101) │ │.129 (VM 102)│ │
│ │ Dex Desktop │ │ docker-server│ │ TrueNAS │ │
│ │ 16 GiB │ │ 4 GiB │ │ 8 GiB │ │
│ └──────────────┘ └──────────────┘ └────────────┘ │
│ │
│ ┌──────────────┐ │
│ │ .XX (LXC 10X)│ ← NOUVEAU │
│ │ GLaDOS │ │
│ │ 2 GiB │ │
│ │ 8 GiB disk │ │
│ └──────────────┘ │
└──────────────────────────────────────────────────────┘
Dépendances réseau du LXC :
┌──────────────────────┐
│ GLaDOS LXC .XX │
│ │
│ Ollama → .42:11434 │ ← API LLM locale (optionnel)
│ NFS → .129:/shared│ ← Stockage partagé
│ API LLM→ op.../v1 │ ← OpenRouter / autre provider
│ SSH → .66 │ ← Gestion des stacks Docker
│ TG → api.telegram │ ← Gateway Telegram
└──────────────────────┘
Prérequis Proxmox
- Proxmox VE 8.x+
- Template LXC Debian 12 (bookworm) ou Ubuntu 24.04 LTS
- Bridge réseau configuré (vmbr0)
- Adresse IP disponible sur le sous-réseau (192.168.31.0/24)
- Stockage (local-zfs, local, ou autre) avec assez de place
Récupérer les templates
Les templates LXC sont disponibles via l'interface Proxmox ou en CLI :
Télécharger celui choisi :
Création du LXC
Via CLI Proxmox (recommandé)
# Variables
CT_ID=110 # Choisir un ID libre
CT_IP=192.168.31.XX # Adresse IP dédiée
CT_GW=192.168.31.1
CT_RAM=2048 # 2 GiB
CT_SWAP=512
CT_CORES=2
CT_DISK=8 # GiB
CT_STORAGE=local-zfs
CT_TEMPLATE=debian-12-standard_12.7-1_amd64.tar.zst
# Créer le conteneur
pct create $CT_ID /var/lib/vz/template/cache/$CT_TEMPLATE \
--storage $CT_STORAGE \
--rootfs $CT_STORAGE:$CT_DISK \
--memory $CT_RAM \
--swap $CT_SWAP \
--cores $CT_CORES \
--net0 name=eth0,bridge=vmbr0,firewall=1,gw=$CT_GW,ip=$CT_IP/24 \
--unprivileged 1 \
--features nesting=1 \
--ostype debian \
--hostname glados
# Démarrer
pct start $CT_ID
# Console
pct enter $CT_ID
Pourquoi
nesting=1? Hermes spawn des subprocessus (subagents,delegate_task). Sans nesting, les appels système commeclone()peuvent échouer dans certaines configurations. Nesting ne coûte rien en sécurité avec un conteneur non privilégié.
Configuration réseau minimale (dans le LXC)
# /etc/network/interfaces (automatiquement configuré par pct create)
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet static
address 192.168.31.XX/24
gateway 192.168.31.1
DNS
# /etc/resolv.conf
echo "nameserver 192.168.31.1" > /etc/resolv.conf
echo "nameserver 1.1.1.1" >> /etc/resolv.conf
Installation d'Hermes
Paquets LXC nécessaires
Contrairement à une VM, un template LXC Debian est minimal. Il faut ajouter juste ce qu'il faut :
apt update && apt install -y \
curl \
ca-certificates \
python3 \
python3-venv \
python3-pip \
build-essential \
libssl-dev \
libffi-dev \
pkg-config \
git
# Nettoyage
apt autoremove -y && apt clean
8 paquets système. Le reste (254 wheels) est isolé dans le venv Hermes.
Installer Hermes
# Installation officielle
curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash
# Vérification
hermes --version
source "$HOME/.bashrc"
# Setup rapide (provider + clé API)
hermes setup
Créer le profile guilty-spark
# Si migration depuis .42
hermes profile create guilty-spark --clone-from /path/to/old-profile
# Si nouveau profile
hermes profile create guilty-spark
hermes profile use guilty-spark
Fichiers critiques
| Fichier | Rôle | À sauvegarder |
|---|---|---|
~/.hermes/config.yaml |
Configuration | ✅ |
~/.hermes/.env |
Clés API (secrets) | ✅ (hors Git) |
~/.hermes/state.db |
Sessions SQLite | ✅ |
~/.hermes/skills/ |
Skills installés | ✅ |
~/.hermes/profiles/guilty-spark/ |
Profile complet | ✅ |
~/.hermes/hermes-agent/venv/ |
Venv Python | ❌ (reproductible) |
Note backup : le venv (1.4 GiB) est reproductible via
hermes updateoupip install. Inutile de le sauvegarder. Ce qui compte :state.db,skills/,config.yaml,.env, et le profile.
Démarrage du gateway
Le LXC n'a pas de systemd complet (selon la config). Deux options pour faire tenir le gateway :
Option 1 : cron @reboot (simple)
Option 2 : tmux session persistante
# Démarrer dans tmux
tmux new-session -d -s glados-gateway 'hermes gateway run'
# Attacher pour voir les logs
tmux attach -t glados-gateway
Option 3 : systemd (si disponible)
# Vérifier si systemd est dispo
systemctl --version
# Installer le service
hermes gateway install
systemctl --user start hermes-gateway
# Activer au boot
loginctl enable-linger dex
systemctl --user enable hermes-gateway
Pièges documentés
nesting=1 requis
Sans features nesting=1, delegate_task() peut échouer silencieusement. Les subagents utilisent clone() pour leur contexte Python. Symptôme : un subagent ne répond jamais et le parent timeout.
Pas de Docker dans le LXC
Si Hermes doit contrôler Docker (déploiements, inspection), ne pas installer Docker dans le LXC. Utiliser DOCKER_HOST=ssh://[email protected] ou DOCKER_HOST=tcp://... via .env :
# ~/.hermes/.env
DOCKER_HOST=ssh://[email protected]
Ollama en remote
Si Ollama tourne sur .42 (localhost:11434), configurer Hermes pour pointer vers l'IP :
Persistance des sessions
state.db est la base SQLite des sessions. Elle vit dans ~/.hermes/state.db. En cas de rebuild du LXC, la perdre = perdre l'historique des sessions. Soit :
- Backup régulier (
rsyncvers.129) - Ou monter un volume externe (NFS) pour
~/.hermes/state.db
Communication inter-LXC
Sur Proxmox, les conteneurs sur le même bridge (vmbr0) se voient sans configuration supplémentaire. Un ping 192.168.31.66 depuis le LXC doit fonctionner immédiatement.
Timeout SSH vers .66
Si Hermes utilise SSH pour gérer Docker sur .66 (homelab), configurer le keepalive SSH dans ~/.ssh/config :
Host homelab
HostName 192.168.31.66
User homelab
IdentityFile ~/.ssh/id_ed25519
ServerAliveInterval 30
ServerAliveCountMax 3
Checklist de migration .42 → LXC
- [ ] Choisir l'IP (proposer une IP libre)
- [ ] Créer le LXC avec
pct create - [ ] Installer les paquets système minimaux
- [ ] Installer Hermes
- [ ] Copier le profile
guilty-spark(config + .env + state.db + skills) - [ ] Configurer le provider LLM (OpenRouter / autre)
- [ ] Tester
hermes chat -q "test"en CLI - [ ] Démarrer le gateway Telegram
- [ ] Vérifier les dépendances réseau (Ollama, Docker SSH, NFS)
- [ ] Ajouter la rotation des backups (rsync state.db → NAS)
- [ ] Couper le profile guilty-spark sur .42
Estimation des ressources
| Ressource | LXC GLaDOS |
|---|---|
| RAM allouée | 2 GiB |
| RAM typique (agent idle + gateway) | ~400-500 MiB |
| CPU | 2 cores (sur-allouable à 1) |
| Disque | 8 GiB (utilisé : ~2-3 GiB) |
| Backup (vzdump) | ~1.5-2 GiB |
| Temps de création | 5 minutes |
| Temps de restauration | 3 minutes |
Comparé aux 9.8 GiB/16 GiB utilisés sur .42, le LXC libère de la RAM sur la VM bureau et garantit à GLaDOS des ressources dédiées.