Tener un modelo funcionando en la terminal está bien para hacer una pregunta, pero se queda corto si queremos conservar conversaciones y consultar nuestros documentos desde una ventana. Open WebUI añade esa interfaz y puede conectarse con Ollama para ejecutar el modelo en nuestro propio equipo.
La parte interesante no es subir una carpeta entera y esperar que la IA lo sepa todo. Vamos a montar una instalación pequeña, conectar un modelo y consultar un documento inventado que podamos comprobar. También veremos dónde se guardan los datos y qué tenemos que revisar antes de utilizar archivos privados.

Qué hace cada programa
Ollama carga el modelo y genera las respuestas. Open WebUI ofrece el chat, gestiona usuarios y conversaciones y puede preparar documentos para buscar información en ellos. El modelo que responde y el que convierte el texto en vectores para buscarlo no tienen por qué ser el mismo.
En este ejemplo utilizaremos dos contenedores conectados entre sí. No cambiaremos la dirección del Ollama que podamos tener instalado en el ordenador. La interfaz se publicará únicamente en la dirección local del equipo, y el servidor de Ollama no tendrá un puerto publicado hacia fuera.
Para comprender la instalación de modelos está la guía de Ollama en Linux y elección por RAM y VRAM. Si Docker todavía nos resulta nuevo, conviene empezar por su introducción para usuarios Linux.
Preparar Docker Compose y una clave propia
Necesitamos Docker con el complemento Compose y espacio para las imágenes, los modelos y los datos. Para comprobar que el complemento está disponible:
docker compose version
Creamos una carpeta para esta instalación. Dentro guardaremos compose.yaml y un archivo .env. El ejemplo utiliza nombres fijos de proyecto y volumen: si ya tenemos una instalación con esos nombres, no los reutilizamos para otra ni para una prueba de restauración. Generamos una clave aleatoria:
openssl rand -hex 32
Copiamos el resultado a .env con este formato, sustituyendo el texto por nuestra clave:
WEBUI_SECRET_KEY=pega_aqui_la_clave_que_acabas_de_generar
No publicamos ese archivo en un repositorio. La clave debe mantenerse al recrear el contenedor. No es la contraseña de nuestra cuenta del chat, y poner la misma clave de ejemplo en todas las instalaciones no tiene sentido.
Guardamos este contenido en compose.yaml:
name: esl-ia-local
services:
ollama:
image: ollama/ollama:0.20.3
environment:
OLLAMA_NO_CLOUD: "1"
volumes:
- modelos:/root/.ollama
restart: unless-stopped
open-webui:
image: ghcr.io/open-webui/open-webui:v0.11.4
ports:
- "127.0.0.1:3000:8080"
environment:
OLLAMA_BASE_URL: http://ollama:11434
ENABLE_OPENAI_API: "false"
WEBUI_SECRET_KEY: ${WEBUI_SECRET_KEY:?Configura WEBUI_SECRET_KEY en .env}
RAG_EMBEDDING_ENGINE: ollama
RAG_EMBEDDING_MODEL: embeddinggemma
RAG_EMBEDDING_MODEL_AUTO_UPDATE: "false"
volumes:
- datos:/app/backend/data
depends_on:
- ollama
restart: unless-stopped
volumes:
modelos:
datos:
name: esl_open_webui_datos
Las versiones están fijadas para no cambiar de instalación sin darnos cuenta. Son una base del ejemplo, no una recomendación de permanecer en ellas para siempre. Antes de instalar comprobamos las versiones estables de Open WebUI y sus instrucciones de actualización.
El ejemplo ejecuta Ollama en CPU. No activa automáticamente la GPU del ordenador. Si después necesitamos aceleración, habrá que configurarla para nuestro hardware. Primero nos interesa que una consulta pequeña funcione y saber qué recursos utiliza.
La guía de inicio de Open WebUI distingue las imágenes disponibles. No cambiaría este ejemplo a la variante slim sólo por ahorrar espacio: sus funciones de documentos pueden necesitar servicios adicionales que aquí no hemos preparado.
Arrancar y descargar los dos modelos
Desde la carpeta de la instalación revisamos la configuración y arrancamos:
docker compose config --quiet
docker compose up -d
docker compose ps
Si el puerto 3000 ya está ocupado, cambiamos el número situado entre 127.0.0.1: y :8080 en el archivo. No necesitamos parar la aplicación que ya lo utiliza.
Descargamos un modelo pequeño de conversación y otro para representar los documentos:
docker compose exec ollama ollama pull qwen3:1.7b
docker compose exec ollama ollama pull embeddinggemma
Qwen3 1.7B sirve aquí para empezar con una instalación modesta, no para prometer la calidad de un modelo grande. EmbeddingGemma se utiliza para la búsqueda. No seleccionamos un modelo de embeddings en el chat esperando que redacte respuestas.
Abrimos http://127.0.0.1:3000 en el navegador del mismo ordenador. La primera cuenta de una instalación nueva tiene permisos de administración, así que elegimos una contraseña adecuada y no dejamos ese paso pendiente en una interfaz abierta a otros equipos.
Comprobar la conexión antes de subir documentos
Seleccionamos el modelo de conversación y preguntamos algo sencillo. Si no aparece, revisamos que las descargas han terminado:
docker compose exec ollama ollama list
docker compose logs --tail 60 open-webui
En los ajustes de conexión de la interfaz, el destino de Ollama debe ser http://ollama:11434. Esa dirección utiliza el nombre del servicio dentro de la red de Compose.
localhost dentro del contenedor no es nuestro ordenador ni el otro contenedor. Cambiar la dirección a http://localhost:11434 suele romper precisamente esta separación. Si ya habíamos guardado otra conexión en el panel, comprobamos también ese valor: la configuración persistida puede seguir activa después de editar una variable del archivo.
Antes de adjuntar documentos, revisamos en los ajustes de documentos que el proveedor de embeddings sea Ollama y el modelo sea embeddinggemma. Si cambiamos después ese modelo, necesitaremos reconstruir los índices afectados. No debemos mezclar sin más representaciones de modelos diferentes.
Una prueba pequeña que podamos verificar
Creamos un archivo turnos-taller.md con información inventada:
El taller abre de lunes a viernes, de 09:30 a 17:30.
Los jueves se realizan las revisiones de frenos a las 11:00.
Para cambiar una cita hay que avisar con 24 horas de antelación.
La revisión básica cuesta 28 euros y no incluye piezas de repuesto.
Adjuntamos ese archivo a una conversación y esperamos a que termine de procesarse. Después preguntamos:
Según el documento adjunto, ¿a qué hora se revisan los frenos?
Indica el fragmento del que sacas la respuesta.
Comprobamos si recupera el jueves a las 11:00 y si el fragmento corresponde al archivo. Luego hacemos una pregunta que el documento no responde, como cuánto cuesta reparar una rueda. Una respuesta fiable debería reconocer que ese precio no figura en el texto, no utilizar los 28 euros de la revisión como si fueran otra tarifa.
La prueba no consiste en que el chat escriba una respuesta larga. Consiste en distinguir lo que el documento dice de lo que el modelo puede completar por su cuenta. La documentación de archivos y bases de conocimiento explica cómo adjuntarlos y reutilizarlos.
Documento completo o búsqueda por fragmentos
Para un archivo pequeño podemos utilizar el modo que incorpora su contenido completo a la conversación. Así evitamos empezar por una colección enorme y por un problema de recuperación difícil de diagnosticar.
Cuando el conjunto crece, RAG divide el contenido, prepara representaciones para buscarlo y selecciona los fragmentos relevantes para una pregunta. El modelo genera la respuesta a partir del contexto que recibe. No estamos entrenándolo con todos nuestros documentos ni garantizando que recuerde cada detalle.

