Héberger Ollama sur un VPS en toute sécurité
Un modèle 7B demande 8 Go de RAM et produit 4 à 10 tokens/s sur CPU. Utilisez l’API sur 127.0.0.1:11434/v1, sans ouvrir le port 11434.
Ce que vous allez mettre en place
Un seul modèle de langage à poids ouverts, exécuté sur un serveur que vous contrôlez, accessible via une API HTTP et, si vous le souhaitez, depuis une interface de chat dans votre navigateur. Ollama télécharge le modèle, le charge en mémoire et traite les requêtes sur http://127.0.0.1:11434. L’installation tient en une commande. Toute la difficulté se trouve ailleurs : choisir un modèle que votre VPS peut réellement charger en RAM et éviter d’exposer par erreur un serveur d’inférence sans authentification à l’ensemble d’Internet.
Deux avertissements importants pour commencer. Un VPS utilisant uniquement le CPU exécute lentement les petits modèles, et l’API ne fournit aucune authentification intégrée. Ces deux points sont détaillés ci-dessous, car ce sont eux qui posent le plus de problèmes.
La réalité du dimensionnement, en chiffres simples
L’empreinte mémoire d’un modèle correspond à peu près à sa taille de fichier, à laquelle il faut ajouter environ un gigaoctet pour le fonctionnement, puis une quantité supplémentaire pour la fenêtre de contexte. Les modèles par défaut d’Ollama sont quantifiés en 4 bits (notés Q4), ce qui consomme environ un demi-gigaoctet de RAM par milliard de paramètres. Le calcul est donc simple, et il détermine tout. Le dernier terme est celui que vous définissez vous-même : augmenter num_ctx au-delà de la petite valeur par défaut d’Ollama permet de gérer des prompts plus longs, mais augmente la taille du cache KV en RAM. Définissez donc la longueur du contexte avant de déterminer si un modèle tient dans la mémoire disponible.
Un modèle 3B comme llama3.2:3b représente un téléchargement d’environ 2 GB et nécessite environ 4 GB de RAM libre pour fonctionner. Un modèle 7B ou 8B comme mistral:7b ou llama3.1:8b occupe environ 5 GB sur le disque et nécessite environ 8 GB de RAM, ou 16 GB pour fonctionner confortablement. Un modèle 13B ou 14B nécessite environ 16 GB. Tout modèle compris entre 30B et 70B nécessite une machine avec beaucoup de RAM ou, plus réalistement, un GPU. Sur un VPS avec CPU, il ne tiendra pas en mémoire ou répondra si lentement qu’il sera inutilisable.
Passons maintenant à la vitesse, car c’est le point que l’on sous-estime le plus. L’inférence sur CPU est limitée par la bande passante mémoire, et non par la fréquence d’horloge. Un VPS avec vCPU partagé dispose d’une bande passante modeste. Comptez de quelques unités à une dizaine de tokens par seconde : un modèle Q4 de 7B à 8B peut atteindre 4 à 10 tokens par seconde, contre 10 à 25 pour un modèle 3B. Un GPU est environ dix fois plus rapide. Ces chiffres sont volontairement approximatifs. La méthode fiable consiste à mesurer les performances de votre propre machine, comme l’explique l’étape d’exécution ci-dessous. Fiez-vous à votre eval rate, et non au chiffre indiqué dans un article, y compris celui-ci.
Conclusion pratique : les petits modèles quantifiés sur CPU sont réellement utiles pour rédiger, résumer et classer du contenu si vous acceptez leur vitesse. Pour des modèles plus grands ou des réponses plus rapides, prévoyez une instance avec GPU. Si vous préférez voir ce calcul appliqué de bout en bout à un modèle précis, exécuter Nemotron 3.5 Lightning sur un VPS explique quel tag télécharger, quelle quantité de RAM il nécessite réellement et si le CPU seul offre des performances suffisantes.
Pour comparer un modèle précis à une machine précise, estimez ici son empreinte mémoire :
Installer Ollama
Deux méthodes propres sont possibles. Le script officiel est la solution la plus simple sur un VPS sans autre couche :
curl -fsSL https://ollama.com/install.sh | shCette commande crée un utilisateur système nommé ollama, installe le binaire dans /usr/local/bin/ollama et enregistre un service systemd nommé ollama.service. Le service démarre au boot et écoute sur 127.0.0.1:11434. Vérifiez qu’il fonctionne :
systemctl status ollama
ollama --versionSi vous utilisez déjà Docker, employez plutôt le conteneur :
docker run -d --name ollama \
-p 127.0.0.1:11434:11434 \
-v ollama:/root/.ollama \
--restart always \
ollama/ollamaNotez le préfixe 127.0.0.1: dans le mapping de port. Il lie le port à localhost uniquement. Si vous écrivez -p 11434:11434 à la place, le port est publié sur toutes les interfaces. C’est l’erreur signalée dans la section consacrée à la sécurité. Choisissez une seule méthode d’installation. N’exécutez pas le script et le conteneur en même temps, car deux processus essaieraient d’utiliser le même port.
Télécharger et exécuter votre premier modèle
ollama pull llama3.2:3b
ollama run llama3.2:3bpull télécharge les couches du modèle sur le disque (environ 2 GB pour celui-ci). run les charge en mémoire et vous place devant une invite >>>. Saisissez une question. Le premier token peut prendre plusieurs secondes, le temps que les poids soient chargés du disque dans la RAM. La réponse est ensuite affichée progressivement. Saisissez /bye pour quitter le chat. Ollama continue de fonctionner en arrière-plan.
Vérifiez ce qui est chargé et la manière dont les ressources sont utilisées :
ollama psLa colonne PROCESSOR indique la réalité. 100% CPU signifie qu’aucun GPU n’est utilisé. C’est la cause de la lenteur. Mesurez la vitesse réelle avec l’option verbose :
ollama run --verbose llama3.2:3b "Write two sentences about Linux."La ligne eval rate affichée à la fin indique le nombre de tokens par seconde sur ce matériel. C’est la valeur à prendre en compte pour la planification.
Emplacement des modèles et capacité de stockage à prévoir
Installés par le script et exécutés par le service, les modèles se trouvent dans le répertoire personnel de l’utilisateur ollama :
sudo du -sh /usr/share/ollama/.ollama/modelsLorsqu’ils sont exécutés de manière interactive avec votre propre utilisateur, ils se trouvent dans ~/.ollama/models. Dans le conteneur, ils se trouvent dans le volume nommé ollama. Ce point est important, car les poids quantifiés occupent rapidement beaucoup d’espace : un modèle 3B utilise environ 2 GB, un modèle 7-8B environ 5 GB et un modèle 14B environ 9 GB. Si vous téléchargez quatre modèles pour les comparer, vous aurez consommé 20 GB sans vous en rendre compte. Prévoyez la capacité du disque en fonction des modèles que vous souhaitez conserver, puis supprimez les autres avec ollama rm <model>. Si le même VPS exécute déjà un autre service particulièrement gourmand, comme PhotoPrism ou Immich qui stocke une photothèque, déduisez d’abord cet espace de l’espace libre et considérez ce qui reste comme votre budget réel pour les modèles.
Exécuter le service sous votre contrôle
Le script d’installation a déjà enregistré ollama.service. Le service redémarre donc au boot sans configuration supplémentaire. Le paramètre qu’il est utile de modifier est la durée pendant laquelle un modèle reste chargé en mémoire. Selon l’installation, vous pouvez aussi modifier l’adresse d’écoute. Ces deux paramètres doivent être placés dans un drop-in systemd afin qu’une mise à niveau d’Ollama ne les écrase pas :
sudo systemctl edit ollama.serviceAjoutez ceci sous l’en-tête [Service] affiché par l’éditeur :
[Service]
Environment="OLLAMA_KEEP_ALIVE=30m"OLLAMA_KEEP_ALIVE indique combien de temps un modèle reste en mémoire après la dernière requête (5 minutes par défaut). Augmentez cette valeur sur une machine interrogée toute la journée pour éviter de recharger les poids à chaque requête. Sur une machine disposant de peu de mémoire, définissez-la sur 0 pour libérer la RAM dès la fin d’une requête. Si vous voulez qu’un modèle reste chargé indéfiniment plutôt que pendant une durée fixe, consultez Garder un modèle Ollama chargé en permanence. Cette page explique le champ keep_alive par requête et comment recharger les poids après un redémarrage afin qu’ils soient prêts, plutôt que d’attendre la première requête lente. systemctl edit recharge les fichiers d’unité à votre place. Redémarrez donc le service pour appliquer la modification :
sudo systemctl restart ollamaLe point de sécurité le plus important
Par défaut, Ollama écoute sur 127.0.0.1:11434. Seuls les processus exécutés sur le VPS peuvent donc y accéder. Ce comportement par défaut est correct. Conservez-le.
L’API n’utilise aucune authentification. Aucune. Il n’y a ni clé d’API, ni connexion, ni limite de débit, ni liste d’autorisation. Toute personne pouvant atteindre le port 11434 peut exécuter n’importe quel modèle que vous avez téléchargé, en télécharger de nouveaux, les supprimer et maintenir votre CPU ou votre GPU à pleine charge indéfiniment. Des scanners comme Shodan indexent des milliers d’instances Ollama ouvertes. Une instance exposée est généralement trouvée et utilisée à des fins malveillantes en quelques heures.
Voici l’unique erreur à ne jamais commettre : ne définissez pas OLLAMA_HOST=0.0.0.0 et n’ouvrez pas le port 11434 dans votre pare-feu. Vous exposeriez ainsi un serveur d’inférence dépourvu d’authentification à l’ensemble d’Internet. Aucune configuration ne peut sécuriser 11434 sur 0.0.0.0 tel quel, car Ollama ne fournit rien à configurer : l’authentification n’existe tout simplement pas. Cette règle concerne ce service particulier. Elle n’interdit pas d’ouvrir un port dans tous les cas : un relais RustDesk auto-hébergé pour le bureau à distance doit accepter du trafic public pour fonctionner, et cela se justifie parce qu’il intègre sa propre authentification par clé ainsi qu’une liste courte et documentée de ports. Ollama ne fournit rien de comparable.
Il existe trois moyens sûrs d’accéder au modèle depuis un autre système :
- Gardez l’accès local. Si le seul client est un autre programme exécuté sur le même VPS, un script cron, un bot ou un serveur MCP reliant vos outils au modèle, laissez l’écoute sur
127.0.0.1et faites appelerhttp://127.0.0.1:11434par ce programme. Rien n’est exposé et rien d’autre n’est nécessaire. - Utilisez un tunnel privé. Connectez le VPS à un VPN WireGuard que vous gérez vous-même, définissez
OLLAMA_HOSTsur l’adresse du tunnel, par exemple10.8.0.1, et non0.0.0.0, et seuls les pairs du VPN pourront se connecter. Internet ne verra toujours rien sur le port 11434. - Placez un reverse proxy avec authentification devant Ollama. Terminez TLS et exigez un mot de passe ou un token dans nginx, Traefik ou Caddy, puis proxyfiez les requêtes vers
127.0.0.1:11434. Ollama conserve son écoute sur localhost. Le proxy est le seul service à écouter sur le port public. C’est le même principe que l’utilisation d’un certificat Let's Encrypt sur nginx devant n’importe quel service local.
L’option du reverse proxy est précisément celle que l’interface de chat vous propose ensuite, avec une véritable connexion utilisateur.
Ajouter une interface de chat avec Open WebUI, derrière TLS
Open WebUI est une interface de chat auto-hébergée. Exécutez-la dans Docker et configurez-la pour utiliser l’instance Ollama locale :
docker run -d \
--name open-webui \
--network=host \
-e OLLAMA_BASE_URL=http://127.0.0.1:11434 \
-v open-webui:/app/backend/data \
--restart always \
ghcr.io/open-webui/open-webui:mainLe paramètre --network=host est essentiel sur un VPS Linux. Il place le conteneur dans l’espace de noms réseau de l’hôte. Ainsi, 127.0.0.1 dans le conteneur correspond à la propre interface loopback de l’hôte, et le conteneur peut joindre Ollama via 127.0.0.1:11434 sans qu’Ollama écoute sur une autre interface. La configuration avec un réseau bridge que vous trouverez ailleurs, --add-host=host.docker.internal:host-gateway avec OLLAMA_BASE_URL=http://host.docker.internal:11434, ne fonctionne pas ici : ce nom se résout vers la passerelle du bridge Docker, et un service lié à 127.0.0.1 sur l’hôte n’est pas accessible depuis le bridge. Open WebUI reste donc bloqué et indique qu’il ne peut pas se connecter à Ollama.
La contrepartie du réseau host est qu’Open WebUI écoute désormais sur le port 8080 de l’hôte, sur toutes les interfaces. Toute redirection -p est ignorée, et Docker affiche un avertissement pour le signaler. Fermez donc 8080 à la fois sur l’hôte et dans le pare-feu du fournisseur, puis faites du reverse proxy TLS l’unique point d’accès public. Lors de la toute première visite, Open WebUI vous demande de créer un compte administrateur. Ce compte constitue votre couche d’authentification : choisissez un mot de passe robuste.
Pour ouvrir le chat depuis votre ordinateur portable en HTTPS, placez un reverse proxy TLS devant 127.0.0.1:8080. Si vous acheminez déjà plusieurs applications Docker sur ce serveur, Traefik avec TLS automatique pour plusieurs applications est la solution la plus adaptée : un seul bloc de labels obtient le certificat et achemine chat.example.com vers Open WebUI. Ce même routage par labels, application par application, sera utilisé par toutes les autres interfaces web du serveur, qu’il s’agisse d’un tableau de bord d’état ou d’une application plus ludique comme Halcyon, qui présente une bibliothèque Jellyfin comme un magasin de location des années 90, chacune avec son propre hostname et sa propre connexion. La règle de la section consacrée à la sécurité reste valable : le proxy gère le port public et la connexion, tandis qu’Ollama reste sur localhost et que le propre 8080 d’Open WebUI reste filtré par le pare-feu.
Utiliser le endpoint compatible avec OpenAI depuis votre code
Ollama expose une partie de l’API Chat d’OpenAI à l’adresse /v1. La plupart des bibliothèques clientes OpenAI fonctionnent après avoir modifié deux éléments : l’URL de base et une clé temporaire.
from openai import OpenAI
client = OpenAI(base_url="http://127.0.0.1:11434/v1", api_key="ollama")
resp = client.chat.completions.create(
model="llama3.2:3b",
messages=[{"role": "user", "content": "Name three Linux distributions."}],
)
print(resp.choices[0].message.content)La api_key est obligatoire pour la bibliothèque cliente, mais Ollama l’ignore. N’importe quelle chaîne convient. La model doit correspondre à un nom que vous avez déjà téléchargé. Un nom inconnu renvoie model "x" not found, try pulling it first. Un simple appel avec curl suit le même principe :
curl http://127.0.0.1:11434/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model":"llama3.2:3b","messages":[{"role":"user","content":"Hello"}]}'C’est également ainsi que vous connectez le modèle à des outils d’agents et d’édition. Si vous développez déjà sur le serveur, un modèle local peut alimenter vos scripts et plugins en parallèle de Claude Code exécuté sur le VPS dans tmux. Les tâches de rédaction peu coûteuses et privées restent ainsi en dehors d’une API payante, tandis que le raisonnement complexe est confié à un modèle hébergé.
Modes d’échec, avec les chaînes exactes que vous verrez
Le processus est « Killed » en pleine génération. Vous démarrez un modèle volumineux et le terminal affiche Killed, ou le journal du serveur contient llama runner process has terminated: signal: killed. Le OOM killer de Linux l’a arrêté parce que le modèle nécessitait plus de RAM que le serveur n’en dispose. Confirmez la cause avec sudo dmesg | grep -i oom : vous y verrez une ligne comme Out of memory: Killed process ... (ollama). La solution consiste à utiliser un modèle plus petit ou davantage quantifié, llama3.2:3b au lieu d’un modèle 13B, ou à ajouter du swap afin qu’une charge dépassant de peu la RAM physique puisse terminer lentement au lieu d’échouer. Le swap transforme un crash immédiat en réponse lente ; il ne rend pas un modèle 70B utilisable avec 4 GB. L’arrêt est silencieux, sauf si vous surveillez le terminal au moment où il se produit. Sur un serveur que vous interrogez depuis un autre poste, associer une unité OnFailure= à ollama.service, qui envoie une notification à un serveur ntfy que vous hébergez pour recevoir des alertes push, vous informe dès que le processus s’arrête au lieu de vous laisser le découvrir lors de la requête suivante.
« Error: model requires more system memory ». Ollama refuse de démarrer le modèle et affiche Error: model requires more system memory (X GiB) than is available (Y GiB). C’est la version contrôlée du crash précédent : Ollama a effectué le calcul et s’est arrêté au lieu de laisser le tueur OOM intervenir. Il vous donne même les deux valeurs. Choisissez un modèle dont les besoins sont inférieurs à votre RAM disponible (vérifiez avec free -h), réduisez la longueur du contexte ou passez à un VPS plus grand. Aucun flag ne permet de faire tenir le modèle : la mémoire nécessaire est bien réelle.
Le premier token met très longtemps à arriver, puis tout fonctionne normalement. Un modèle froid n’affiche rien pendant cinq à trente secondes, puis diffuse normalement la réponse. Cette pause correspond au chargement initial des poids depuis le disque vers la RAM, et un stockage lent l’aggrave. Une fois chargé, le modèle reste en mémoire pendant la durée de OLLAMA_KEEP_ALIVE ; le deuxième prompt reçoit donc une réponse instantanée. Augmentez cette valeur si ces pauses vous gênent et utilisez ollama ps pour vérifier si un modèle est actuellement chargé.
Tout est simplement lent. Vous obtenez dix tokens par seconde ou moins, sans aucune erreur. C’est l’inférence sur CPU qui se comporte comme prévu. ollama ps affiche 100% CPU, ce qui signifie qu’aucun GPU n’est disponible. Ce n’est pas un bug et aucun réglage ne peut le corriger, car la limite vient de la bande passante mémoire et non d’une mauvaise configuration. Utilisez un modèle plus petit, acceptez cette vitesse ou passez à une instance équipée d’un GPU. Mesurez votre débit réel avec --verbose avant de conclure que quelque chose ne fonctionne pas. Lorsque l’attente vient de la longueur de la réponse plutôt que du débit, limiter la réponse avec num_predict évite qu’un modèle trop bavard passe plusieurs minutes à générer des tokens que vous n’allez jamais lire.
La connexion est refusée depuis une autre machine. Depuis votre ordinateur portable, vous obtenez curl: (7) Failed to connect to <ip> port 11434: Connection refused. C’est le fonctionnement prévu : Ollama n’écoute que sur localhost. Ne « corrigez » pas le problème en le faisant écouter sur 0.0.0.0, car il s’agit précisément de l’erreur d’exposition décrite plus haut. Accédez au modèle via le VPN ou par l’intermédiaire du proxy authentifiant.
Vous avez exposé 11434 sur Internet. Si vous avez défini OLLAMA_HOST=0.0.0.0, ouvert le firewall et constatez maintenant des téléchargements de modèles que vous n’avez pas lancés ou un CPU saturé à 100 % par des clients inconnus, votre serveur a été découvert et utilisé. C’est l’erreur principale, pas un cas marginal. Faites à nouveau écouter le service sur 127.0.0.1 ou sur l’adresse du VPN, fermez 11434 dans le firewall et placez une authentification devant le service. Considérez que tout ce qui était accessible à cette adresse pendant son exposition a été interrogé par des inconnus.
Sauvegardes et mises à niveau
Il y a peu d’état à préserver. Les modèles peuvent être téléchargés à nouveau. Les seuls éléments qui méritent une sauvegarde sont le volume de données d’Open WebUI, les comptes, l’historique des conversations, les paramètres et tout drop-in systemd que vous avez créé. Sauvegardez le volume avec un conteneur temporaire :
docker run --rm -v open-webui:/data -v "$PWD":/backup alpine \
tar czf /backup/open-webui.tgz -C /data .Mettez à niveau Ollama en réexécutant le script d’installation. Mettez à niveau Open WebUI avec docker pull ghcr.io/open-webui/open-webui:main, puis recréez le conteneur. Ne figez aucune version à long terme : la qualité des modèles et le runtime évoluent rapidement. Lisez les notes de version et réévaluez les performances sur votre propre serveur au lieu de vous fier aux chiffres du trimestre précédent.
FAQ
Puis-je réellement exécuter un LLM sur un VPS avec CPU uniquement ?
Oui, dans certaines limites. Les petits modèles quantifiés de 3B à 8B fonctionnent sur CPU et sont réellement utiles pour rédiger, résumer et classer, mais lentement : de quelques tokens par seconde à une dizaine sur un vCPU partagé. À partir de 13B, l’exécution devient très lente ou le modèle ne tient plus du tout en RAM. Pour obtenir de meilleures performances ou utiliser des modèles plus volumineux, vous avez besoin d’une instance GPU.
De quelle quantité de RAM chaque modèle a-t-il besoin ?
Pour les modèles quantifiés par défaut en 4 bits, comptez environ 0.5 GB de RAM par milliard de paramètres pour les poids, plus environ 1 GB de surcharge et un peu plus pour le contexte. Un modèle 3B nécessite donc environ 4 GB libres, un modèle 7-8B environ 8 GB et un modèle 14B environ 16 GB. Vérifiez la marge disponible avec free -h et laissez de la place pour le système d’exploitation et les autres services du serveur.
L’API Ollama est-elle authentifiée ?
Non. Ollama ne fournit ni authentification intégrée, ni clé d’API, ni limite de débit. Toute personne pouvant atteindre le port 11434 en a le contrôle complet. C’est précisément pourquoi Ollama est lié à 127.0.0.1 par défaut et pourquoi vous ne devez jamais exposer 11434 sur 0.0.0.0 à Internet. Accédez-y localement, via un VPN privé ou par l’intermédiaire d’un reverse proxy qui ajoute une authentification.
Comment ajouter une interface de chat web ?
Exécutez Open WebUI dans Docker avec --network=host afin qu’il partage la loopback de l’hôte et accède à l’instance Ollama native via http://127.0.0.1:11434, puis placez un reverse proxy TLS devant son port 8080 pour y accéder depuis votre ordinateur portable. Laissez 8080 fermé au niveau du firewall afin que le proxy soit le seul point d’accès public. Le compte administrateur propre à Open WebUI fournit l’authentification. Définissez son mot de passe lors du premier démarrage.
Comment l’appeler depuis ma propre application ?
Utilisez l’endpoint compatible avec OpenAI à l’adresse http://127.0.0.1:11434/v1. Configurez n’importe quel SDK OpenAI pour utiliser cette base URL, transmettez n’importe quelle chaîne comme clé d’API puisqu’elle est ignorée, puis définissez model sur le nom d’un modèle que vous avez téléchargé. Le code OpenAI existant fonctionne généralement sans modification, à l’exception de la base URL et de la clé.