La mascotte ours polaire de NordBastion assise sur un banc de pierre sculpté dans un coffre nordique sombre avec un ordinateur portable sur les genoux, un treillis neuronal cyan lumineux scellé dans un récipient de verre hexagonal au-dessus du rack de serveurs à côté de lui, et un court flux de tokens cyan s'écoulant du récipient jusqu'à son écran derrière une porte runique fermée
How-to · Agents IA·17 min de lecture · 30 min pratique

Héberger un LLM sur un VPS.
Aucun GPU. Aucune clef d'API. Aucun prompt ne quitte jamais les murs.

Six étapes vers un LLM qui répond sur votre propre matériel — la division qui prédit vos tokens par seconde avant d'acheter la machine, quel modèle tient dans 4, 8, 16 ou 32 Go, l'authentification qu'Ollama n'intègre pas, et une liste honnête des tâches qui ne passent pas. Testé sur Debian 12.

Les six étapes
  1. 01

    Taille

    La bande passante, pas les cœurs

  2. 02

    Installer

    Ollama

  3. 03

    Mesurer

    Vos propres tokens/s

  4. 04

    Protéger

    TLS + un jeton

  5. 05

    Connecter

    Une seule base URL

  6. 06

    Borner

    Contexte, RAM, disque

Avant de commencer · L'arithmétique

Une division vous dit ce que la machine peut faire. Faites-la avant d'acheter la machine.

Presque tout ce qui s'écrit sur l'exécution locale de modèles de langage parle de cartes graphiques, ce qui n'aide guère si l'on dispose d'une machine virtuelle. Le modèle mental utile est plus simple que ne le laisse penser le discours autour du GPU, et il tient en une phrase : pour produire un seul token, un modèle dense doit lire chacun de ses poids depuis la mémoire. Pas une partie d'entre eux — tous, une fois par token.

Ce seul fait règle toute la question des performances. La vitesse de génération n'est pas décidée par le nombre de cœurs que vous louez ; elle est décidée par la vitesse à laquelle la machine peut faire défiler le modèle depuis la RAM. Ce qui vous donne un plafond calculable au dos d'une enveloppe avant de dépenser quoi que ce soit :

tokens per second  ≈  memory bandwidth (GB/s)  ÷  model size (GB)

Un modèle 8B quantisé occupe environ 5 Go. Sur un hôte virtualisé où l'on peut réalistement débiter dans les 20 Go/s, le plafond est d'environ quatre tokens par seconde, et le chiffre réellement observé sera peut-être de la moitié aux deux tiers de cela. Environ trois mots par seconde. Prenez-le comme un fait sur la charge de travail plutôt qu'une déception : c'est lent pour une fenêtre de chat et tout à fait suffisant pour une tâche qui classe un document et renvoie une ligne de JSON.

Les cœurs comptent encore, mais pas pour la raison qu'on imagine. Plus de threads aident jusqu'à saturer le chemin mémoire, ce qui arrive tôt sur ces machines — souvent autour de quatre à huit threads. Au-delà, les cœurs supplémentaires restent inactifs pendant que tout attend la RAM. C'est pourquoi une machine à seize cœurs n'est pas quatre fois plus rapide qu'une machine à quatre cœurs pour générer du texte, et pourquoi payer pour des cœurs en espérant de la vitesse est la façon la plus courante de se tromper de forfait.

Lire est rapide, écrire est lent. Chaque requête comporte deux phases qui ne se comportent pas du tout pareil. Traiter le prompt — le prefill — est une opération matricielle limitée par le calcul sur toute l'entrée à la fois, et elle s'exécute bien plus vite que la génération. Produire la réponse est la partie limitée par la mémoire décrite plus haut, un token à la fois. Donner au modèle un document de deux mille mots et lui demander trois phrases en retour est donc une charge confortable, tandis que lui demander un essai de deux mille mots ne l'est pas. Concevez vos prompts autour de cette asymétrie, et une machine CPU semble bien meilleure que ne le suggère son débit de tokens.

Niveau Mémoire Le plus gros modèle confortable Ordre de grandeur À quoi ça sert
Sentinel · $3.904 GB3B à Q4 (~2 Go)une phrase par secondeClassification, étiquetage, routage, embeddings
Garrison · $7.908 GB8B à Q4 (~5 Go)quelques mots par secondeLe réglage par défaut. Résumés, extraction JSON, réponses RAG
Ravelin · $16.9016 GB14B à Q4 (~9 Go)environ la moitié de ce qui précèdeRaisonnement plus poussé, contexte long, pipelines par lots
Bulwark · $32.9032 GB32B à Q4 (~20 Go)moins d'un mot par secondeLa qualité avant la vitesse. Travail asynchrone uniquement
Citadel · $62.9064 GB70B à Q4 (~40 Go)minutes par réponseÇa tient. Ce n'est pas interactif. Tâches de nuit

Les tailles de modèle sont les quantisations Q4_K_M habituelles, qui échangent une petite quantité de qualité, généralement imperceptible, contre moins de la moitié de la mémoire. La colonne vitesse est un ordre de grandeur dérivé de la division ci-dessus, pas un benchmark — tout l'intérêt de l'étape 03 est de mesurer votre propre machine plutôt que de faire confiance à un tableau, y compris celui-ci.