El contexto que recibe el modelo cambia según el modo elegido. La comprobación con el documento original sigue siendo necesaria.
En los modos que utilizan herramientas nativas, el modelo también debe saber invocar la búsqueda. Si una conversación normal funciona pero no consulta el archivo, revisamos cómo se ha adjuntado y si el modelo utiliza el modo de recuperación elegido. Para una primera comprobación, un archivo corto adjunto al chat en contexto completo resulta más fácil de revisar.
No toda pregunta necesita una base de conocimiento. Para buscar una frase exacta en una carpeta de textos, una herramienta de búsqueda puede ser más directa y verificable. RAG tiene sentido cuando necesitamos relacionar contenido, pero debemos seguir comprobando los fragmentos citados. Su guía específica desarrolla estos modos.
Por qué un PDF puede dar una respuesta incorrecta
Si el PDF es una imagen de un escaneo, primero hace falta reconocer su texto. Si una tabla se extrae desordenada, el modelo puede recibir columnas mezcladas. Y si un documento contiene instrucciones dirigidas a una IA, hay que tratar esas instrucciones como parte del archivo, no como permisos para ejecutar acciones.
Comprobamos el texto que llega al sistema y empezamos por archivos simples. Una cita con un enlace bonito no prueba que el fragmento respalde la respuesta. Si el dato importa, volvemos al documento original.
No aumentamos el tamaño de contexto, el número de fragmentos y la creatividad del modelo a la vez para resolver un fallo. Cambiamos una cosa, repetimos la misma pregunta y comprobamos si el dato vuelve a aparecer correctamente.
Dónde se guardan las conversaciones y las copias
El volumen esl_open_webui_datos conserva los datos de Open WebUI. El volumen de modelos conserva otra parte de la instalación. Guardar sólo compose.yaml no recupera usuarios, conversaciones y documentos.
Antes de una copia sencilla de los datos, paramos la interfaz para evitar copiar una base de datos mientras se modifica:
docker compose stop open-webui
docker volume inspect esl_open_webui_datos
Si el volumen no existe, no continuamos utilizando otro nombre al azar. Creamos una carpeta copias desde el gestor de archivos y, desde la carpeta de esta instalación, podemos generar el archivo:
docker run --rm --network none \
--mount type=volume,source=esl_open_webui_datos,target=/datos,readonly \
--mount type=bind,source="$PWD/copias",target=/copias \
alpine:3.22 tar -czf /copias/open-webui-datos.tar.gz -C /datos .
docker compose start open-webui
Si no tenemos la imagen Alpine, Docker la descargará antes de ejecutar el contenedor. --network none se aplica al contenedor de copia, no convierte la descarga de una imagen en una operación sin Internet. El archivo de copia puede contener datos privados. Lo protegemos y guardamos también la clave y la configuración necesarias para restaurarlo, fuera del único disco del servidor.
La prueba de recuperación debe hacerse en otro volumen y otra instalación, no sobrescribiendo los datos activos. Abrimos esa copia recuperada con la misma versión y comprobamos una conversación y un documento antes de dar por bueno el procedimiento. La documentación de actualización recoge las precauciones con el almacenamiento.
No utilizamos docker compose down -v como forma de actualizar: eliminar los volúmenes puede borrar precisamente lo que queremos conservar.
Qué datos pueden salir del equipo
Esta configuración desactiva las conexiones OpenAI de la interfaz y las funciones cloud de Ollama, pero no sustituye una revisión de todos los ajustes. Descargas, comprobaciones de versiones o funciones opcionales pueden requerir red. Una búsqueda web, un extractor remoto o un proveedor externo de embeddings cambian dónde se procesa el documento.
Para preparar un entorno sin conexión seguimos el procedimiento oficial de modo offline, descargando antes lo que necesitemos. Un interruptor de modo offline no instala modelos que todavía no existen en el equipo.
Tampoco activaría herramientas capaces de ejecutar comandos para responder preguntas sobre un texto. Hay que separar consultar información de permitir que un agente actúe sobre el ordenador. Los chats y archivos locales siguen necesitando protección del disco y de las cuentas, como explica la documentación de privacidad y cifrado.
Una aclaración sobre la licencia
Open WebUI es autohospedable, pero su licencia vigente incluye condiciones de marca. El propio proyecto explica que las versiones posteriores al cambio no utilizan una licencia aprobada por la OSI. Podemos consultarlo en su página de licencia. No lo llamaría software libre sólo porque tenga el código disponible o la palabra Open en el nombre.
Con una instalación pequeña y unas preguntas comprobables ya podemos decidir si esta forma de consultar documentos nos ayuda. Si el modelo inventa respuestas con un archivo de cuatro líneas, cargar cientos de PDF no va a arreglarlo por sí solo.
