Pourquoi self-héberger PrivateGPT sur un VPS
PrivateGPT est conçu autour du RAG (Retrieval-Augmented Generation) : il ingère vos documents, les découpe en fragments, calcule des embeddings stockés dans une base vectorielle (Qdrant par défaut, en mode disque local), puis répond aux questions en s'appuyant sur ce corpus et en citant les passages utilisés. Depuis la version 1.0, publiée en juin 2026, PrivateGPT ne fait plus tourner les modèles lui-même : il se branche sur un serveur d'inférence compatible OpenAI (Ollama, llama.cpp ou vLLM) que vous installez à côté, sur le même VPS. Le LLM, les embeddings et l'index restent ainsi sur votre machine, aucune requête ne part vers un fournisseur d'IA.
Sur un VPS dédié, vous obtenez un assistant documentaire d'entreprise isolé du poste de chacun, avec une base de connaissances centralisée que toute l'équipe interroge, sans jamais exposer des contrats, dossiers RH ou documents juridiques à un service cloud. L'enjeu est aussi juridique : coller un document contenant des données personnelles dans une API d'IA hébergée fait de ce fournisseur un sous-traitant au sens du RGPD, dont le traitement doit être encadré par un contrat (article 28, paragraphe 3). Un traitement qui reste sur votre propre serveur n'ajoute pas ce maillon.
Bénéfices concrets de l'auto-hébergement
- Confidentialité totale : documents, embeddings et index Qdrant ne quittent jamais le VPS
- Réponses sourcées : chaque réponse s'appuie sur les passages retrouvés dans vos fichiers, pas sur la mémoire générale du modèle
- Aucun coût d'API si le modèle tourne localement via Ollama ou llama.cpp
- Ingestion de PDF, DOCX, PPTX, EPUB, CSV, Markdown, archives e-mail
.mboxet même images ou audio, rangés par collections - API de type Messages (calquée sur la spécification de l'API d'Anthropic) pour brancher PrivateGPT dans vos outils internes
- Conformité facilitée pour les données sensibles (RGPD, secret professionnel) : pas de sous-traitant IA supplémentaire
PrivateGPT et Ollama : deux rôles complémentaires
On confond souvent les deux outils, alors qu'ils occupent deux étages différents de la pile. Ollama est un serveur de modèles : il télécharge des LLM et des modèles d'embeddings, les charge en mémoire et expose une API sur le port 11434. Il ne sait rien de vos fichiers : il répond à partir du contexte qu'on lui envoie.
PrivateGPT (dépôt zylon-ai/private-gpt, licence Apache-2.0) est la couche applicative RAG : il indexe vos documents, retrouve les passages pertinents à chaque question et les injecte dans le contexte envoyé à Ollama. En 1.0, il ne fonctionne donc jamais seul : sans serveur d'inférence joignable, il démarre sans aucun modèle.
PrivateGPT vs Ollama : qui fait quoi
Faites défiler le tableau
| Critère | PrivateGPT 1.0 | Ollama |
|---|---|---|
| Rôle | Application RAG : ingestion, recherche, réponses citées | Serveur d'inférence : charge et exécute les modèles |
| Exécute le modèle | Non : délègue à un serveur compatible OpenAI | Oui, sur CPU ou GPU |
| Lecture de vos fichiers | Oui : PDF, DOCX, CSV, `.mbox`… par collections | Non : contexte fourni à la main |
| Base vectorielle | Qdrant (disque local par défaut) | Aucune |
| Interface | Workbench sur `/ui`, sans contrôle d'accès | API REST, pas d'interface web côté serveur |
| Port par défaut | `8080` | `11434`, lié à `127.0.0.1` |
Prérequis matériels et logiciels
La mémoire se dimensionne sur le modèle servi par Ollama, pas sur PrivateGPT lui-même. Les modèles proposés par défaut dans la documentation visent une machine à GPU (qwen3.5:35b, environ 24 Go à télécharger) : sur un VPS CPU, choisissez une variante plus légère de la même famille, qwen3.5:4b (3,3 à 4 Go) ou qwen3.5:9b (6,6 à 7,6 Go), plus mxbai-embed-large (environ 670 Mo) pour les embeddings. Comptez 8 Go de RAM pour la variante 4b et 16 Go pour la 9b, afin de laisser de la place au système, à Qdrant et aux documents en cours d'ingestion, et au moins 4 vCPU : sur CPU, c'est le nombre de cœurs qui fixe la vitesse de génération.
Prévoyez 30 Go de disque, idéalement en NVMe, pour les modèles, l'index Qdrant et les documents ingérés : l'ingestion d'un gros PDF lit et écrit beaucoup. Côté logiciel : Docker (ou Python 3.11 et uv si vous installez le paquet hors conteneur), Ollama, et un domaine pointant vers le VPS pour exposer l'interface derrière un reverse proxy.
Liste de contrôle avant l'installation
- VPS avec 8 Go de RAM minimum (16 Go pour un modèle de 9 milliards de paramètres) et 4 vCPU
- Debian 12 ou Ubuntu 24.04 à jour, accès SSH avec
sudo - Docker installé (
docker versionrépond) ou, à défaut,uvavec Python 3.11 - 30 Go de disque libre, NVMe de préférence, pour les modèles et
local_data/ - Un sous-domaine (par exemple
docs.votre-domaine.com) pointant vers l'IP du VPS - Pare-feu actif : seuls SSH, 80 et 443 ouverts, les ports
8080et11434restent fermés
Déploiement de PrivateGPT en mode local
Installer Ollama et tirer les modèles
Installez Ollama avec le script officiel, puis téléchargez un LLM adapté au CPU et le modèle d'embeddings recommandé :
curl -fsSL https://ollama.com/install.sh | sh ollama pull qwen3.5:4b ollama pull mxbai-embed-largePar défaut, Ollama n'écoute que sur
127.0.0.1:11434: laissez-le ainsi, seul PrivateGPT doit pouvoir le joindre. C'est la seule étape qui a besoin d'Internet ; une fois les modèles en place, l'inférence se fait hors ligne.Lancer PrivateGPT avec Docker
L'image officielle
zylonai/private-gptembarque le paquetcore. Sur Linux, le conteneur doit partager le réseau de l'hôte pour atteindre Ollama surlocalhost, et un volume doit conserver les données, sinon les documents ingérés disparaissent au redémarrage :mkdir -p /opt/privategpt/local_data docker run -d --name privategpt --restart unless-stopped \ --network host \ -e OPENAI_API_BASE=http://localhost:11434/v1 \ -v /opt/privategpt/local_data:/home/worker/app/local_data \ zylonai/private-gpt:latestAu démarrage, PrivateGPT interroge
GET /v1/modelssur Ollama et enregistre automatiquement les modèles trouvés : aucun fichier de configuration n'est requis. La variableOPENAI_EMBEDDING_API_BASEn'est utile que si vos embeddings sont servis ailleurs.Ingérer vos documents par collection
Envoyez vos fichiers à l'API d'ingestion en les regroupant par collection, par exemple une collection par dossier client ou par service :
curl -X POST http://localhost:8080/v1/artifacts/ingest \ -F "file=@/srv/documents/contrat-cession.pdf" \ -F "collection=juridique" curl "http://localhost:8080/v1/artifacts/list?collection=juridique"PrivateGPT découpe, vectorise et indexe chaque fichier dans Qdrant. Les formats sans lecteur dédié sont lus comme du texte brut.
Interroger le corpus avec citations
Testez d'abord dans le Workbench (
http://localhost:8080/ui), puis branchez vos outils sur l'API Messages. La recherche documentaire passe par l'outil intégrésemantic_search_v1, restreint à une collection :curl http://localhost:8080/v1/messages \ -H "Content-Type: application/json" \ -d '{"model": "qwen3.5:4b", "messages": [{"role": "user", "content": "Quelles sont les conditions suspensives du contrat ?"}], "tools": [{"name": "recherche_docs", "type": "semantic_search_v1", "context": [{"type": "ingested_artifact", "context_filter": {"collection": "juridique"}}]}]}'Mettre en place le reverse proxy, le SSL et l'authentification
Le Workbench n'a aucun contrôle d'accès : la documentation le réserve à un usage local. Exposez-le uniquement derrière Nginx ou Caddy, avec un certificat Let's Encrypt et une authentification basique :
server { listen 443 ssl; server_name docs.votre-domaine.com; ssl_certificate /etc/letsencrypt/live/docs.votre-domaine.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/docs.votre-domaine.com/privkey.pem; auth_basic "Accès restreint"; auth_basic_user_file /etc/nginx/.htpasswd; location / { proxy_pass http://127.0.0.1:8080; } }Si seules deux ou trois personnes s'en servent, un tunnel SSH (
ssh -L 8080:127.0.0.1:8080 user@votre-vps) évite même toute exposition publique.Verrouiller l'accès
PrivateGPT écoute par défaut sur
0.0.0.0, et le mode réseau hôte publie donc le port8080sur toutes les interfaces. Fermez-le au pare-feu pour ne laisser joignable que le reverse proxy :ufw default deny incoming ufw allow OpenSSH ufw allow 80,443/tcp ufw enableVos utilisateurs passent alors par
https://docs.votre-domaine.comet interrogent le corpus en langage naturel.
Ollama ne sait pas annoncer la fenêtre de contexte de ses modèles, et PrivateGPT n'estime alors les tokens que grossièrement : sur des documents longs, les réponses peuvent être tronquées. Déclarez context_window explicitement dans un profil de modèle (fichier settings-<nom>.yaml, activé par PGPT_PROFILES), avec une valeur nettement sous la limite réelle du modèle. Fixez aussi votre modèle d'embeddings dès le départ : en changer après coup provoque une erreur « Embedding dimensions mismatch » et impose de réindexer tout le corpus (embed_dim vaut 1024 pour mxbai-embed-large).
Sauvegarder et vérifier qu'aucune donnée ne sort
Ce qu'il faut sauvegarder. L'état complet de PrivateGPT tient dans /opt/privategpt/local_data (index Qdrant sous local_data/qdrant, fichiers ingérés), plus vos documents sources et vos éventuels profils settings-*.yaml. Les modèles Ollama se retéléchargent, inutile de les sauvegarder. Arrêtez le conteneur le temps de la copie (docker stop privategpt), ou copiez un instantané du volume : un index copié pendant une ingestion peut être incohérent. Pour plusieurs instances ou une équipe nombreuse, la documentation recommande un serveur Qdrant distinct plutôt que le mode disque local.
Contrôler le trafic sortant. La confidentialité est une propriété de l'architecture, et elle se vérifie. Pendant une série de questions, listez les connexions établies : seules doivent apparaître celles de PrivateGPT vers 127.0.0.1:11434, celles du reverse proxy et votre session SSH.
ss -tnp state establishedToute connexion sortante inattendue mérite d'être expliquée avant de confier des documents sensibles à l'outil.
Dépannage : les erreurs les plus fréquentes
PrivateGPT démarre sans aucun modèle. Ollama n'était pas lancé au démarrage du conteneur, ou OPENAI_API_BASE est faux : l'URL doit se terminer par /v1. Vérifiez avec curl http://localhost:11434/v1/models, puis redémarrez le conteneur (docker restart privategpt).
« Connection refused » depuis le conteneur. Dans un conteneur en réseau bridge, localhost désigne le conteneur lui-même. Sur Linux, gardez --network host ; sur macOS ou Windows, visez host.docker.internal.
« Embedding dimensions mismatch » à l'ingestion. L'index a été construit avec un autre modèle d'embeddings. Revenez au modèle d'origine, ou videz le magasin vectoriel (make wipe dans le dépôt) et réingérez les documents.
Réponses tronquées sur les longs documents. La fenêtre de contexte est mal estimée : déclarez context_window dans un profil de modèle (voir l'astuce ci-dessus).
Ollama tué en pleine réponse. Le noyau a manqué de mémoire (OOM) : dmesg | grep -i oom le confirme. Passez à une variante plus petite du modèle ou augmentez la RAM.
« Address already in use » au démarrage. Le port 8080 est déjà pris : en Docker, définissez la variable PORT (par exemple -e PORT=8090), hors conteneur l'option --port de private-gpt serve, puis adaptez le proxy_pass de Nginx.