Avant de commencer · Ce qui tient

Ce qui tient vraiment sur un CPU. Et ce qui ne tient pas, dit sans détour.

La version honnête de cette section vaut mieux qu'une version enthousiaste, car la façon la plus rapide d'abandonner un modèle self-hosted est de le pointer vers la seule tâche où il est le plus mauvais et de conclure que toute l'idée était absurde.

Tient confortablement. Tout ce dont la sortie est courte et dont la valeur tient au jugement plutôt qu'à la prose. Classer un message dans l'une de quelques catégories. Décider si un ticket de support est urgent. Extraire cinq champs d'une facture sous forme de JSON. Résumer un fil de discussion en trois phrases. Étiqueter un document. Réécrire une description de produit. Traduire une courte chaîne. Détecter si deux fiches décrivent la même personne. Caviarder des noms dans un paragraphe avant qu'il n'aille où que ce soit d'autre. Chacune de ces tâches consomme une longue entrée et produit une sortie courte, exactement l'asymétrie qu'un CPU gère bien.

Tient, avec patience. Du travail sans humain qui attend. Traitements de nuit, workers de file, une passe nocturne sur les documents du jour, un rapport planifié. Si rien ne bloque sur la réponse, un débit de tokens qui serait intolérable dans une fenêtre de chat cesse totalement d'avoir de l'importance — une tâche qui tourne six minutes à trois heures du matin est simplement une tâche qui a tourné.

Ne tient pas. Un assistant interactif que les gens auront vraiment plaisir à utiliser : à ces débits, le curseur rampe et l'expérience est pire que pas d'assistant du tout. La génération longue — écris-moi deux mille mots — où la totalité de la sortie constitue la partie lente. Les agents de code qui itèrent sur un gros dépôt, où le contexte comme le niveau de qualité exigé dépassent ce qu'un petit modèle peut tenir. Tout ce qui nécessite un contexte de cent mille tokens, où le cache à lui seul dépasse la machine. Et les modèles d'image ou de vidéo, qui relèvent d'une discipline entièrement différente et ont réellement besoin d'un GPU.

Si votre charge de travail appartient à ce dernier groupe, la réponse sensée n'est pas d'acheter une machine CPU plus grosse — c'est un hybride. Gardez un modèle local pour l'essentiel des appels et routez la poignée qui a besoin d'un raisonnement de pointe vers une API hébergée, exactement la forme que décrit le guide sur l'exécution d'un agent IA 24/7 pour la partie runtime. Ce guide laissait délibérément le modèle lui-même hors périmètre. Celui-ci en est la moitié manquante.

Étape 01 · Taille

Achetez pour le modèle, pas pour les cœurs. Et laissez de la marge.

Partez de la tâche et remontez. Décidez ce que le modèle doit faire, choisissez la plus petite taille qui y arrive, vérifiez ce que cette taille occupe en Q4_K_M, puis ajoutez les surcoûts :

RAM needed  =  model file  +  KV cache  +  ~2 GB for the system

  3B  Q4_K_M  ≈  2.0 GB        KV cache at 8k context   ≈  0.5–1 GB
  8B  Q4_K_M  ≈  4.9 GB        KV cache at 32k context  ≈  2–4 GB
 14B  Q4_K_M  ≈  9.0 GB
 32B  Q4_K_M  ≈ 20.0 GB
 70B  Q4_K_M  ≈ 40.0 GB

Le cache clef-valeur est le surcoût qu'on oublie. Chaque token déjà présent dans la conversation est gardé en mémoire pour que le modèle n'ait pas à le recalculer, et ce stockage grandit avec le contexte que vous autorisez. Doubler le contexte le double à peu près. Un modèle qui tient avec un contexte de 4k peut ne plus tenir à 32k, et l'échec surviendra à la dixième requête plutôt qu'à la première, ce qui donne l'impression d'un mystère plutôt que d'une erreur de calcul.

Il n'y a pas de dégradation en douceur ici. Quand le total dépasse la RAM, le noyau ne ralentit pas poliment : il se met à swapper les poids du modèle vers et depuis le disque, à chaque token. Une génération de quatre secondes devient quatre minutes, la charge moyenne grimpe dans les dizaines, et tout le reste sur la machine — la base de données, le serveur web, votre session SSH — en souffre aussi. Tenir en mémoire n'est pas une optimisation. C'est l'exigence.

Dans le panneau : Order → VPS → le forfait indiqué par le calcul, image Debian 12. Aucune adresse e-mail n'est requise pour ouvrir le compte, aucun document d'identité n'est demandé à quelque étape que ce soit, et la facture se règle en Monero, Bitcoin, Lightning ou tout autre actif accepté — ce qui compte ici davantage que sur un serveur web ordinaire, pour les raisons qu'expose le guide pilier sur l'hébergement VPS anonyme, et que le chapitre confidentialité ci-dessous applique spécifiquement aux prompts.

Étape 02 · Installation

Une commande, un service. Lié au loopback, et laissé là.

Durcissez d'abord la machine — SSH par clef uniquement, un pare-feu qui n'autorise rien que vous n'ayez demandé, des mises à jour de sécurité automatiques. La checklist de la première heure prend environ une heure, et c'est une machine qui va bientôt contenir chacune des questions que vous lui posez.

