Guide pas à pas · Ubuntu · ARM64

Faire d'un Raspberry Pi 5 une machine Hermes avec Ollama et un modèle local

Tout, de A à Z, pour quelqu'un qui n'a jamais ouvert un terminal. Chaque commande est suivie de la vérification qui prouve qu'elle a marché, et les attentes de performance sont mesurées, pas rêvées.

À lire avant de commencer (2 minutes)

Un Raspberry Pi 5 n'est pas une machine à IA. Il n'a ni GPU NVIDIA, ni accélérateur, ni mémoire rapide. Il fera tourner Hermes et un petit modèle lentement mais réellement. Ce guide vous dit exactement à quoi vous attendre, chiffres en main, sources à la fin. Si votre objectif est d'avoir un agent rapide et bavard, il faut un mini-PC ou une machine avec GPU ; si votre objectif est d'avoir un agent à vous, chez vous, qui ne coûte rien à l'usage et qui ne sort pas vos données, le Pi 5 fait très bien le travail. Toute la suite part de ce postulat-là.

0.Ce qu'on obtient, et les limites

Ce que vous allez obtenir à la fin

Ce que le Pi 5 ne peut pas faire (et pourquoi)

CroyanceRéalité sur un Pi 5
« Je vais faire tourner un modèle 70B » Non. Il faudrait ~40 Go de RAM. Le Pi 5 existe en 1, 2, 4, 8 et 16 Go — et la mémoire est soudée, on ne peut pas l'augmenter.
« Le GPU va accélérer » Non. Le GPU VideoCore VII n'est pas exposé comme backend de calcul par Ollama ni par llama.cpp ; sur le Pi 5, tout passe par les 4 cœurs ARM. Le seul chemin GPU connu est une carte AMD en PCIe avec un noyau patché — hors sujet ici.
« Ce sera un peu plus lent que sur mon PC » Beaucoup plus lent. Le facteur limitant n'est pas le processeur mais la bande passante mémoire : ~17 Go/s sur le Pi 5 (LPDDR4X-4267 sur un bus de 32 bits). Un GPU d'entrée de gamme fait 3 à 5 fois mieux, une carte moderne 20 fois mieux.
« Hermes sera aussi efficace que sur une machine normale » Non. Hermes envoie à chaque requête un « préambule » fixe (consignes + schémas des outils) de l'ordre de 16 000 jetons avant même votre message. Sur un Pi, ce préambule met plusieurs minutes à être avalé par le processeur (le prefill). Le chat fonctionne, l'agent autonome multi-étapes est très lent.
« Un petit modèle 1B, c'est comme un gros » Non. Un modèle 1–4B se trompe, invente des faits et suit mal les instructions complexes. Et surtout : beaucoup de petits modèles ne savent pas appeler des outils, donc Hermes ne peut alors que discuter, pas agir.
Le bon usage du Pi 5

Tâches courtes, sans surveillance, ou lentes mais utiles : résumer un texte, trier des fichiers, répondre sur Telegram, lancer une tâche planifiée la nuit, tenir un journal. Le Pi est excellent pour « ça tourne, ça ne coûte rien, ça ne fuit pas ». Il est mauvais pour « je discute en direct comme avec ChatGPT ».

1.Matériel et système

1.1 La liste de courses

ÉlémentRecommandationPourquoi
Raspberry Pi 5 8 Go minimum
16 Go si le budget le permet
Le modèle + le contexte doivent tenir en RAM à côté du système. 4 Go est trop juste pour Hermes (voir §4).
AlimentationOfficielle 27 W USB-C (5 V / 5 A) Une alimentation faible fait brider la machine (et le débit de génération). C'est la panne la plus sournoise.
Refroidissement Active Cooler officiel, ou boîtier ventilé Le BCM2712 commence à réduire sa fréquence dès 80 °C et plafonne à 85 °C. Sans ventilateur, les longues générations deviennent encore plus lentes.
Stockage SSD NVMe (HAT M.2 officiel) — à défaut microSD A2 ≥ 32 Go Un modèle de 2–5 Go se charge depuis le disque à chaque réveil : sur microSD c'est douloureux, et les cartes s'usent vite si le système swappe.
RéseauCâble Ethernet (Gigabit) Plus fiable que le Wi-Fi pour un service permanent et pour le SSH.

1.2 Installer Ubuntu Server 64 bits

On installe Ubuntu, pas Raspberry Pi OS : Ubuntu est la base pour laquelle Hermes et les paquets ARM64 modernes sont pensés, et c'est ce que ce guide suppose. La machine qui prépare la carte (votre PC) et le Pi sont deux choses distinctes.

  1. Sur votre PC, installez Raspberry Pi Imager (raspberrypi.com/software) — ou sudo snap install rpi-imager sous Ubuntu.
  2. Insérez la microSD (ou le NVMe dans un boîtier USB) — son contenu sera effacé.
  3. CHOOSE OS → Other general-purpose OS → Ubuntu → choisissez la dernière Ubuntu Server LTS 64 bits pour Raspberry Pi. Le numéro de version (24.04, 26.04…) n'a pas d'importance ici : ce qui compte est Server et 64-bit. Une image 32 bits ne fera pas tourner Ollama.
  4. Cliquez sur l'icône engrenage (options avancées) et remplissez tout :
    • hostname : hermes-pi
    • username / mot de passe : romain + un mot de passe solide
    • Enable SSH : oui, avec authentification par mot de passe pour commencer
    • Wi-Fi : uniquement si vous n'utilisez pas de câble Ethernet
    • Locale / timezone : Europe/Zurich
  5. Write, puis insérez le support dans le Pi et branchez l'alimentation.
  6. Attendez que cloud-init ait fini (2 minutes environ au premier démarrage). Le prompt de connexion apparaît avant la fin : si vous vous connectez trop tôt, vous tombez dans un système incomplet.

1.3 Se connecter en SSH

Le SSH, c'est simplement ouvrir une fenêtre de terminal qui pilote le Pi : vous tapez sur votre PC, le Pi exécute. Depuis le PC :

ssh romain@hermes-pi.local

Si le nom ne se résout pas, trouvez l'adresse IP du Pi dans l'interface de votre box et utilisez-la à la place (ssh romain@192.168.1.42). Répondez yes à la question sur l'empreinte, puis tapez le mot de passe.

