Installer Hermes Agent (agent IA) sur un VPS
Ce guide vous explique comment installer Hermes Agent sur un VPS HostMyServers. Hermes est un framework d'agent IA open source (licence MIT) édité par Nous Research. Contrairement à un assistant de code utilisé en direct sur votre poste (Claude Code, OpenCode…), Hermes tourne en permanence sur un serveur : vous lui parlez depuis votre messagerie (Discord, Telegram, Slack…), il travaille de manière autonome en arrière-plan, garde une mémoire de vos échanges, apprend de nouvelles procédures (skills) et peut exécuter des tâches planifiées.
Le déploiement s'appuie sur Docker Compose avec une configuration durcie, et l'interface web d'administration n'est accessible que via un VPN (Tailscale), jamais depuis Internet.
Ce guide s'inspire du retour d'expérience de l'article « Hermes : simple hype ou vraie révolution ? » (damyr.fr) et de la documentation officielle Hermes Agent.
Commander un serveur
Hermes ne fait pas tourner de modèle d'IA en local : il appelle des modèles distants (OpenRouter, Anthropic, Nous Portal…). Un petit VPS suffit donc largement :
- VPS Performance - Idéal pour une instance personnelle
- VPS NVMe - Excellent rapport qualité/prix
- Serveurs dédiés Eco - Pour plusieurs agents/profils ou de l'automatisation de navigateur intensive
Prérequis
- Accès SSH root ou utilisateur avec sudo
- Système Ubuntu 24.04 LTS ou Debian 12/13
- Un compte chez un fournisseur de modèles (par exemple OpenRouter) avec une clé API
- Un compte Tailscale (gratuit pour un usage personnel) pour accéder à l'interface web
- Un compte Discord (ou Telegram, Slack…) pour discuter avec l'agent
Configuration requise
| Composant | Minimum | Recommandé |
|---|---|---|
| RAM | 2 Go | 4 Go |
| CPU | 1 vCPU | 2 vCPU |
| Stockage | 10 Go | 20 Go |
L'auteur de l'article fait tourner Hermes sur un VPS 2 vCPU / 2 Go, mais recommande au moins 4 Go de RAM dès que vous utilisez l'automatisation de navigateur (Playwright/Chromium) ou plusieurs sous-agents.
Les consoles navigateur (noVNC) transmettent mal certains caractères (:, @, =) et peuvent corrompre silencieusement les commandes et clés API collées. Utilisez une vraie session SSH.
Connexion et mise à jour du système
ssh utilisateur@adresse_ip_serveur
sudo apt update && sudo apt upgrade -y
sudo apt install -y ca-certificates curl gnupg openssl
Installation de Docker
L'image Docker officielle est la méthode d'installation recommandée par Hermes : l'image est sans état, toutes les données vivent dans un seul dossier monté (/opt/data), et une mise à jour se résume à tirer une nouvelle image.
Installez Docker Engine et le plugin Compose depuis le dépôt officiel Docker :
sudo install -m 0755 -d /etc/apt/keyrings
. /etc/os-release
curl -fsSL https://download.docker.com/linux/$ID/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/$ID $VERSION_CODENAME stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
Vérifiez l'installation :
docker --version
docker compose version
Installation de Tailscale (accès privé)
L'interface web d'Hermes permet de tout administrer (clés API, configuration, MCP, plugins, exécution de commandes via l'agent). Elle ne doit jamais être exposée sur Internet : des instances ouvertes sur 0.0.0.0 ont été compromises par des scanners automatiques (installation de clés SSH malveillantes via l'agent). On la rend donc accessible uniquement depuis votre réseau privé Tailscale.
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up
Ouvrez le lien d'authentification affiché pour rattacher le serveur à votre compte Tailscale, puis récupérez l'adresse IP Tailscale du VPS (plage 100.x.y.z) :
tailscale ip -4
Notez cette adresse : elle servira d'adresse d'écoute pour l'interface web. Installez aussi Tailscale sur votre ordinateur ou votre téléphone pour pouvoir y accéder.
Docker écrit ses propres règles iptables et contourne le pare-feu UFW pour les ports publiés. Publier le port sur l'adresse Tailscale (et non sur 0.0.0.0) garantit qu'il n'est pas joignable depuis l'interface publique, quel que soit l'état du pare-feu.
Préparation des répertoires
sudo mkdir -p /opt/hermes/data
sudo chown -R 10000:10000 /opt/hermes/data
sudo chmod 0750 /opt/hermes/data
cd /opt/hermes
Le conteneur exécute l'agent avec l'utilisateur non privilégié UID/GID 10000 : le dossier de données doit lui appartenir.
Fichier d'environnement
Créez le fichier /opt/hermes/.env qui contiendra l'adresse d'écoute et les identifiants de l'interface web :
sudo nano /opt/hermes/.env
# Adresse Tailscale du serveur (résultat de `tailscale ip -4`) — JAMAIS 0.0.0.0
HERMES_BIND_ADDR=100.x.y.z
HERMES_DASHBOARD_PORT=9119
# Identifiants de l'interface web
HERMES_DASHBOARD_BASIC_AUTH_USERNAME=admin
HERMES_DASHBOARD_BASIC_AUTH_PASSWORD=MOT_DE_PASSE
HERMES_DASHBOARD_BASIC_AUTH_SECRET=SECRET
# Limites de ressources (adaptez à votre VPS : ~1200m pour 2 Go, 3g pour 4 Go)
HERMES_MEMORY_LIMIT=1200m
HERMES_CPU_LIMIT=1.5
TZ=Europe/Paris
Générez le mot de passe et le secret de session, puis reportez-les dans le fichier :
openssl rand -base64 24 # -> HERMES_DASHBOARD_BASIC_AUTH_PASSWORD
openssl rand -hex 32 # -> HERMES_DASHBOARD_BASIC_AUTH_SECRET
HERMES_DASHBOARD_BASIC_AUTH_SECRET doit faire au moins 16 octets. En dessous, le module d'authentification ne s'active pas et l'interface refuse de démarrer avec l'erreur trompeuse « no auth providers are registered ». openssl rand -hex 32 est largement suffisant. Gardez ce secret stable : le changer invalide les sessions ouvertes.
Protégez le fichier, il contient des secrets :
sudo chmod 0600 /opt/hermes/.env
Configuration Docker Compose
Créez /opt/hermes/compose.yaml :
sudo nano /opt/hermes/compose.yaml
services:
hermes:
image: nousresearch/hermes-agent:latest
container_name: hermes
command: gateway run
restart: unless-stopped
stop_grace_period: 30s
# Aucun processus du conteneur ne peut acquérir de nouveaux privilèges
security_opt:
- no-new-privileges:true
# Retire toutes les capacités Linux par défaut...
cap_drop:
- ALL
# ...et ne rend que celles nécessaires à l'initialisation du conteneur
cap_add:
- CHOWN
- FOWNER
- DAC_OVERRIDE
- SETUID
- SETGID
- KILL
# Évite les erreurs liées à un trop grand nombre de fichiers ouverts
ulimits:
nofile:
soft: 4096
hard: 8192
ports:
# Interface web publiée UNIQUEMENT sur l'adresse Tailscale
- "${HERMES_BIND_ADDR}:${HERMES_DASHBOARD_PORT:-9119}:${HERMES_DASHBOARD_PORT:-9119}"
volumes:
# Toutes les données de l'agent : config, clés, mémoire, skills, crons, logs
- ./data:/opt/data
# Ne montez JAMAIS /var/run/docker.sock : cela donnerait l'équivalent root sur l'hôte
environment:
PUID: "10000"
PGID: "10000"
TZ: "${TZ:-Europe/Paris}"
# Interface web (supervisée dans le même conteneur que la gateway)
HERMES_DASHBOARD: "1"
HERMES_DASHBOARD_HOST: "0.0.0.0" # dans le conteneur uniquement ; côté hôte, seul Tailscale est exposé
HERMES_DASHBOARD_PORT: "${HERMES_DASHBOARD_PORT:-9119}"
HERMES_DASHBOARD_BASIC_AUTH_USERNAME: "${HERMES_DASHBOARD_BASIC_AUTH_USERNAME}"
HERMES_DASHBOARD_BASIC_AUTH_PASSWORD: "${HERMES_DASHBOARD_BASIC_AUTH_PASSWORD}"
HERMES_DASHBOARD_BASIC_AUTH_SECRET: "${HERMES_DASHBOARD_BASIC_AUTH_SECRET}"
# Garde-fous de l'agent
HERMES_WRITE_SAFE_ROOT: "/opt/data" # l'agent ne peut écrire que dans son dossier de données
HERMES_YOLO_MODE: "0" # les commandes dangereuses restent soumises à approbation
shm_size: "256m"
deploy:
resources:
limits:
memory: "${HERMES_MEMORY_LIMIT:-1200m}"
cpus: "${HERMES_CPU_LIMIT:-1.5}"
pids: 512
# Évite qu'un agent très bavard ne remplisse le disque
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
L'auteur de l'article publie une variante de l'image officielle (DamyrFr/hermes-docker) qui ajoute notamment rtk (filtrage des sorties de commandes pour réduire la consommation de tokens) et supprime les binaires setuid. La configuration ci-dessus en reprend les réglages de sécurité avec l'image officielle.
Premier lancement : l'assistant de configuration
Avant de démarrer le service, lancez une fois l'assistant interactif (interface en mode texte). Il vous demande votre fournisseur de modèles, vos clés API, et vous propose de configurer la messagerie (gateway) :
cd /opt/hermes
sudo docker compose run --rm hermes setup
Pendant l'assistant :
- Fournisseur de modèles : choisissez par exemple OpenRouter et collez votre clé API. Alternative :
hermes setup --portalavec un abonnement Nous Portal (300+ modèles et outils web inclus, sans clés à gérer). - Outils : activez la recherche web et l'extraction de pages (voir plus bas).
- Messagerie : configurez Discord (voir section suivante) — c'est la principale interface avec l'agent.
- Les paramètres obscurs peuvent être laissés par défaut, tout est modifiable ensuite.
Les clés sont enregistrées dans /opt/hermes/data/.env et la configuration dans /opt/hermes/data/config.yaml.
OpenRouter permet de fixer une limite de dépense par clé API, réinitialisable périodiquement. C'est idéal pour une instance personnelle facturée à la consommation.
Créer le bot Discord (gateway)
La gateway est le composant qui relie Hermes à votre messagerie. Discord est l'une des options les plus utilisées : les salons et threads permettent de bien organiser les échanges.
- Rendez-vous sur le Discord Developer Portal et cliquez sur New Application.
- Dans l'onglet Bot, activez les Privileged Gateway Intents suivants puis cliquez sur Save Changes :
- Message Content Intent (obligatoire : sans lui, le bot reçoit des messages vides)
- Server Members Intent (obligatoire)
- Toujours dans Bot, cliquez sur Reset Token et copiez le token.
- Invitez le bot sur votre serveur Discord via l'onglet Installation (ou OAuth2 → URL Generator avec le scope
bot). - Récupérez votre identifiant utilisateur Discord : activez le Mode développeur (Paramètres → Avancés), puis clic droit sur votre nom → Copier l'identifiant.
Si vous ne l'avez pas fait dans l'assistant, lancez la configuration de la gateway :
sudo docker compose run --rm hermes gateway setup
Ou ajoutez directement ces lignes dans /opt/hermes/data/.env :
DISCORD_BOT_TOKEN=votre-token-de-bot
DISCORD_ALLOWED_USERS=123456789012345678
DISCORD_ALLOWED_USERS (ou DISCORD_ALLOWED_ROLES) liste les seules personnes autorisées à donner des ordres à l'agent. Sans cette variable, Hermes refuse tout le monde par sécurité. N'ajoutez que des personnes de confiance : l'agent peut exécuter des commandes sur le serveur.
Par défaut, Hermes répond à tous vos messages privés et, dans les salons, uniquement lorsqu'il est @mentionné.
Démarrage du service
cd /opt/hermes
sudo docker compose up -d
sudo docker compose logs -f --tail=100
restart: unless-stopped relance automatiquement le conteneur après un crash ou un redémarrage du VPS (y compris si l'interface Tailscale n'est pas encore prête au boot : Docker réessaie jusqu'à ce qu'elle le soit).
Vérifiez que le port n'est publié que sur l'adresse Tailscale :
sudo ss -tlnp | grep 9119
La sortie doit afficher 100.x.y.z:9119 et pas 0.0.0.0:9119.
Envoyez ensuite un message privé à votre bot sur Discord : il doit vous répondre.
Accéder à l'interface web
Depuis un appareil connecté à votre réseau Tailscale, ouvrez :
http://100.x.y.z:9119
Connectez-vous avec les identifiants définis dans /opt/hermes/.env. L'interface permet de discuter avec l'agent, consulter les logs, gérer la configuration, les MCP, les profils et les plugins, ainsi qu'un Kanban : vous créez une tâche, l'agent la découpe en sous-tâches confiées à des sous-agents, et les cartes avancent automatiquement.
Arborescence des données
Tout l'état de l'agent se trouve dans /opt/hermes/data (monté sur /opt/data dans le conteneur) :
| Chemin | Rôle |
|---|---|
config.yaml | Paramètres globaux : modèles, outils, approbations, délégation |
.env | Clés API (fournisseurs de modèles, Discord, outils web…) |
auth.json | Authentifications (OAuth, plateformes de messagerie) |
SOUL.md | Personnalité de l'agent (nom, ton, manière d'interagir) |
skills/ | Procédures que l'agent apprend et améliore au fil du temps |
cron/ | Tâches planifiées |
state.db | Mémoire de l'agent : sessions, historiques… (ne jamais modifier ni copier à chaud) |
Personnaliser l'agent
Lui donner une personnalité (SOUL.md)
Le fichier SOUL.md définit le caractère de l'agent et sa manière de s'exprimer. Donnez-lui un nom et un ton : cela rend les échanges plus agréables au quotidien.
sudo nano /opt/hermes/data/SOUL.md
# Janet
Tu es Janet, une assistante serviable, concise et un brin malicieuse.
Tu réponds en français, tu vas droit au but et tu demandes confirmation
avant toute action irréversible.
Choisir les modèles
Un bon compromis consiste à utiliser un modèle rapide et peu coûteux pour la discussion, et un modèle plus solide pour le travail autonome des sous-agents (délégation). Exemple de configuration dans /opt/hermes/data/config.yaml avec OpenRouter :
model:
default: deepseek/deepseek-v4.1-flash
provider: openrouter
base_url: https://openrouter.ai/api/v1
api_mode: chat_completions
delegation:
max_iterations: 50
model: z-ai/glm5.3
provider: openrouter
Ces modèles sont des exemples issus de l'article au moment de sa rédaction. Le paysage évolue vite : choisissez ceux qui correspondent à votre budget et à vos besoins. Vous pouvez aussi changer de modèle depuis Discord avec la commande /model.
Un second agent pour la relecture de code
Pour éviter qu'un modèle relise son propre travail, créez un profil distinct utilisant un autre modèle (par exemple Claude Opus), puis demandez à votre agent principal de lui faire systématiquement relire le code avant de vous le soumettre :
sudo docker compose run --rm hermes profile create reviewer
Le profil se configure ensuite (modèle, fournisseur) depuis l'interface web, rubrique Profils.
Recherche web
Pour chercher sur Internet de manière autonome, l'agent utilise deux outils :
web_search: trouve des liens pertinents.duckduckgo-searchfonctionne en local, gratuitement.web_extract: convertit une ou plusieurs pages en Markdown. Tavily propose une clé avec un quota gratuit.
Activez-les depuis l'interface web ou avec sudo docker compose run --rm hermes tools.
Tâches planifiées (crons)
Hermes gère nativement les tâches planifiées. Le plus simple est de les demander directement dans Discord :
/cron add "every 2h" "Vérifie l'état du serveur et préviens-moi en cas d'anomalie"
/cron add "every 1d" "Fais-moi une veille des actualités DevOps et résume les 5 plus importantes"
Idées d'usage : veille automatisée multi-sources, ingestion régulière d'un coffre Obsidian (« second cerveau »), rapports périodiques. Par défaut, une commande dangereuse déclenchée par un cron est refusée (approvals.cron_mode: deny).
Sécurité : les bonnes pratiques
- Interface web : uniquement via Tailscale (ou autre VPN), jamais sur
0.0.0.0, toujours avec authentification. - Approbations : laissez
approvals.mode: smart(par défaut) ou passez enmanualdansconfig.yaml. N'utilisez jamais--yolo/approvals.mode: offsur un agent connect é à une messagerie. - Accès messagerie : limitez
DISCORD_ALLOWED_USERSà vous-même. - Socket Docker : ne le montez jamais dans le conteneur.
- Clés API : utilisez des clés dédiées avec plafond de dépense, et soyez prudent sur les droits accordés aux intégrations (GitHub, e-mail, MCP…).
- Pare-feu : n'ouvrez que SSH sur l'interface publique. Voir Sécuriser son serveur Linux.
Commandes utiles
| Action | Commande (depuis /opt/hermes) |
|---|---|
| Voir les logs | sudo docker compose logs -f --tail=100 |
| Redémarrer | sudo docker compose restart |
| Arrêter | sudo docker compose down |
| Relancer l'assistant | sudo docker compose run --rm hermes setup |
| Changer de modèle | sudo docker compose run --rm hermes model |
| Diagnostic | sudo docker compose run --rm hermes doctor |
Arrêtez le service (docker compose down) avant d'utiliser docker compose run pour modifier la configuration, puis relancez-le avec docker compose up -d.
Mise à jour
L'image étant sans état, il suffit de tirer la nouvelle version et de recréer le conteneur :
cd /opt/hermes
sudo docker compose pull
sudo docker compose up -d
Sauvegarde
Tout l'agent (configuration, clés, mémoire, skills, crons) tient dans /opt/hermes/data. La base state.db ne doit pas être copiée pendant que l'agent tourne : arrêtez-le le temps de l'archive.
cd /opt/hermes
sudo docker compose stop
sudo tar czf /root/hermes-backup-$(date +%F).tar.gz -C /opt/hermes data .env compose.yaml
sudo docker compose start
Conservez ces archives hors du serveur : elles contiennent vos clés API.
En cas de problème
L'interface web ne démarre pas (« no auth providers are registered »)
- Vérifiez que
HERMES_DASHBOARD_BASIC_AUTH_SECRETfait au moins 16 octets (utilisezopenssl rand -hex 32). - Vérifiez que les trois variables
HERMES_DASHBOARD_BASIC_AUTH_*sont bien renseignées dans/opt/hermes/.env.
Le conteneur ne démarre pas
- Consultez les logs :
sudo docker compose logs --tail=200 - Vérifiez les droits du dossier de données :
ls -ln /opt/hermes(propriétaire10000:10000) - Vérifiez que
HERMES_BIND_ADDRcorrespond bien àtailscale ip -4et que Tailscale est actif :tailscale status - Si une erreur de permission apparaît lors de l'initialisation après une mise à jour, commentez temporairement le bloc
cap_drop/cap_addpour confirmer, puis ajoutez uniquement la capacité manquante.
Le bot Discord est en ligne mais ne répond pas
- Vérifiez que Message Content Intent est activé dans le Developer Portal.
- Vérifiez que votre identifiant figure dans
DISCORD_ALLOWED_USERS. - Dans un salon, pensez à @mentionner le bot.
- Redémarrez après toute modification :
sudo docker compose restart
« API key not set »
Relancez la configuration du fournisseur : sudo docker compose run --rm hermes model, puis redémarrez le service.