Installez ensuite le serveur. Ollama, c'est llama.cpp entouré d'un registre de modèles, d'une API REST et d'une unité systemd, et l'installeur en une ligne met en place les trois :

apt update && apt install -y curl
curl -fsSL https://ollama.com/install.sh | sh

systemctl status ollama --no-pager
ss -ltnp | grep 11434
# → 127.0.0.1:11434 — loopback only. Leave it that way.

Cette dernière ligne mérite d'être lue deux fois. Par défaut, le service écoute sur l'interface loopback, ce qui est exactement juste, et l'erreur la plus courante des dix minutes suivantes est de mettre OLLAMA_HOST à 0.0.0.0 parce qu'une autre machine n'arrivait pas à l'atteindre. L'étape 04 explique comment l'atteindre correctement ; il n'existe aucune version de ceci où le port 11434 fait face directement à internet.

Deux réglages valent la peine d'être mis en place maintenant plutôt que découverts plus tard. Les modèles sont stockés sous /usr/share/ollama par défaut et ils sont volumineux, alors pointez ce chemin là où vous avez de la place. Et le réglage par défaut garde un modèle résident en RAM pendant cinq minutes après la dernière requête, ce qui est généreux sur une machine qui fait aussi autre chose :

systemctl edit ollama
[Service]
Environment="OLLAMA_MODELS=/var/lib/ollama/models"
Environment="OLLAMA_KEEP_ALIVE=30m"
Environment="OLLAMA_NUM_PARALLEL=1"
Environment="OLLAMA_MAX_LOADED_MODELS=1"
systemctl daemon-reload && systemctl restart ollama

Les requêtes parallèles et le chargement de plusieurs modèles multiplient tous deux l'usage mémoire, et sur une machine dimensionnée pour tenir exactement un modèle, il n'y a pas de gigaoctet de réserve pour une seconde copie. Sérialiser la file n'est pas une limitation de ce matériel ; c'est la seule configuration qui ne s'effondre pas.

Étape 03 · Mesurer

Obtenez votre propre chiffre. Le benchmark de personne d'autre ne parle de votre machine.

Téléchargez un modèle. N'importe lequel des modèles instruct actuels de classe 8B convient pour une première mesure — ils sont assez proches en taille pour que le chronométrage vous renseigne sur le matériel plutôt que sur le modèle :

ollama pull llama3.1:8b        # ~4.9 GB at Q4_K_M
ollama list
ollama ps                      # nothing resident yet

Lancez maintenant une génération avec le chronométrage activé. Le chiffre qui compte est le taux d'eval — les tokens produits par seconde, une fois le prompt lu :

ollama run llama3.1:8b --verbose "Reply with exactly one sentence about the Baltic Sea."
total duration:        14.2s
load duration:          3.1s
prompt eval count:        24 token(s)
prompt eval rate:      92.11 tokens/s      ← reading: fast
eval count:               38 token(s)
eval rate:              3.42 tokens/s      ← writing: the real ceiling

Deux lignes, deux mondes différents. La lecture tournait à une bonne quatre-vingt-dix tokens par seconde ; l'écriture à trois et demi. Ce ratio est l'asymétrie du chapitre sur l'arithmétique, mesurée sur votre propre machine, et c'est le fait le plus utile que vous collecterez aujourd'hui. Il dit : donnez à cette machine de longues entrées et demandez-lui de courtes sorties.

La même mesure via l'API, ce que vous voulez réellement si vous comptez scripter la comparaison entre deux ou trois tailles de modèle :

apt install -y jq

curl -s http://127.0.0.1:11434/api/generate -d '{
  "model":  "llama3.1:8b",
  "prompt": "List three Nordic capitals.",
  "stream": false
}' | jq '{
  tokens: .eval_count,
  seconds: (.eval_duration / 1000000000),
  rate: (.eval_count / (.eval_duration / 1000000000))
}'

Mesurez la taille en dessous et la taille au-dessus, puis arrêtez-vous. Téléchargez un 3B et un 14B, passez le même prompt dans chacun, et notez les trois débits. Vous savez maintenant exactement ce que coûte l'échange sur cette machine — généralement proche d'un doublement dans chaque sens — et vous pouvez choisir par tâche plutôt que par opinion. Supprimez ensuite les modèles que vous ne gardez pas, car chacun pèse plusieurs gigaoctets.

Une réserve sur la première exécution de tout modèle : la durée de chargement dans cette sortie est le temps passé à lire les poids du disque vers la RAM. Elle n'est payée que si le modèle n'est pas déjà résident, ce que contrôle OLLAMA_KEEP_ALIVE. Ne l'incluez pas quand vous comparez des débits, et ne vous en inquiétez pas — sur NVMe, ce sont des secondes, et ça n'arrive qu'une fois.

Étape 04 · Protéger

Ollama n'a aucune authentification. Aucune. Pas une faible — aucune.