Vérification — on est bien sur le Pi, en 64 bits
uname -m
nproc
free -h
cat /etc/os-release | head -2
hostname
aarch64            <- ARM 64 bits. Si vous voyez « armv7l » ou « armhf », l'image est 32 bits : recommencez à l'étape 1.2.
4                  <- 4 cœurs
               total        used        free
Mem:            15Gi       0.6Gi       14Gi     <- 15Gi pour un 16 Go, 7.6Gi pour un 8 Go, 3.7Gi pour un 4 Go
PRETTY_NAME="Ubuntu 24.04.x LTS"             <- peu importe la version, il faut « Ubuntu » et « LTS »
hermes-pi

Retenez le chiffre de la ligne Mem: : c'est lui qui décidera du modèle au §4. Notez aussi que ~1 Go est déjà pris par le système.

2.Préparer Ubuntu

Trois blocs à copier-coller, dans l'ordre. Comptez 10 à 20 minutes pour le premier (toutes les mises à jour du système).

2.1 Mettre à jour le système et installer les outils de base

sudo apt update
sudo apt full-upgrade -y
sudo apt install -y git curl xz-utils lm-sensors

sudo signifie « exécute en administrateur » : Ubuntu va demander votre mot de passe, et c'est normal qu'il ne s'affiche pas pendant que vous tapez.

Ces paquets sont les seuls prérequis réels : git, curl et xz-utils (l'installateur d'Ollama et celui de Hermes s'en servent). Le reste (Python, Node.js, ripgrep, ffmpeg) sera installé automatiquement par Hermes.

Vérification
git --version
curl --version | head -1
sensors
git version 2.4x.x
curl 8.x.x (aarch64-...) libcurl/8.x.x
Adapter: ...
Package id 0:  +48.0°C   <- température au repos. Au-delà de 75 °C au repos : ventilateur ou pâte thermique à revoir.

Si sensors ne trouve aucun capteur, ce n'est pas bloquant, mais installez-le : c'est votre indicateur de bridage thermique pour toute la suite.

2.2 Vérifier où vit le système (et combien de place il reste)

lsblk -o NAME,SIZE,TYPE,MOUNTPOINT
findmnt /
df -h /
Vérification
NAME        SIZE TYPE MOUNTPOINT
nvme0n1   476.9G disk
└─nvme0n1p2 476G part /          <- « / » sur nvme = vous démarrez bien sur le SSD
mmcblk0    29.7G disk
TARGET SOURCE                                FSTYPE OPTIONS
/      /dev/mapper/ubuntu--vg-ubuntu--lv     ext4   rw,relatime
/dev/mapper/ubuntu--vg-ubuntu--lv   48G   14G   32G  31% /     <- il faut au moins 10 Go libres pour les modèles + Hermes

Si / pointe vers mmcblk0p2, vous êtes sur la microSD : ça fonctionne, mais prévoyez le NVMe si vous gardez ce Pi en service permanent.

2.3 Vérifier le swap (la mémoire de secours)

swapon --show
cat /proc/sys/vm/swappiness
Vérification
NAME      TYPE  SIZE  USED PRIO
/swap.img file    4G     0B   -2     <- ou /swapfile, peu importe. S'il n'y a RIEN, signalez-le.
60

Le swap n'est pas un problème tant qu'il n'est pas utilisé. Mais si le modèle se met à swapper, le débit s'effondre (de 4 jetons/s à 0,2). Règle simple : un modèle ne doit jamais être plus gros que la moitié de la RAM, sinon Ollama rame et peut tuer le service (erreur out of memory, cf. §11).

3.Installer Ollama (et vérifier)

Ollama est le logiciel qui fait tourner le modèle. Une seule commande l'installe, crée un utilisateur système, installe un service systemd et le démarre.

curl -fsSL https://ollama.com/install.sh | sh
Ce que fait vraiment ce script (et pourquoi c'est acceptable)

On télécharge un script officiel depuis ollama.com et on le donne à sh. C'est la méthode d'installation officiellement documentée par Ollama pour Linux. Si vous préférez ne pas exécuter de script à distance, la documentation propose une installation manuelle (télécharger ollama-linux-arm64.tar.zst et le décompresser dans /usr) — mais il faudra alors créer vous-même le service systemd, ce que le script fait pour vous.

Vérification — Ollama tourne et écoute en local
ollama --version
systemctl is-active ollama
systemctl is-enabled ollama
curl -s http://127.0.0.1:11434/api/tags
ss -ltn | grep 11434
ollama version is 0.x.y
active                       <- le service tourne
enabled                      <- il redémarrera tout seul au boot
{"models":[]}                <- aucune erreur : l'API répond, il n'y a juste aucun modèle encore
LISTEN 0  4096  127.0.0.1:11434  0.0.0.0:*

Les deux points qui comptent : l'API répond en JSON (Ollama est vivant) et elle écoute sur 127.0.0.1 uniquement (elle n'est donc pas exposée au réseau). Si vous voyez 0.0.0.0:11434, quelqu'un a ouvert Ollama à tout le réseau : Ollama n'a aucune authentification, remettez OLLAMA_HOST=127.0.0.1:11434 dans la configuration du service.

3.1 Que faire si ollama --version échoue

Le service est peut-être monté mais le client pas encore dans le PATH. Rechargez votre shell, puis regardez les journaux du service :

source ~/.bashrc
which ollama
journalctl -u ollama -n 30 --no-pager
Vérification
/usr/local/bin/ollama        <- le binaire existe. Sinon : réinstallez et lisez la sortie du script jusqu'au bout.
... Listening on 127.0.0.1:11434 (version 0.x.y)   <- dernière ligne saine des journaux

4.Choisir le modèle (selon votre RAM)

Le premier critère n'est pas la vitesse, c'est le support des outils. Hermes est un agent : il lit/écrit des fichiers et lance des commandes en « appelant des outils ». Un modèle qui ne sait pas faire d'appels d'outils ne pourra que discuter. Tous les modèles retenus ci-dessous sont marqués tools dans la bibliothèque Ollama.

4.1 La formule qui explique tous les débits

Générer un jeton oblige à relire une fois tous les poids du modèle depuis la RAM. Le débit maximum théorique est donc simplement :

jetons/seconde ≈ bande passante mémoire (Go/s) ÷ taille du modèle (Go)

Pi 5 : 4267 MT/s × 32 bits ÷ 8 = 17,1 Go/s
Exemple : modèle de 2,0 Go  ->  17,1 ÷ 2,0 ≈ 8,5 jetons/s maximum théorique

Les débits réels mesurés sur Pi 5 sont nettement en dessous de ce plafond (typiquement 50 à 65 % du plafond, parfois moins avec un long contexte). C'est pourquoi les tableaux ci-dessous donnent des fourchettes pessimistes, issues de mesures publiées, et non des plafonds théoriques.

4.2 Les modèles à retenir, par taille de RAM

Votre PiModèleTailleOutils ?Débit réaliste
16 Go
confortable
qwen3:8b5,2 Gooui 1,5 – 2,5 j/s (mesuré ~2,0 j/s pour un 8B sur Pi 5) — utilisable en tâche de fond, pas en conversation
gemma4:e4b-it-qat6,1 Gooui 2 – 3,5 j/s — le meilleur compromis qualité/outils du tableau
gemma4:e2b-it-qat4,3 Gooui 3 – 4,5 j/s
8 Go
le minimum utile
qwen3:4b2,5 Gooui 3 – 5 j/s (recommandé)
llama3.2:3b2,0 Gooui 4 – 5,8 j/s (mesuré 4,6 j/s avec Ollama, 5,8 j/s avec llama.cpp à 4 threads)
gemma3:1b815 Monon 10 – 15 j/s — le plus rapide, mais conversation seulement
4 Go
trop juste pour Hermes
qwen3:1.7b1,4 Gooui 5 – 8 j/s
llama3.2:1b1,3 Gooui 6 – 10 j/s
qwen3:0.6b523 Mooui 8 – 15 j/s — le seul vraiment fluide, mais faible

Sources de ces chiffres, avec les liens et les conditions de mesure : page Sources & chiffres.

Le piège des petits modèles « avec outils »

Le guide officiel Hermes recommande gemma4:31b (20 Go) pour un usage agentique fiable. Ce modèle ne rentre pas dans un Pi 5 (20 Go de poids pour un maximum de 16 Go de RAM totale). Traduction concrète : sur un Pi, vous n'aurez jamais le niveau de fiabilité agentique décrit dans les démos. Attendez-vous à ce qu'un 3–4B appelle parfois mal ses outils, oublie une étape ou invente un chemin de fichier. Hermes corrige automatiquement une partie de ces appels ratés, mais pas tous.

Si vous avez 4 Go de RAM

Soyez lucide : le système en prend ~1 Go, il reste ~2,8 Go. Un modèle de 1,4 Go laisse ~1,4 Go pour le contexte et les outils — Hermes ne tiendra pas la distance. Sur un 4 Go, utilisez le Pi comme serveur de chat (ou comme client SSH vers une autre machine), pas comme machine d'agent complète. C'est dit franchement ici plutôt que découvert à l'usage.

4.3 Télécharger et tester

Remplacez qwen3:4b par le modèle choisi dans le tableau. Le téléchargement est un fichier ; il est mis en cache, on ne le retélécharge jamais deux fois.

ollama pull qwen3:4b
Vérification — le modèle est là et il sait appeler des outils
ollama list
ollama show qwen3:4b
NAME         ID           SIZE     MODIFIED
qwen3:4b     3be8f7...    2.5 GB   30 seconds ago

  Model
    architecture        qwen3
    parameters          4.0B
    context length      40960            <- IMPORTANT : notez ce chiffre, il borne le contexte
    ...
  Capabilities
    completion
    tools                              <- LA ligne à chercher. Si « tools » est absent, le modèle ne peut pas agir.

4.4 Tester la réponse ET mesurer le débit réel

C'est la mesure importante de tout ce guide : celle de votre machine. La ligne eval rate est votre débit de génération, prompt eval rate votre vitesse d'absorption du prompt.

ollama run qwen3:4b --verbose "Explique en trois phrases ce qu'est un ordinateur. Réponds en français."
Vérification — lisez ces deux lignes, ce sont vos vrais chiffres
Un ordinateur est une machine qui exécute...

total duration:       24.983s
load duration:        2.401s
prompt eval count:    34 token(s)
prompt eval duration: 1.213s
prompt eval rate:     28.03 tokens/s     <- vitesse d'ABSORPTION du prompt (28 j/s : c'est lent)
eval count:           96 token(s)
eval duration:        21.369s
eval rate:            4.49 tokens/s      <- votre DÉBIT de génération. À comparer au tableau du §4.2.

