Skip to content

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 :

pveam update
pveam available | grep -E 'debian-12|ubuntu-24'

Télécharger celui choisi :

pveam download local debian-12-standard_12.7-1_amd64.tar.zst

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 comme clone() 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 update ou pip 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)

crontab -e
# Ajouter :
@reboot cd /home/dex && hermes gateway start

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 :

# config.yaml
providers:
  ollama:
    api: http://192.168.31.42:11434

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 (rsync vers .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.

Références