C'est la partie du guide qui empêche quelque chose de grave, alors elle se dit sans détour : l'API Ollama n'a ni mot de passe, ni jeton, ni modèle d'utilisateur, ni système de permissions. Tout ce qui peut ouvrir une connexion TCP vers le port 11434 peut générer du texte sur votre CPU, énumérer les modèles que vous avez téléchargés, en télécharger de nouveaux et supprimer ceux que vous utilisez. Il n'y a aucun réglage à activer, parce qu'il n'y a aucun mécanisme à activer.

Le port 11434 est scanné en continu, pour une raison évidente : un serveur de modèle ouvert, c'est du calcul gratuit qui appartient à quelqu'un d'autre. Le symptôme n'est pas une alerte. C'est une machine qui semble lente pendant quinze jours et un graphique de bande passante qui ne correspond à rien de ce que vous avez fait. Gardez le service sur loopback, et placez devant lui quelque chose qui demande qui appelle.

Si rien en dehors de cette machine n'a besoin du modèle, arrêtez-vous ici — c'est déjà terminé. Le loopback plus un pare-feu est une réponse complète, et un agent, une pile d'automatisation ou une application web tournant sur le même VPS atteint le modèle via 127.0.0.1 sans rien de ce qui suit. Ne continuez que si une machine tierce doit l'appeler.

Le proxy, et le jeton. Générez un jeton aléatoire long, pointez un enregistrement A vers la machine, et laissez Caddy gérer à la fois le certificat et la porte d'entrée :

openssl rand -hex 32      # → the bearer token, store it in a password manager
apt install -y caddy

/etc/caddy/Caddyfile

llm.example.com {
    @unauthorised not header Authorization "Bearer PASTE_THE_HEX_TOKEN_HERE"
    respond @unauthorised "unauthorised" 401

    reverse_proxy 127.0.0.1:11434 {
        # Generation is slow by nature — do not let the proxy give up first.
        transport http {
            read_timeout 10m
        }
    }
}
systemctl reload caddy
ufw allow 80,443/tcp
ufw status                # 11434 must appear nowhere

Il y a une petite élégance à choisir un jeton porteur plutôt qu'une authentification basique. Ollama expose une API compatible OpenAI, chaque client OpenAI envoie sa clef exactement sous cet en-tête, si bien que le jeton que vous venez de générer devient la clef d'API que vos applications savent déjà transporter. Rien n'a besoin d'un en-tête personnalisé, et faire tourner l'accès tient en une ligne dans le Caddyfile et une variable d'environnement côté appelant.

Vérifiez depuis une machine qui n'est pas le serveur. Le premier appel devrait être refusé et le second devrait répondre :

curl -s -o /dev/null -w '%{http_code}\n' https://llm.example.com/api/tags
# → 401

curl -s https://llm.example.com/api/tags -H "Authorization: Bearer THE_TOKEN" | jq '.models[].name'
# → the list of models you pulled

Si le modèle doit être appelé par des agents plutôt que par vous, la question de l'exposition mérite le traitement complet du guide sur l'hébergement d'un serveur MCP distant — le même raisonnement sur le TLS, les jetons et ce qui doit être joignable depuis où, appliqué à un service qui distribue des outils plutôt que des tokens.

Étape 05 · Connexion

Une seule base URL, et tout la parle déjà. Vous changez une chaîne.

Ollama expose une surface compatible OpenAI sur /v1 en plus de sa propre API. C'est toute l'histoire de l'intégration : tout ce qui est construit pour OpenAI — les SDK officiels, les wrappers de framework, les nœuds d'automatisation — fonctionne en changeant la base URL et la clef, et rien d'autre ne change.

curl -s https://llm.example.com/v1/chat/completions \
  -H "Authorization: Bearer THE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "llama3.1:8b",
    "messages": [{"role":"user","content":"Reply with the word OK."}]
  }' | jq -r '.choices[0].message.content'

En Python, les seules lignes qui diffèrent d'une configuration hébergée sont les deux du haut :

from openai import OpenAI

client = OpenAI(
    base_url="https://llm.example.com/v1",
    api_key="THE_TOKEN",
)

r = client.chat.completions.create(
    model="llama3.1:8b",
    messages=[{"role": "user", "content": "Classify: 'the invoice is overdue'"}],
)
print(r.choices[0].message.content)

Demandez du JSON, obtenez du JSON. La fonctionnalité la plus utile pour l'automatisation est la sortie contrainte. Ollama peut forcer la réponse à être du JSON valide plutôt que d'espérer que le modèle se comporte bien, ce qui transforme un petit modèle d'un narrateur peu fiable en un analyseur fiable — et c'est la différence entre un workflow qui tourne sans supervision et un qui casse un item sur quarante :

curl -s http://127.0.0.1:11434/api/generate -d '{
  "model":  "llama3.1:8b",
  "prompt": "Extract the total and the currency: Invoice 4021, 1 249,90 EUR due 30 days.",
  "format": "json",
  "stream": false
}' | jq -r .response
# → {"total": 1249.90, "currency": "EUR"}

Dans une pile d'automatisation, le même principe s'applique : n8n embarque un nœud Ollama dédié, et son nœud OpenAI accepte une base URL personnalisée, si bien qu'un workflow existant bascule sur de l'inférence locale en modifiant un seul identifiant. Le guide de self-hosting n8n couvre le moteur d'automatisation lui-même ; faites tourner les deux sur des machines séparées si possible, car un moteur qui reste à 700 Mo au repos et un modèle qui veut cinq gigaoctets sont de mauvais voisins sur une machine de huit gigaoctets.