Pour quitter Ollama : tapez  /bye  puis Entrée.

Écartez-vous du tableau de plus de 30 % ? Ce n'est presque jamais le modèle : c'est la température (bridage) ou le stockage (microSD). Vérifiez avec sensors et ollama ps pendant la génération.

Deuxième test, par l'API exactement comme Hermes va le faire (point de terminaison compatible OpenAI) :

curl -s http://127.0.0.1:11434/v1/chat/completions -H "Content-Type: application/json" -d '{"model":"qwen3:4b","messages":[{"role":"user","content":"Dis bonjour"}],"max_tokens":40}'
Vérification
{"id":"chatcmpl-...","object":"chat.completion","created":...,"model":"qwen3:4b",
 "choices":[{"index":0,"message":{"role":"assistant","content":"Bonjour !..."},"finish_reason":"stop"}],
 "usage":{...}}

Si vous obtenez ce JSON, alors Hermes pourra parler à Ollama : c'est exactement l'adresse et le format qu'il utilisera (§7).

5.Régler Ollama (contexte, mémoire, démarrage)

Par défaut, Ollama ouvre un contexte de 4 096 jetons et décharge le modèle de la mémoire après 5 minutes d'inactivité. Pour Hermes, ces deux réglages sont inadaptés : il lui faut plus de contexte, et recharger un modèle de 2,5 Go à chaque message est du temps perdu. On règle donc le service.

Cette commande ouvre un fichier de surcharge dans l'éditeur nano :

sudo systemctl edit ollama

Collez exactement ces lignes (elles sont encadrées par des commentaires dans le fichier, écrivez en dessous de ces commentaires) :

