Por qué autoalojar PrivateGPT en un VPS
PrivateGPT está diseñado en torno al RAG (Retrieval-Augmented Generation): ingiere sus documentos, los divide en fragmentos, calcula embeddings almacenados en una base vectorial (Qdrant por defecto, en modo disco local) y después responde a las preguntas apoyándose en ese corpus y citando los pasajes utilizados. Desde la versión 1.0, publicada en junio de 2026, PrivateGPT ya no ejecuta los modelos por sí mismo: se conecta a un servidor de inferencia compatible con OpenAI (Ollama, llama.cpp o vLLM) que usted instala a su lado, en el mismo VPS. El LLM, los embeddings y el índice permanecen así en su máquina y ninguna consulta sale hacia un proveedor de IA.
En un VPS dedicado obtiene un asistente documental de empresa aislado del equipo de cada persona, con una base de conocimiento centralizada que todo el equipo consulta, sin exponer nunca contratos, expedientes de RR. HH. o documentos jurídicos a un servicio en la nube. El reto también es jurídico: pegar un documento con datos personales en una API de IA alojada convierte a ese proveedor en encargado del tratamiento según el RGPD, y el tratamiento debe regirse por un contrato (artículo 28, apartado 3). Un tratamiento que se queda en su propio servidor no añade ese eslabón.
Beneficios concretos del autoalojamiento
- Confidencialidad total: documentos, embeddings e índice Qdrant nunca salen del VPS
- Respuestas con fuentes: cada respuesta se apoya en los pasajes encontrados en sus archivos, no en la memoria general del modelo
- Ningún coste de API si el modelo se ejecuta localmente con Ollama o llama.cpp
- Ingesta de PDF, DOCX, PPTX, EPUB, CSV, Markdown, archivos de correo
.mboxe incluso imágenes o audio, organizados en colecciones - API de tipo Messages (calcada de la especificación de la API de Anthropic) para conectar PrivateGPT con sus herramientas internas
- Cumplimiento más sencillo para datos sensibles (RGPD, secreto profesional): ningún encargado de IA adicional
PrivateGPT y Ollama: dos papeles complementarios
A menudo se confunden ambas herramientas, aunque ocupan dos pisos distintos de la pila. Ollama es un servidor de modelos: descarga LLM y modelos de embeddings, los carga en memoria y expone una API en el puerto 11434. No sabe nada de sus archivos: responde a partir del contexto que se le envía.
PrivateGPT (repositorio zylon-ai/private-gpt, licencia Apache-2.0) es la capa de aplicación RAG: indexa sus documentos, recupera los pasajes pertinentes para cada pregunta y los inyecta en el contexto enviado a Ollama. En la 1.0 nunca funciona solo: sin un servidor de inferencia accesible, arranca sin ningún modelo.
PrivateGPT frente a Ollama: quién hace qué
Desplace la tabla
| Criterio | PrivateGPT 1.0 | Ollama |
|---|---|---|
| Papel | Aplicación RAG: ingesta, búsqueda, respuestas citadas | Servidor de inferencia: carga y ejecuta los modelos |
| Ejecuta el modelo | No: lo delega en un servidor compatible con OpenAI | Sí, en CPU o GPU |
| Lectura de sus archivos | Sí: PDF, DOCX, CSV, `.mbox`… por colecciones | No: contexto aportado a mano |
| Base vectorial | Qdrant (disco local por defecto) | Ninguna |
| Interfaz | Workbench en `/ui`, sin control de acceso | API REST, sin interfaz web en el servidor |
| Puerto por defecto | `8080` | `11434`, ligado a `127.0.0.1` |
Requisitos de hardware y software
La memoria se dimensiona según el modelo que sirve Ollama, no según PrivateGPT. Los modelos propuestos por defecto en la documentación apuntan a una máquina con GPU (qwen3.5:35b, unos 24 GB de descarga): en un VPS con CPU, elija una variante más ligera de la misma familia, qwen3.5:4b (de 3,3 a 4 GB) o qwen3.5:9b (de 6,6 a 7,6 GB), más mxbai-embed-large (unos 670 MB) para los embeddings. Cuente con 8 GB de RAM para la variante 4b y 16 GB para la 9b, para dejar sitio al sistema, a Qdrant y a los documentos en plena ingesta, y al menos 4 vCPU: en CPU, el número de núcleos marca la velocidad de generación.
Prevea 30 GB de disco, idealmente NVMe, para los modelos, el índice Qdrant y los documentos ingeridos: la ingesta de un PDF grande lee y escribe mucho. En cuanto al software: Docker (o Python 3.11 y uv si instala el paquete fuera de un contenedor), Ollama y un dominio que apunte al VPS para exponer la interfaz detrás de un proxy inverso.
Lista de comprobación antes de la instalación
- VPS con 8 GB de RAM como mínimo (16 GB para un modelo de 9 mil millones de parámetros) y 4 vCPU
- Debian 12 o Ubuntu 24.04 actualizados, acceso SSH con
sudo - Docker instalado (
docker versionresponde) o, en su defecto,uvcon Python 3.11 - 30 GB de disco libre, NVMe preferiblemente, para los modelos y
local_data/ - Un subdominio (por ejemplo
docs.su-dominio.com) que apunte a la IP del VPS - Cortafuegos activo: solo SSH, 80 y 443 abiertos; los puertos
8080y11434siguen cerrados
Despliegue de PrivateGPT en modo local
Instalar Ollama y descargar los modelos
Instale Ollama con el script oficial y descargue después un LLM adaptado a CPU y el modelo de embeddings recomendado:
curl -fsSL https://ollama.com/install.sh | sh ollama pull qwen3.5:4b ollama pull mxbai-embed-largePor defecto, Ollama solo escucha en
127.0.0.1:11434: déjelo así, solo PrivateGPT necesita alcanzarlo. Es el único paso que requiere Internet; una vez instalados los modelos, la inferencia se realiza sin conexión.Lanzar PrivateGPT con Docker
La imagen oficial
zylonai/private-gptincluye el paquetecore. En Linux, el contenedor debe compartir la red del host para llegar a Ollama enlocalhost, y un volumen debe conservar los datos; de lo contrario, los documentos ingeridos desaparecen al reiniciar: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:latestAl arrancar, PrivateGPT consulta
GET /v1/modelsen Ollama y registra automáticamente los modelos encontrados: no hace falta ningún archivo de configuración. La variableOPENAI_EMBEDDING_API_BASEsolo es útil si sus embeddings se sirven en otro lugar.Ingerir sus documentos por colección
Envíe sus archivos a la API de ingesta agrupándolos por colección, por ejemplo una colección por expediente de cliente o por departamento:
curl -X POST http://localhost:8080/v1/artifacts/ingest \ -F "file=@/srv/documents/contrat-cession.pdf" \ -F "collection=juridico" curl "http://localhost:8080/v1/artifacts/list?collection=juridico"PrivateGPT divide, vectoriza e indexa cada archivo en Qdrant. Los formatos sin lector dedicado se leen como texto plano.
Consultar el corpus con citas
Pruebe primero en el Workbench (
http://localhost:8080/ui) y conecte después sus herramientas a la API Messages. La búsqueda documental pasa por la herramienta integradasemantic_search_v1, restringida a una colección:curl http://localhost:8080/v1/messages \ -H "Content-Type: application/json" \ -d '{"model": "qwen3.5:4b", "messages": [{"role": "user", "content": "¿Cuáles son las condiciones suspensivas del contrato?"}], "tools": [{"name": "buscar_docs", "type": "semantic_search_v1", "context": [{"type": "ingested_artifact", "context_filter": {"collection": "juridico"}}]}]}'Configurar el proxy inverso, el SSL y la autenticación
El Workbench no tiene ningún control de acceso: la documentación lo reserva a un uso local. Expóngalo únicamente detrás de Nginx o Caddy, con un certificado Let's Encrypt y una autenticación básica:
server { listen 443 ssl; server_name docs.su-dominio.com; ssl_certificate /etc/letsencrypt/live/docs.su-dominio.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/docs.su-dominio.com/privkey.pem; auth_basic "Acceso restringido"; auth_basic_user_file /etc/nginx/.htpasswd; location / { proxy_pass http://127.0.0.1:8080; } }Si solo lo usan dos o tres personas, un túnel SSH (
ssh -L 8080:127.0.0.1:8080 user@su-vps) evita incluso cualquier exposición pública.Bloquear el acceso
PrivateGPT escucha por defecto en
0.0.0.0, de modo que la red del host publica el puerto8080en todas las interfaces. Ciérrelo en el cortafuegos para dejar accesible solo el proxy inverso:ufw default deny incoming ufw allow OpenSSH ufw allow 80,443/tcp ufw enableSus usuarios pasan entonces por
https://docs.su-dominio.comy consultan el corpus en lenguaje natural.
Ollama no sabe anunciar la ventana de contexto de sus modelos, y PrivateGPT solo estima entonces los tokens de forma aproximada: con documentos largos, las respuestas pueden llegar truncadas. Declare context_window explícitamente en un perfil de modelo (archivo settings-<nombre>.yaml, activado con PGPT_PROFILES), con un valor claramente inferior al límite real del modelo. Fije también su modelo de embeddings desde el principio: cambiarlo después provoca un error «Embedding dimensions mismatch» y obliga a reindexar todo el corpus (embed_dim vale 1024 para mxbai-embed-large).
Hacer copias de seguridad y comprobar que ningún dato sale
Qué respaldar. El estado completo de PrivateGPT cabe en /opt/privategpt/local_data (índice Qdrant en local_data/qdrant, archivos ingeridos), además de sus documentos de origen y sus posibles perfiles settings-*.yaml. Los modelos de Ollama se pueden volver a descargar, no hace falta respaldarlos. Detenga el contenedor durante la copia (docker stop privategpt) o copie una instantánea del volumen: un índice copiado durante una ingesta puede quedar incoherente. Para varias instancias o un equipo numeroso, la documentación recomienda un servidor Qdrant independiente en lugar del modo disco local.
Controlar el tráfico saliente. La confidencialidad es una propiedad de la arquitectura, y se comprueba. Durante una serie de preguntas, enumere las conexiones establecidas: solo deben aparecer las de PrivateGPT hacia 127.0.0.1:11434, las del proxy inverso y su sesión SSH.
ss -tnp state establishedCualquier conexión saliente inesperada merece una explicación antes de confiar documentos sensibles a la herramienta.
Solución de problemas: los errores más frecuentes
PrivateGPT arranca sin ningún modelo. Ollama no estaba en marcha al iniciar el contenedor, o OPENAI_API_BASE es incorrecta: la URL debe terminar en /v1. Compruébelo con curl http://localhost:11434/v1/models y reinicie el contenedor (docker restart privategpt).
«Connection refused» desde el contenedor. En un contenedor con red bridge, localhost designa al propio contenedor. En Linux, mantenga --network host; en macOS o Windows, apunte a host.docker.internal.
«Embedding dimensions mismatch» durante la ingesta. El índice se construyó con otro modelo de embeddings. Vuelva al modelo original o vacíe el almacén vectorial (make wipe en el repositorio) y vuelva a ingerir los documentos.
Respuestas truncadas en documentos largos. La ventana de contexto está mal estimada: declare context_window en un perfil de modelo (vea el consejo anterior).
Ollama terminado en plena respuesta. El núcleo se quedó sin memoria (OOM): dmesg | grep -i oom lo confirma. Pase a una variante más pequeña del modelo o amplíe la RAM.
«Address already in use» al arrancar. El puerto 8080 ya está ocupado: en Docker, defina la variable PORT (por ejemplo -e PORT=8090); fuera de un contenedor, use la opción --port de private-gpt serve, y adapte después el proxy_pass de Nginx.