Et le point d'accès embeddings, là où cette machine justifie son prix. Les modèles d'embedding sont deux ordres de grandeur plus petits que les modèles de génération et ils font une seule passe par fragment sans rien générer, si bien qu'un CPU les traite à un rythme qui semble instantané :

ollama pull nomic-embed-text      # ~275 MB

curl -s http://127.0.0.1:11434/api/embed -d '{
  "model": "nomic-embed-text",
  "input": ["the first chunk of a document", "the second chunk"]
}' | jq '.embeddings | length'
Étape 06 · Borner

Un serveur de modèle sans limite utilisera tout ce que vous avez. Donnez-lui des bornes.

Plafonnez le contexte. La longueur de contexte est le principal réglage de l'usage mémoire, et la valeur par défaut est plus généreuse que ce que veut une petite machine. Fixez-la globalement à ce dont votre prompt réaliste le plus long a réellement besoin — la plupart des tâches de classification et d'extraction sont à l'aise sous quatre mille tokens — et augmentez-la par requête pour le rare appel qui en demande plus :

Environment="OLLAMA_CONTEXT_LENGTH=4096"
curl -s http://127.0.0.1:11434/api/generate -d '{
  "model": "llama3.1:8b",
  "prompt": "…a long document…",
  "options": { "num_ctx": 16384 },
  "stream": false
}'

Décidez combien de temps le modèle reste en mémoire. Un modèle résident répond instantanément et retient plusieurs gigaoctets en otage. Sur une machine dédiée à l'inférence, gardez-le chargé en permanence ; sur une machine partagée, laissez-le se décharger au bout d'un moment. La valeur se règle aussi par requête, si bien qu'un traitement de nuit peut épingler le modèle le temps de son exécution puis le libérer à la fin :

OLLAMA_KEEP_ALIVE=-1     # resident until the service restarts
OLLAMA_KEEP_ALIVE=30m    # a sensible default on a shared box
OLLAMA_KEEP_ALIVE=0      # unload immediately after each request

ollama ps                # what is resident right now, and how much it holds

Sérialisez la file. Deux requêtes simultanées contre un même modèle ne vont pas deux fois plus vite ; elles se disputent le même chemin mémoire saturé et chacune ralentit, et si Ollama décide de charger une seconde copie pour les servir, la machine manque de RAM. Sur cette classe de matériel, une requête à la fois, avec une file devant, est à la fois la configuration la plus rapide et la seule sûre — c'est pourquoi OLLAMA_NUM_PARALLEL et OLLAMA_MAX_LOADED_MODELS ont été fixés à un dès l'étape 02.

Surveillez le disque. Comparer quatre modèles en laisse quatre derrière soi, et à cinq gigaoctets chacun, c'est un disque qui se remplit en silence sans que rien ne se plaigne. Faites du nettoyage une partie de la comparaison plutôt qu'une tâche pour plus tard :

ollama list
du -sh /var/lib/ollama/models
ollama rm mistral:7b qwen2.5:14b

Enfin, sauvegardez ce qui n'est pas reproductible. Les poids du modèle ne le sont pas — eux, un pull les ramène. Ce qui mérite un dépôt, c'est la configuration, le Caddyfile, le jeton, les prompts affinés en trois semaines et, si vous en avez construit un, l'index vectoriel derrière votre recherche documentaire. Le guide des sauvegardes chiffrées couvre la mécanique ; la liste à inclure pour cette machine est courte et vaut la peine d'être notée.

La bonne partie · Recherche documentaire

Là où le CPU l'emporte sur l'argument. Les embeddings ne sont pas lents.

Tout ce qui précède portait sur la génération, la partie qu'un CPU fait lentement. La recherche documentaire est l'autre moitié de la plupart des systèmes utiles, et elle inverse complètement le tableau — c'est pourquoi le forfait le moins cher de cette page peut faire quelque chose de réellement précieux même si vous n'y générez jamais le moindre token.

Un modèle d'embedding transforme un morceau de texte en vecteur. Il se mesure en centaines de mégaoctets plutôt qu'en gigaoctets, il fait exactement une passe avant par fragment, et il n'y a aucune boucle token par token pour être limité par la bande passante mémoire. Sur la même machine où un modèle 8B écrit trois mots par seconde, un modèle d'embedding traite une bibliothèque de documents à un rythme qui évoque une copie de fichiers.

La forme de la chose. Découpez vos documents en fragments de quelques centaines de mots. Encodez chaque fragment une fois et stockez le vecteur. Au moment de la question, encodez la question, trouvez la poignée de fragments les plus proches, et transmettez-les au modèle avec la question. Le stockage n'a besoin de rien d'exotique : une base SQLite avec une extension vectorielle suffit pour des dizaines de milliers de fragments sur un seul VPS, et PostgreSQL avec pgvector couvre largement au-delà. Une base vectorielle dédiée est une bonne chose à vouloir plus tard et une dépendance inutile le premier jour.