[Service]
Environment="OLLAMA_KEEP_ALIVE=24h"
Environment="OLLAMA_CONTEXT_LENGTH=16384"
Environment="OLLAMA_NUM_PARALLEL=1"

Dans nano : Ctrl+O pour enregistrer, Entrée pour confirmer le nom, puis Ctrl+X pour sortir.

sudo systemctl daemon-reload
sudo systemctl restart ollama
Vérification — les réglages sont bien pris en compte
systemctl show ollama -p Environment
curl -s http://127.0.0.1:11434/api/tags >/dev/null && echo "API OK"
Environment=OLLAMA_KEEP_ALIVE=24h OLLAMA_CONTEXT_LENGTH=16384 OLLAMA_NUM_PARALLEL=1
API OK

Si la ligne Environment est vide, le fichier de surcharge n'a pas été enregistré : recommencez sudo systemctl edit ollama (pensez à Ctrl+O).

5.1 Pourquoi 16 384 et pas 64 000 ? (le calcul honnête)

Le contexte coûte de la mémoire, en plus des poids du modèle. Chaque jeton conservé occupe une place dans le cache KV, que l'on estime ainsi :

mémoire du contexte ≈ 2 × (nombre de couches) × (têtes KV) × (dimension de tête) × 2 octets

Exemple qwen3:4b : 36 couches, 8 têtes KV, tête de 128 dimensions
  ->  2 × 36 × 8 × 128 × 2 = 147 456 octets ≈ 144 Ko PAR JETON
  ->  16 384 jetons  ≈ 2,3 Go de cache
  ->  32 768 jetons  ≈ 4,6 Go de cache
RAMPoids du modèleCache 16kSystèmeTotalVerdict
16 Go2,5 Go2,3 Go1 Go~5,8 Goconfortable — vous pouvez monter à 32k
8 Go2,5 Go2,3 Go1 Go~5,8 Goça passe — mais sans marge : restez à 16k, jamais 64k
8 Go2,0 Go1,8 Go (12k)1 Go~4,8 Goplus sûr — 12k suffit en pratique
4 Go1,4 Go0,7 Go (5k)1 Go~3,1 Goau bord du gouffre

Le guide Hermes indique qu'il lui faut « au moins 64 000 jetons » pour un travail agentique confortable. Sur un Pi 5, c'est hors de portée : 64k de cache KV coûteraient ~9 Go à eux seuls pour un modèle 4B. On travaille donc avec un contexte réduit, en acceptant que les longues conversations déclenchent une compression plus tôt (commande /compress dans Hermes).

Astuce : réduire la mémoire du contexte (à essayer, pas garanti)

Ollama sait compresser le cache KV (2× moins de mémoire) quand le Flash Attention est actif. Sur Pi, ça dépend du support du backend CPU, donc vérifiez au lieu de supposer : ajoutez Environment="OLLAMA_FLASH_ATTENTION=1" et Environment="OLLAMA_KV_CACHE_TYPE=q8_0" dans le même fichier de surcharge, redémarrez, puis comparez ollama ps et la mémoire consommée (ps -o rss= -p $(pgrep -f 'ollama runner' | head -1)). Si le service refuse de démarrer ou si le débit chute, revenez en arrière : ces deux lignes ne sont pas obligatoires.

5.2 Précharger le modèle (et le garder chaud)

curl -s http://127.0.0.1:11434/api/generate -d '{"model":"qwen3:4b","keep_alive":"24h"}' | head -c 200
Vérification — le modèle est résident en mémoire
ollama ps
NAME         ID           SIZE     PROCESSOR    CONTEXT    UNTIL
qwen3:4b     3be8f7...    3.6 GB   100% CPU     16384      23 hours from now

PROCESSOR = 100% CPU : c'est normal et attendu sur un Pi (aucun GPU n'est utilisé). CONTEXT = 16384 : votre réglage du §5 est bien appliqué. Le total SIZE (3,6 Go ici) est la vraie consommation : poids + contexte. Comparez-le à votre RAM libre.

6.Installer Hermes

Hermes est un agent qui vit dans le terminal : il comprend une demande, puis exécute réellement des commandes, lit et écrit des fichiers, cherche sur le web. Le script officiel installe tout (uv, Python, le venv, Node.js, ripgrep, ffmpeg) sans que vous ayez à préparer Python vous-même.

curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash -s -- --skip-browser
Pourquoi --skip-browser ?

Par défaut, l'installateur prépare aussi un navigateur Chromium pilotable (Playwright) : ~400 Mo de téléchargement, plusieurs minutes sur un Pi, et des bibliothèques système qui demandent sudo. Pour piloter un modèle local, vous n'en avez pas besoin. Vous pourrez l'ajouter plus tard sans tout réinstaller.

Délai réaliste

Comptez 10 à 30 minutes sur un Pi 5 (téléchargement de Python 3.11, Node.js v22, ripgrep, ffmpeg, puis création de l'environnement Python). Laissez la fenêtre SSH ouverte. L'installation se fait dans ~/.hermes/ et le lanceur dans ~/.local/bin/hermes.

source ~/.bashrc
Vérification — Hermes est installé et se diagnostique
which hermes
hermes --version
hermes doctor
/home/romain/.local/bin/hermes

Hermes Agent v0.xx.y (2026.x.x) · upstream xxxxxxx
Install directory: /home/romain/.hermes/hermes-agent
Install method: git
Python: 3.11.15

┌─────────────────────────────────────────────────────────┐
│                 🩺 Hermes Doctor                        │
└─────────────────────────────────────────────────────────┘

◆ Python Environment
  ✓ Python 3.11.15
  ✓ Virtual environment active
◆ Configuration Files
  ✓ ~/.hermes/.env file exists
  ⚠ API key or custom endpoint configured   <- ATTENDU À CE STADE : on le corrige au §7
  ✓ ~/.hermes/config.yaml exists
◆ Directory Structure
  ✓ ~/.hermes directory exists

Un ⚠ (avertissement) n'est pas une panne. Un ✗ (croix) est un vrai problème : hermes doctor indique toujours la commande pour le corriger. C'est le premier outil à lancer en cas de doute, et le premier à consulter après une mise à jour (§12).

7.Brancher Hermes sur Ollama en local

Il faut dire à Hermes : « ton fournisseur de modèle n'est pas dans le cloud, il est ici, sur ce Pi ». Rien de secret, rien de payant. Trois chemins possibles — choisissez un moyen : la méthode A (recommandée), B ou C.

Méthode A — la commande unique (recommandée)

Ollama sait installer et configurer Hermes lui-même :

ollama launch hermes

Ce que fait cette commande, dans l'ordre : elle propose d'installer Hermes s'il est absent, vous fait choisir un modèle local, configure le fournisseur Ollama en pointant Hermes vers http://127.0.0.1:11434/v1, définit ce modèle comme modèle principal, propose de connecter une plateforme de messagerie (à ignorer pour l'instant, on verra au §10), puis lance la discussion.