Pourquoi c'est plus important que la vitesse. Regardez ce que chaque moitié touche. L'étape de génération voit une question et quelques paragraphes. L'étape d'embedding voit <em>chaque document que vous possédez</em> — toute l'archive, chaque contrat, chaque note, chaque message, passés dans le modèle un fragment à la fois. Si cette étape tourne contre un point d'accès hébergé, tout votre corpus a été transmis à un tiers pour être indexé. Si elle tourne sur votre propre machine, rien n'a bougé.

Cela donne un hybride réellement bon pour qui ne veut pas renoncer à la qualité de pointe : indexer localement, rechercher localement, et n'envoyer que la question et les trois fragments retrouvés à un modèle hébergé quand la réponse doit être excellente. Le corpus reste chez vous ; une fine tranche voyage, et seulement à la demande.

Deux voisins sur ce site rendent le schéma concret. Un SearXNG self-hosted donne à la couche recherche documentaire une façade privée pour le web ouvert plutôt qu'un corpus ; un stockage de documents self-hosted lui donne le corpus. Les deux, plus le modèle, tiennent sur des forfaits qui coûtent moins par mois qu'un seul siège hébergé.

La couche sous le modèle

Les prompts sont la partie sensible. Pas les réponses — les questions.

On raisonne sur la confidentialité des modèles comme si le risque était dans la sortie. Ce n'est pas le cas. La sortie est du texte générique ; mille autres personnes ont obtenu quelque chose de similaire. L'artefact révélateur, c'est l'entrée — et un an d'entrées dresse un portrait remarquablement complet d'une organisation.

Considérez ce que contient réellement un journal de requêtes. Le contrat que vous avez collé pour le faire résumer. L'e-mail client que vous avez fait classer, avec le client dedans. La lettre médicale, le montant du salaire, la lettre de démission en cours de rédaction, le code d'un dépôt qui n'est pas public. Puis les métadonnées autour : quelles questions, dans quel ordre, à quelle heure, depuis quelle adresse, sur combien de mois. Personne ne signe un document intitulé « voici notre stratégie » — mais la séquence des questions est ce document, assemblé honnêtement, par vous, un appel à la fois.

Couche un — ce que le point d'accès conserve. Les fournisseurs sérieux publient des politiques sérieuses, et les bons ne s'entraînent effectivement pas sur le trafic API professionnel. Ce n'est pas la même promesse que de ne pas le conserver. Les requêtes sont typiquement stockées un certain temps pour la surveillance des abus, accessibles au personnel sous conditions définies, et productibles sur réquisition légale — ce qui est exactement la bonne façon de gérer une grande plateforme et exactement le mauvais endroit pour un texte que vous n'enverriez pas par e-mail à un inconnu. Un modèle sur votre propre machine n'a aucun journal de ce genre, à moins que vous n'en écriviez un.

Couche deux — l'identité à laquelle le journal est rattaché. La rétention seule n'est que la moitié de l'exposition. L'autre moitié, c'est la clef à laquelle elle se rattache : un compte, un nom d'entreprise, une adresse de facturation, une carte. C'est ce rattachement qui transforme « quelqu'un s'est renseigné sur le rachat d'un concurrent » en « cette entreprise s'est renseignée, ce mardi-là ». Retirer le modèle de l'équation supprime la rétention ; retirer l'identité de la machine supprime le rattachement. Un VPS ouvert sans adresse e-mail ni document d'identité, dans une juridiction nordique, réglé en Monero, est la seconde moitié du même geste.

Couche trois — les journaux que vous écrivez vous-même. L'auto-hébergement déplace le risque plutôt qu'il ne le supprime, et il vaut la peine de voir clairement où il atterrit. Votre application journalise probablement ses propres prompts. Votre reverse proxy journalise chaque ligne de requête. Une session de débogage vieille de deux mois a laissé une sortie verbeuse dans le journal. Le modèle lui-même ne garde rien entre les appels, mais la machinerie qui l'entoure peut tout garder — décidez donc délibérément ce qui est écrit, fixez-lui une rétention, et tenez ce journal au niveau d'exigence que vous n'étiez pas prêt à accepter de quelqu'un d'autre.

Rien de tout cela ne fait d'un modèle local une garantie de confidentialité en soi. Cela en fait la seule architecture où la garantie vous appartient de donner : le texte reste sur du matériel que vous louez, sous une juridiction que vous avez choisie, derrière un jeton que vous avez émis, et il ne répond de rien d'autre.

Notes de terrain · Six pièges

Six façons dont ça déçoit les gens. Cinq d'entre elles sont évitables.

Piège 01 · Mémoire

La machine s'est figée au lieu de ralentir

Le modèle plus son cache de contexte dépassait la RAM, et le noyau a commencé à swapper les poids à chaque token. Tenir en mémoire ou descendre d'une taille — il n'y a pas de réglage intermédiaire.

Piège 02 · Exposition

Quelqu'un d'autre utilisait votre CPU

OLLAMA_HOST a été mis à 0.0.0.0 pour faire fonctionner un client. L'API n'a aucune authentification, et le 11434 est scanné. Loopback plus un proxy qui vérifie un jeton.

Piège 03 · Attente

Ça marche, et ça tape comme un fax

Un modèle 32B a été choisi pour un assistant interactif. Adaptez la taille à l'interaction : l'interactif veut du petit, la qualité veut de l'asynchrone.

Piège 04 · Contexte

La première requête allait bien, la dixième rampait

Une conversation qui grandit fait grandir le cache, et tout l'historique est relu à chaque tour. Plafonnez le contexte, et repartez sur une nouvelle conversation plutôt que d'ajouter indéfiniment.

Piège 05 · Résidence

Cinq gigaoctets ont disparu et rien ne tourne

Le modèle reste résident après le dernier appel, c'est voulu. Réglez OLLAMA_KEEP_ALIVE selon la machine, et lisez ollama ps avant de blâmer autre chose.

Piège 06 · Disque

Le disque s'est rempli de modèles comparés une fois

Quatre candidats à cinq gigaoctets chacun, aucun supprimé. Faites de ollama rm une étape de la comparaison, et vérifiez le répertoire des modèles quand les alertes disque se déclenchent.

FAQ · Modèles locaux

Questions, réponses.

Dix questions pour savoir si un modèle CPU seul est le bon outil pour la tâche que vous avez en tête.

Peut-on vraiment faire tourner un LLM sans GPU ?

Oui, avec une réserve honnête sur la vitesse. Un modèle quantisé tourne parfaitement bien sur des CPU de serveur ordinaires — les poids tiennent en RAM, le calcul est largement à portée, et rien dans le processus n'a besoin d'une carte graphique. Ce qu'achète un GPU, c'est de la bande passante mémoire, et c'est la bande passante qui fixe la vitesse de génération. Une machine CPU seul répondra donc, correctement et complètement, à quelque part entre quelques mots et quelques dizaines de mots par seconde selon le modèle. C'est lent pour une fenêtre de chat et tout à fait bien pour le travail que la plupart des gens automatisent réellement : classer un message, extraire du JSON structuré d'un document, résumer une page, encoder du texte pour la recherche, réécrire un paragraphe. La question n'est jamais « est-ce possible » — c'est « à quel débit, et ce débit compte-t-il pour cette tâche ».

Combien de tokens par seconde puis-je espérer ?

Faites le calcul plutôt que de faire confiance au benchmark de qui que ce soit, y compris le nôtre. Un modèle dense lit chacun de ses poids depuis la mémoire pour produire un token, si bien que le plafond est à peu près la bande passante mémoire divisée par la taille du modèle. Un modèle 3B quantisé à environ 2 Go, sur une machine avec un débit effectif de 20 Go/s, a un plafond proche de 10 tokens par seconde ; un 7B à 4,4 Go est proche de 4,5 ; un 32B à 20 Go est sous 1. Les chiffres réels se situent en dessous du plafond — disons 50 à 70 % — et varient selon l'hôte, les voisins et le nombre de threads. Le traitement du prompt relève d'une tout autre logique : il est limité par le calcul, s'exécute bien plus vite, et c'est pourquoi résumer un long document est confortable alors que discuter avec un gros modèle ne l'est pas.

Avec 8 Go, quel modèle choisir pour commencer ?

Un modèle instruct de classe 8B en Q4_K_M, qui se situe autour de 4,5 à 5 Go et laisse de la place pour le système d'exploitation et le cache de contexte. Cette taille est le point d'équilibre actuel : assez bon pour suivre des instructions de façon fiable, produire du JSON valide sur demande, résumer, classer et réécrire ; assez petit pour rester réactif. En dessous, un modèle 3B est réellement utile pour la classification, l'étiquetage et le routage, et environ deux fois plus rapide. Au-dessus, un 14B est nettement meilleur sur le raisonnement en plusieurs étapes et environ deux fois plus lent, ce qui est un bon compromis pour du traitement par lots et un mauvais pour tout ce qui est interactif. Commencez à 8B, mesurez, puis avancez dans la direction indiquée par la mesure.

De combien de RAM un modèle a-t-il vraiment besoin ?

La taille du fichier quantisé, plus le cache de contexte, plus la place pour le système — et le total doit tenir, car le mode d'échec n'est pas la lenteur mais l'effondrement. Quand le modèle ne tient pas, le noyau se met à swapper les poids sur le disque, et une génération qui devrait prendre quatre secondes en prend quatre minutes pendant que la charge moyenne grimpe dans les dizaines. Règle pratique en Q4_K_M : un modèle 3B fait environ 2 Go, un 8B environ 5 Go, un 14B environ 9 Go, un 32B environ 20 Go, un 70B environ 40 Go. Ajoutez deux gigaoctets pour Debian et ses services, et un à quatre de plus pour le cache clef-valeur selon la longueur de contexte que vous autorisez. Puis achetez le forfait au-dessus de la réponse, pas celui qui la matche exactement.

Ollama ou llama.cpp ?

Ollama est llama.cpp, entouré d'un registre de modèles, d'une API REST et d'un service systemd. Utilisez Ollama sauf raison précise de ne pas le faire : une commande d'installation, ollama pull plutôt que de chasser les fichiers GGUF, un point d'accès compatible OpenAI, et des réglages par défaut sensés pour le nombre de threads et la mémoire. Passez à llama.cpp directement quand vous voulez un flag qu'Ollama n'expose pas, quand vous voulez figer un build exact pour la reproductibilité, ou quand vous faites tourner un seul modèle avec une seule configuration pour toujours et préférez ne pas avoir de démon qui gère quoi que ce soit. Les deux font tourner les mêmes poids à la même vitesse ; la différence est entièrement opérationnelle.