Méthode B — l'assistant de Hermes (la référence)

hermes setup

Répondez exactement ceci :

How would you like to set up Hermes?
 → Quick setup — provider, model & messaging (recommended)      <- choisissez celle-ci

[puis]  → More providers...
        → Custom endpoint (enter URL manually)

API base URL [e.g. https://api.example.com/v1]: http://127.0.0.1:11434/v1
API key [optional]:                                        <- laissez VIDE puis Entrée
Verified endpoint via http://127.0.0.1:11434/v1/models (1 model(s) visible)
Detected model: qwen3:4b
Use this model? [Y/n]: Y
Context length in tokens [leave blank for auto-detect]:    <- laissez VIDE
Connect a messaging platform? ...   → Skip — set up later with 'hermes gateway setup'

Ollama n'a besoin d'aucune clé d'API. Si un écran en réclame une malgré tout, tapez une valeur bidon comme ollama — et jamais un vrai secret : il n'y a rien à protéger ici.

Méthode C — sans question, par commandes (utile en script)

hermes config set model.provider custom
hermes config set model.base_url http://127.0.0.1:11434/v1
hermes config set model.default qwen3:4b
La règle d'or d'Hermes : ne jamais éditer config.yaml à la main

Deux fichiers, deux rôles, à ne pas confondre : ~/.hermes/.env ne contient QUE des secrets (clés d'API, jetons de bot) ; ~/.hermes/config.yaml contient les réglages (fournisseur, URL, modèle). Et on ne modifie pas config.yaml à la main quand une commande existe : une indentation de travers et le fichier est corrompu, ce qui casse le service en silence. Utilisez hermes config set (méthode C), hermes model ou hermes setup. Pour lire ce qui est enregistré : hermes config get et hermes config show.

Vérification — Hermes pointe bien sur votre Ollama local
hermes config get model.provider
hermes config get model.base_url
hermes config get model.default
custom
http://127.0.0.1:11434/v1
qwen3:4b

Les trois lignes doivent être exactement celles-ci. Si model.provider affiche autre chose (openrouter, deepseek…), la configuration n'a pas été prise : relancez la méthode A ou B. Ensuite, hermes doctor doit avoir remplacé son avertissement par une validation du fournisseur.

7.1 Donner à Hermes le temps de respirer (le réglage qui sauve)

Un modèle local répond en minutes, pas en secondes. Hermes relève déjà automatiquement son délai de lecture pour les points de terminaison locaux (de 120 s à 1 800 s), mais autant rendre la chose explicite. La variable suivante est un réglage d'environnement qui n'a pas d'équivalent dans config.yaml : sa place documentée est donc .env — ce n'est pas un secret, c'est simplement le seul endroit prévu pour elle.

echo 'HERMES_API_TIMEOUT=1800' >> ~/.hermes/.env
Vérification
hermes config env-path
grep -n HERMES_API_TIMEOUT "$(hermes config env-path)"
/home/romain/.hermes/.env
12:HERMES_API_TIMEOUT=1800

Contrôle de sécurité dans le même mouvement : assurez-vous que ce fichier ne contient aucun vrai secret inutile. Affichez seulement les noms de variables, jamais les valeurs :

sed -E 's/=.*/=<masqué>/' "$(hermes config env-path)"
Etat attendu à ce stade

Ollama tourne en service, un modèle est chargé, Hermes sait où le trouver. Il ne reste plus qu'à parler.

8.La première conversation

8.1 Le test en une question (sans interface)

hermes chat -q "Réponds en une seule phrase, en français : quelle est la capitale de la Suisse ?"
Ce que « ça marche » veut dire exactement

Vous devez voir, au bout d'un moment (parfois plusieurs minutes, cf. 8.3), une phrase cohérente en français : « La capitale de la Suisse est Berne. »

La lenteur n'est pas un échec. Un échec, c'est :

8.2 La preuve que le calcul se fait bien sur le Pi

Ouvrez deux fenêtres SSH. Dans la première, lancez Hermes normalement. Dans la seconde, pendant que ça répond, observez la machine :

ollama ps
top -bn1 | head -12
Vérification — aucune connexion sortante, tout est local
NAME         ID           SIZE     PROCESSOR    CONTEXT    UNTIL
qwen3:4b     3be8f7...    3.6 GB   100% CPU     16384      23 hours from now

  PID USER   %CPU  %MEM  COMMAND
 4213 romain 391%  22.0  ollama runner --model ...   <- un cœur à 100 % : 391 % = les 4 cœurs qui travaillent

Si vous voyez ce ollama runner à fond pendant que Hermes répond, la démonstration est faite : le raisonnement se passe sur le Pi, sans internet. (Preuve négative : coupez le réseau, la même question marche encore.)

8.3 Pourquoi la première réponse prend plusieurs minutes

Avant votre question, Hermes envoie systématiquement un « préambule » technique : ses consignes de comportement plus le mode d'emploi de chacun de ses outils. Sur une machine normale, c'est instantané. Sur un Pi, ce préambule doit être absorbé jeton par jeton — c'est la phase de prefill.

Vous pouvez mesurer votre propre préambule :

hermes prompt-size
Vérification — la taille de ce qu'Hermes envoie à chaque requête
Prompt-size breakdown (platform=cli, model=qwen3:4b)

  System prompt total :   23,455 B  (22.9 KB, 22,866 chars)
  Tool schemas         :   40,612 B  (39.7 KB, 25 tools)
  ------------------------------------------------------------------
  Total par requête    :   ~64 000 B  soit environ 16 000 jetons

Le calcul est simple et sévère : 16 000 jetons ÷ 28 jetons/s d'absorption ≈ 570 secondes, soit près de 10 minutes pour la première réponse d'une session. Les tours suivants sont bien plus rapides : le modèle garde en cache le début identique de la conversation (à condition qu'il reste chargé — d'où OLLAMA_KEEP_ALIVE=24h au §5).

MomentDurée réaliste (Pi 5, modèle 3–4B, 16 Go)
Première réponse d'une session (prefill complet)5 à 12 minutes
Réponse suivante, même session, modèle resté chargé15 secondes à 2 minutes
Modèle déchargé (après 5 min d'inactivité sans réglage §5)Retour au cas n°1
Une tâche d'agent en plusieurs étapes (5 à 10 appels d'outils)15 minutes à 1 heure

8.4 Alléger le préambule (la seule vraie optimisation)

Sur un Pi, gagner du débit est presque impossible ; réduire ce qu'on envoie est la seule optimisation qui paye vraiment.

hermes tools
hermes skills list

Désactivez les outils dont vous ne vous servez pas (navigateur, TTS, vision, code exécuté en bac à sable…) : chacun coûte à Hermes un mode d'emploi de 1 à 5 Ko, envoyé à chaque requête. Puis remesurez :

hermes prompt-size
Vérification — mesurer le gain plutôt que le supposer

Comparez la ligne Tool schemas avant/après. Passer de 40 Ko à 20 Ko de schémas divise par deux le temps de prefill. Dans la conversation, la commande /compress résume l'historique et libère du contexte.

9.Mise en service permanente (survivre au redémarrage)

Deux choses doivent survivre à un sudo reboot : le moteur de modèle et, si vous voulez que Hermes soit joignable depuis l'extérieur, le gateway. Le reste (taper hermes dans un SSH) ne nécessite aucun service, puisque vous le lancez vous-même.

9.1 Ollama : déjà un service (à vérifier)

systemctl is-enabled ollama
systemctl is-active ollama
Vérification
enabled
active

enabled signifie qu'Ollama démarre avant même que vous vous connectiez. C'est l'installateur d'Ollama qui l'a mis en place, rien à faire de plus.

9.2 Option : précharger le modèle au démarrage

Sinon, le premier message après un reboot paye le chargement du modèle (plusieurs secondes) en plus du prefill. Un petit service oneshot règle ça.

sudo tee /usr/local/bin/ollama-warmup.sh > /dev/null <<'EOF'
#!/bin/bash
set -eu
MODEL="qwen3:4b"
curl -sf -X POST http://127.0.0.1:11434/api/generate \
  -H 'Content-Type: application/json' \
  -d "{\"model\":\"$MODEL\",\"keep_alive\":\"24h\"}" >/dev/null
echo "ollama: $MODEL prechauffe"
EOF
sudo chmod 755 /usr/local/bin/ollama-warmup.sh
sudo tee /etc/systemd/system/ollama-warmup.service > /dev/null <<'EOF'
[Unit]
Description=Precharge le modele Ollama utilise par Hermes
After=ollama.service
Requires=ollama.service

[Service]
Type=oneshot
RemainAfterExit=yes
User=romain
ExecStart=/usr/local/bin/ollama-warmup.sh

[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now ollama-warmup
Vérification
systemctl is-enabled ollama-warmup
systemctl status ollama-warmup --no-pager | head -6
ollama ps
enabled
● ollama-warmup.service - Precharge le modele Ollama utilise par Hermes
     Active: active (exited) since ...
NAME         ID           SIZE     PROCESSOR    CONTEXT    UNTIL
qwen3:4b     ...          3.6 GB   100% CPU     16384      23 hours from now

Changez MODEL="qwen3:4b" dans le script si vous changez de modèle : c'est le seul endroit à adapter.

9.3 Hermes en service (le gateway)

Le gateway, c'est la partie de Hermes qui écoute en permanence (Telegram, Discord…) et qui exécute les tâches planifiées. C'est lui qui doit démarrer tout seul.

hermes gateway setup

Configurez au moins une plateforme (Telegram au §10). Ce n'est qu'après cette étape que l'installation du service a un sens.

sudo loginctl enable-linger $USER
hermes gateway install
hermes gateway start

enable-linger est la ligne que tout le monde oublie : sans elle, un service « utilisateur » s'arrête à votre déconnexion SSH et ne redémarre pas au boot. Si vous préférez un service système (démarré au boot sans dépendre de votre session) :

sudo hermes gateway install --system
Vérification
systemctl --user is-enabled hermes-gateway
systemctl --user is-active hermes-gateway
hermes gateway status
loginctl show-user $USER -p Linger
enabled
active
Gateway: running (profile: default)
Linger=yes

enabled + active + Linger=yes : les trois conditions sont réunies. Notez que systemctl --user reset-failed hermes-gateway est la commande de secours si le gateway entre dans une boucle d'échecs.

9.4 Le test final : redémarrer pour de vrai

sudo reboot

Attendez une minute, reconnectez-vous en SSH, puis :

systemctl is-active ollama
curl -s http://127.0.0.1:11434/api/tags | head -c 120
ollama ps
systemctl --user is-active hermes-gateway
hermes --version
Vérification — la machine est autonome
active
{"models":[{"name":"qwen3:4b",...}]}
NAME         ID           SIZE     PROCESSOR    CONTEXT    UNTIL
qwen3:4b     ...          3.6 GB   100% CPU     16384      23 hours from now
active
Hermes Agent v0.xx.y

Si les cinq commandes répondent comme ci-dessus, votre Pi est une machine Hermes autonome : vous pouvez couper le courant, il reviendra tout seul en état de marche.

10.Option : piloter la machine depuis Telegram

Avertissement de sécurité — à lire avant

Un bot Hermes connecté à Telegram donne l'accès à votre terminal à quiconque peut lui parler. La configuration par défaut de Hermes refuse tout utilisateur non autorisé, et c'est indispensable : ne mettez jamais GATEWAY_ALLOW_ALL_USERS=true. Le jeton de bot est un secret : il ne va que dans ~/.hermes/.env, jamais dans un script, jamais dans un fichier partagé, jamais dans un message.

  1. Dans Telegram, cherchez @BotFather (t.me/BotFather) et envoyez /newbot. Choisissez un nom d'affichage (peu importe) puis un nom d'utilisateur qui finit par bot. BotFather renvoie un jeton de la forme 123456789:ABCdef....
  2. Cherchez @userinfobot et envoyez-lui n'importe quoi : il vous donne votre identifiant numérique (par exemple 123456789). C'est ce numéro, pas votre pseudo, qui sert de mot de passe d'accès.
  3. Configurez avec l'assistant :
hermes gateway setup

Choisissez Telegram, collez le jeton, puis votre identifiant quand il demande la liste des utilisateurs autorisés. L'assistant écrit les deux lignes suivantes dans ~/.hermes/.env (c'est bien leur place : ce sont des secrets) :

TELEGRAM_BOT_TOKEN=123456789:ABCdef...
TELEGRAM_ALLOWED_USERS=123456789        # plusieurs identifiants : séparés par des virgules
hermes gateway

Ceci lance le gateway au premier plan pour le test : laissez la fenêtre ouverte, envoyez un message au bot, il doit répondre (lentement, évidemment). Ensuite, Ctrl+C, puis mettez-le en service comme au §9.3.

Vérification
grep -i "telegram" ~/.hermes/logs/gateway.log | tail -5
grep -iE "failed to send|error" ~/.hermes/logs/gateway.log | tail -5
... Telegram: polling started (bot @votre_bot)
... Telegram: message from user 123456789 -> dispatched
                                                            <- la seconde commande doit rester VIDE (pas d'erreur)

Points de blocage connus : le bot ne répond pas dans un groupe (le « privacy mode » de Telegram est activé par défaut : @BotFather → /mybots → Bot Settings → Group Privacy → Turn off, puis retirez et réajoutez le bot au groupe), ou le bot ignore vos messages (votre identifiant n'est pas dans TELEGRAM_ALLOWED_USERS).

11.Dépannage : les 6 pannes les plus probables

Panne 1 — « Connection refused » sur le port 11434

Symptôme : Hermes répond connection refused, ou curl http://127.0.0.1:11434/api/tags ne renvoie rien.

systemctl status ollama --no-pager | head -12
journalctl -u ollama -n 40 --no-pager | tail -20
sudo systemctl restart ollama
curl -s http://127.0.0.1:11434/api/tags
Vérification
Active: active (running)
... Listening on 127.0.0.1:11434
{"models":[...]}          <- l'API répond de nouveau

Si le service refuse de démarrer juste après une modification du §5, c'est presque toujours le fichier de surcharge : retirez vos lignes avec sudo systemctl edit ollama (effacez tout l'intérieur), puis sudo systemctl daemon-reload && sudo systemctl restart ollama.

Panne 2 — hermes: command not found

Cause : le PATH de votre session n'a pas rechargé le dossier ~/.local/bin. Fréquent après une installation ou une reconnexion SSH.

source ~/.bashrc
ls -l ~/.local/bin/hermes
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
Vérification
which hermes
hermes --version
/home/romain/.local/bin/hermes
Hermes Agent v0.xx.y

Erreur voisine : ModuleNotFoundError: No module named 'dotenv' → vous appelez le fichier source ~/.hermes/hermes-agent/hermes avec le Python du système au lieu du lanceur du venv. Utilisez ~/.local/bin/hermes (ou le lien /usr/local/bin/hermes).

Panne 3 — ça semble figé, aucune réponse ne vient pendant 10 minutes

Ce n'est pas forcément une panne : c'est le prefill (§8.3). Un Pi 5 peut rester plusieurs minutes sans émettre le moindre caractère tout en travaillant.

ollama ps
top -bn1 | head -10
sensors | grep -i -E "package|temp"
Vérification — distinguer « ça travaille » de « c'est planté »
NAME         ID        SIZE     PROCESSOR    CONTEXT    UNTIL
qwen3:4b     ...       3.6 GB   100% CPU     16384      23 hours from now

  PID USER   %CPU  %MEM  COMMAND
 4213 romain 388%  22.0  ollama runner ...    <- 300-400 % : les 4 cœurs tournent = ça travaille, attendez.
Package id 0:  +81.0°C                        <- au-delà de 80 °C le Pi bride : ventilateur, aération, boîtier.

Remèdes concrets, du plus efficace au moins : désactiver des outils (hermes tools) pour réduire le préambule ; garder le modèle chargé (OLLAMA_KEEP_ALIVE=24h, §5) ; vérifier que HERMES_API_TIMEOUT=1800 est bien dans .env (§7.1) ; refroidir la machine.

Panne 4 — le modèle ne se charge pas / la machine devient inutilisable

Symptôme : erreur out of memory, ou le Pi répond au ralenti et le disque s'agite en permanence.

free -h
ollama ps
journalctl -u ollama -n 40 --no-pager | grep -i -E "memory|oom|error"
Vérification — le diagnostic tient en deux chiffres
               total   used   free   available
Mem:            7.6Gi  2.1Gi  180Mi    4.9Gi    <- « available » doit rester > 1 Gi
Swap:           4.0Gi  2.7Gi  1.3Gi            <- Swap USED > 0 pendant une génération = c'est perdu

NAME        SIZE     PROCESSOR    CONTEXT
qwen3:4b    3.6 GB   100% CPU     16384          <- si SIZE dépasse la moitié de la RAM : modèle trop gros

Corrections, dans cet ordre : prenez un modèle plus petit (§4.2) ; baissez OLLAMA_CONTEXT_LENGTH à 8 192 ; fermez les autres services du Pi ; enfin seulement, augmentez la RAM (impossible sur un Pi : il faut changer de modèle de carte).

Panne 5 — Hermes répond en texte, ne lance jamais ses outils

Symptôme : au lieu d'exécuter une commande, le modèle écrit quelque chose comme {"name": "terminal", "arguments": {...}} dans sa réponse.

ollama show qwen3:4b | sed -n '/Capabilities/,$p'
Vérification — la capacité « tools » doit être listée
  Capabilities
    completion
    tools          <- présente = le modèle sait appeler des outils. Absente = changez de modèle (voir §4.2).

Si tools est absent, aucune configuration ne le rendra : changez de modèle (qwen3:*, llama3.2:1b/3b, gemma4:* sont marqués tools ; gemma3:* ne l'est pas). Si tools est bien présent, le problème est côté serveur : Hermes tente de réparer automatiquement les appels mal formés, mais un modèle 1–4B en produit régulièrement. Réduisez le nombre d'outils actifs (hermes tools) et reformulez la demande plus simplement.

Panne 6 — « conversation trop longue », HTTP 400, ou réponses qui se dégradent

Cause : le contexte configuré dans Hermes et celui réellement ouvert par Ollama ne concordent pas. Ollama rapporte la taille maximale du modèle, pas la valeur effective de num_ctx.

ollama ps
hermes config get model.default
hermes prompt-size
Vérification — les deux contextes doivent concorder
NAME        SIZE     PROCESSOR   CONTEXT     <- doit afficher 16384 (ce que vous avez réglé au §5)
qwen3:4b    3.6 GB   100% CPU    16384

Prompt-size breakdown ...
  Total par requête : ~64 000 B  (~16 000 jetons)   <- à comparer au CONTEXT ci-dessus

Si le total du préambule approche la taille du contexte, il ne reste plus de place pour la conversation : c'est la cause classique. Trois gestes : /compress dans la session pour résumer l'historique ; augmenter OLLAMA_CONTEXT_LENGTH (16k → 32k) si la RAM disponible le permet (§5.1) ; ou démarrer une nouvelle session (/new).

Bonus — la machine est plus lente que prévu

vcgencmd get_throttled
cat /sys/class/thermal/thermal_zone0/temp
dmesg | grep -i -E "under-voltage|throttl" | tail -5
Vérification
throttled=0x0                            <- 0x0 = aucun bridage. Toute autre valeur = alimentation insuffisante ou surchauffe.
52600                                    <- 52,6 °C (millièmes de degré). Au-delà de 80 000 : bridage.
[  ... ] Under-voltage detected! ...     <- alimentation trop faible : mettez la 27 W officielle

Cause n°1 des débits décevants sur Pi 5 : l'alimentation, pas le logiciel. Cause n°2 : la carte microSD (le chargement du modèle est lent et le swap l'est encore plus).

12.Mises à jour

12.1 Hermes

hermes update --check
hermes update
Vérification
Updating Hermes Agent...
📥 Pulling latest code...
📦 Updating dependencies...
🔍 Checking for new config options...
🔄 Restarting gateways...
✅ Hermes Agent updated successfully!

Puis, les trois contrôles d'usage :
  git status --short     <- doit être vide (une arborescence « sale » = à inspecter)
  hermes doctor          <- aucune ✗
  hermes --version       <- le numéro a bien bougé

Bon à savoir : hermes update fait une sauvegarde avant de tirer le nouveau code, se protège d'une coupure de terminal (fermer la fenêtre SSH ne casse plus rien) et redémarre tout seul le service du gateway. Tout est journalisé dans ~/.hermes/logs/update.log si vous avez un doute. Après un gros saut de version : hermes config check puis hermes config migrate pour ajouter les nouveaux réglages.

Si une mise à jour casse quelque chose, on revient en arrière :

cd ~/.hermes/hermes-agent
git log --oneline -10
git checkout <commit-précédent>
uv pip install -e ".[all]"
hermes gateway restart

12.2 Ollama

curl -fsSL https://ollama.com/install.sh | sh
Vérification
ollama --version
systemctl is-active ollama
systemctl show ollama -p Environment
ollama version is 0.x.y (numéro supérieur à avant)
active
Environment=OLLAMA_KEEP_ALIVE=24h OLLAMA_CONTEXT_LENGTH=16384 OLLAMA_NUM_PARALLEL=1

Relancer le script d'installation fait la mise à jour et préserve vos réglages du §5.

12.3 Les modèles

ollama pull qwen3:4b
ollama list
Vérification
pulling manifest
... success
NAME         ID           SIZE     MODIFIED
qwen3:4b     7cdf5d13...  2.5 GB   2 seconds ago      <- la date a bougé : vous avez la version à jour

Un ollama pull sur un modèle déjà présent le met à jour sans repartir de zéro. Pour faire de la place : ollama rm nom-du-modele.

12.4 Le système Ubuntu

sudo apt update
sudo apt full-upgrade -y
sudo reboot
Vérification après reboot
uptime -p
systemctl is-active ollama
systemctl --user is-active hermes-gateway
up since 2 minutes
active
active

13.Ce qui est réaliste, en une page

Vous voulez…Sur un Pi 5
Discuter avec un modèle local, sans cloud ni factureoui 4 à 6 jetons/s avec un 3–4B : c'est lent mais parfaitement utilisable pour des réponses courtes
Un agent qui lance des commandes et touche aux fichiersoui, lentement comptez 5–12 min pour la première réponse, puis 15 s à 2 min par échange
Répondre sur Telegram depuis le téléphoneoui c'est le cas d'usage le plus confortable : la latence ne se voit pas
Des tâches planifiées la nuit (résumés, tri, veille)oui le meilleur usage : personne n'attend devant l'écran
Une conversation fluide type ChatGPTnon 4 jetons/s = ~4 minutes pour un texte d'une page
Un modèle 13B ou 30Bnon soit il ne rentre pas, soit il tombe sous 1,5 jeton/s et devient inutilisable
Plusieurs utilisateurs simultanésnon un seul jeu de réponses à la fois ; serialisez
Un long contexte (documents entiers)non c'est ce que le Pi paye en premier : restez à 8–16k de contexte
Le compromis qui marche vraiment sur cette machine

Le modèle local sur le Pi pour tout ce qui est court, privé et sans urgence ; et, si un jour vous voulez la vitesse, un fournisseur cloud en secours que Hermes n'utilise que quand le local échoue. Vous gardez le contrôle et la gratuité au quotidien, sans vous interdire l'usage ponctuel d'un gros modèle.


Les chiffres de débit de ce guide ne sont pas des estimations de principe : ce sont les mesures publiées par des tiers sur des Raspberry Pi 5, avec les liens, les conditions de test et les plafonds théoriques → Sources & chiffres.

Toutes les commandes sont rassemblées, sans explication, sur la page Fiche mémo : c'est la page à garder ouverte pendant l'installation.