Un modèle self-hosted vaut-il les grands modèles hébergés ?

Non, et prétendre le contraire vous fait perdre l'après-midi. Un modèle de pointe derrière une API est plus gros que tout ce qui tient sur une machine virtuelle, et il sera meilleur sur le raisonnement difficile, le contexte long et le code. Là où un petit modèle local est réellement compétitif, c'est sur l'immense zone médiane du travail réel : décider dans laquelle de six catégories ranger un e-mail, extraire cinq champs d'une facture, résumer un fil de support, réécrire une description, étiqueter un document, juger si deux fiches décrivent la même personne. Pour cette classe de tâches, l'écart entre un 8B et un modèle de pointe est faible, la différence de coût est totale, et la différence de confidentialité est absolue. La posture productive n'est pas « remplacer l'API » mais « arrêter de lui envoyer les quatre-vingt-dix pour cent qui n'avaient jamais besoin de sortir ».

Ollama dispose-t-il d'une authentification ?

Non — aucune, et c'est le fait opérationnel le plus important de ce guide. Il n'y a ni mot de passe, ni jeton, ni modèle d'utilisateur. Tout ce qui peut ouvrir une connexion TCP vers le port 11434 peut générer du texte, lister vos modèles, en télécharger de nouveaux et supprimer les existants. Ce port est scanné en permanence, et les instances non protégées sont repérées et utilisées comme calcul gratuit par des inconnus, ce qui se traduit d'abord par une charge machine mystérieuse, puis par une facture de bande passante. Gardez Ollama lié à 127.0.0.1, placez un reverse proxy devant, terminez le TLS à cet endroit, et exigez un jeton porteur ou un certificat client au niveau du proxy. Si rien en dehors de la machine n'a besoin du modèle, ne l'exposez pas du tout.

n8n ou mon runtime d'agent peuvent-ils utiliser un modèle local ?

Oui, et ça tient en général à un seul champ. Ollama expose une API compatible OpenAI sur /v1, donc tout client qui permet de définir une base URL — les SDK OpenAI, LangChain, le nœud OpenAI de n8n, la plupart des frameworks d'agents — lui parlera en pointant vers https://your-host/v1 et en envoyant n'importe quelle chaîne non vide comme clef. n8n embarque aussi un nœud Ollama dédié. Le schéma qui fonctionne bien en pratique est hybride : router les appels en masse, routiniers, à fort volume vers le modèle local, et réserver l'API hébergée à la poignée d'étapes qui ont vraiment besoin d'un raisonnement de pointe, avec un repli si le local refuse de produire du JSON valide.

Les embeddings sur CPU, ça vaut le coup ?

C'est ce qui offre le meilleur rapport sur toute cette page. Les modèles d'embedding sont minuscules — des dizaines à des centaines de mégaoctets plutôt que des gigaoctets — et ils font une seule passe avant par fragment sans génération token par token, si bien qu'un CPU les avale sans peine. Cela signifie que toute la moitié recherche documentaire d'un système RAG — indexer vos documents, encoder la requête, trouver les fragments les plus proches — tourne confortablement sur le forfait le moins cher, et c'est aussi la moitié qui touche chacun de vos documents. Même si vous décidez que l'étape de génération revient à une API hébergée, déplacer l'étape d'embedding sur votre propre machine garde votre corpus hors de la machine de quelqu'un d'autre.

Pourquoi self-hoster le modèle si une API est plus rapide et moins chère ?

Trois raisons, par ordre croissant d'importance. Le coût a une forme : une API est moins chère jusqu'à ce qu'elle ne le soit plus, et un workflow qui classe cinquante mille messages par mois voit sa facture grimper tandis qu'un VPS à $7.90 ne bouge pas. La disponibilité : aucune limite de débit, aucune dépréciation du modèle autour duquel vous avez construit, aucune panne sur la page de statut de quelqu'un d'autre. Et celle qui tranche — vos prompts sont le texte le plus révélateur que vous produisez. Pas les réponses, les questions. Ce que vous avez demandé, à propos de qui, quel jour, dans quel ordre. Un point d'accès hébergé voit tout cela, rattaché à une identité de facturation. Un modèle tournant sur une machine louée sans document d'identité, dans une juridiction nordique, payée en Monero, voit le même texte et ne le rapporte à personne.

Obtenir le métal

Un VPS nordique pour un modèle qui ne répond qu'à vous. Sans KYC, payé en crypto.

Garrison (4 vCPU, 8 Go, 240 Go NVMe, $7.90/mois) fait tourner un modèle 8B avec de la place pour le cache de contexte et le système — le forfait par lequel la plupart des gens devraient commencer. Ravelin double la mémoire pour du 14B et des contextes longs. Aucun e-mail à l'inscription, aucun document d'identité, et aucune facture au token.

Dernière révision · 2026-08-24 · Références · Documentation et référence API d'Ollama, documentation de llama.cpp, documentation du reverse proxy Caddy, fiches de modèles publiées pour les builds quantisés référencés · Fréquence · annuellement