Why OpenWebUI Changes Everything
For years, the default assumption was that serious AI work required surrendering data to proprietary APIs. OpenWebUI shatters that premise. Built as a self-hosted, extensible web interface for large language models, it delivers a ChatGPT-class experience—complete with chat history, model management, document ingestion (RAG), prompt libraries, and multi-user workspaces—while keeping every token, every document, and every conversation on infrastructure you own.
Whether you're a solo developer experimenting on a laptop, a team deploying on a VPS, or an organization running air-gapped clusters, OpenWebUI adapts. Its plugin architecture, OpenAI-compatible API, and native Ollama integration make it the de facto standard for private AI deployments.
Prerequisites and Architecture Overview
Before diving into installation methods, understand what OpenWebUI needs to run:
- Container Runtime: Docker Engine 20.10+ or Podman 4.0+
- Model Backend: Ollama (recommended), vLLM, TGI, or any OpenAI-compatible endpoint
- Storage: Persistent volume for SQLite/PostgreSQL database, uploaded documents, and user data
- Network: Port 8080 (default HTTP) or 443 with reverse proxy TLS
- Resources: Minimum 2 GB RAM for the UI alone; model inference requires additional GPU/CPU/RAM per model
OpenWebUI is the frontend and orchestration layer. It does not include model weights. You must pair it with a model server like Ollama (easiest), vLLM (high throughput), or a remote API (OpenAI, Anthropic, Together, etc.). The UI communicates with backends via standard OpenAI-compatible REST endpoints.
Method 1: Docker Quick Start (Single Command)
The fastest path to a working instance. This command pulls the official image, creates a persistent volume, and exposes the UI on port 8080.
docker run -d \
--name open-webui \
-p 8080:8080 \
-v open-webui:/app/backend/data \
--restart unless-stopped \
ghcr.io/open-webui/open-webui:main
Visit http://your-server-ip:8080. The first account created becomes the administrator. If you already run Ollama on the same host, add --network=host (Linux) or -e OLLAMA_BASE_URL=http://host.docker.internal:11434 (Mac/Windows) so OpenWebUI can discover local models automatically.
Method 2: Docker Compose for Production
Compose adds declarative configuration, secrets management, and easy multi-service wiring (OpenWebUI + Ollama + PostgreSQL + Redis + Nginx).
version: '3.8'
services:
open-webui:
image: ghcr.io/open-webui/open-webui:main
container_name: open-webui
ports:
- "8080:8080"
volumes:
- open-webui-data:/app/backend/data
environment:
- OLLAMA_BASE_URL=http://ollama:11434
- WEBUI_AUTH=True
- WEBUI_SECRET_KEY=${WEBUI_SECRET_KEY}
- DATABASE_URL=postgresql://openwebui:${POSTGRES_PASSWORD}@postgres:5432/openwebui
- REDIS_URL=redis://redis:6379/0
- ENABLE_RAG_LOCAL_WEB_FETCH=True
- ENABLE_RAG_WEB_SEARCH=True
depends_on:
- ollama
- postgres
- redis
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 30s
timeout: 10s
retries: 3
ollama:
image: ollama/ollama:latest
container_name: ollama
volumes:
- ollama-data:/root/.ollama
ports:
- "11434:11434"
restart: unless-stopped
# For GPU support, add: deploy: { resources: { reservations: { devices: [{ driver: nvidia, count: all, capabilities: [gpu] }] } } }
postgres:
image: pgvector/pgvector:pg16
container_name: openwebui-postgres
environment:
- POSTGRES_DB=openwebui
- POSTGRES_USER=openwebui
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
volumes:
- postgres-data:/var/lib/postgresql/data
restart: unless-stopped
redis:
image: redis:7-alpine
container_name: openwebui-redis
volumes:
- redis-data:/data
restart: unless-stopped
volumes:
open-webui-data:
ollama-data:
postgres-data:
redis-data:
Create a .env file alongside docker-compose.yml:
WEBUI_SECRET_KEY=$(openssl rand -hex 32)
POSTGRES_PASSWORD=$(openssl rand -hex 16)
Launch with docker compose up -d. This stack enables persistent chat history, multi-user auth, vector search via pgvector, caching via Redis, and local model inference through Ollama—all wired securely on a private Docker network.
Method 3: Kubernetes (Helm) for Scale
For teams needing horizontal scaling, rolling updates, and GitOps workflows, the official Helm chart is the path.
helm repo add open-webui https://helm.openwebui.com
helm repo update
helm install open-webui open-webui/open-webui \
--namespace open-webui --create-namespace \
--set image.tag=main \
--set ingress.enabled=true \
--set ingress.hosts[0]=ai.yourdomain.com \
--set ingress.tls[0].hosts[0]=ai.yourdomain.com \
--set ingress.tls[0].secretName=openwebui-tls \
--set ollama.enabled=true \
--set postgresql.enabled=true \
--set redis.enabled=true \
--set persistence.enabled=true \
--set persistence.size=20Gi
The chart provisions Ingress with cert-manager TLS, PostgreSQL with pgvector, Redis, and an Ollama sub-chart—all configurable via values.yaml for GitOps.
Method 4: Bare Metal / Systemd (No Containers)
If containers are prohibited, run the Python backend directly. Requires Python 3.11+ and Node 20+ for the frontend build.
# 1. Clone and install backend
git clone https://github.com/open-webui/open-webui.git
cd open-webui/backend
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt
# 2. Build frontend (separate repo or monorepo)
cd ../frontend
npm ci && npm run build
# 3. Configure environment
cp ../.env.example ../.env
# Edit .env: set OLLAMA_BASE_URL, WEBUI_SECRET_KEY, DATABASE_URL, etc.
# 4. Run migrations and start
cd ../backend
alembic upgrade head
python -m uvicorn main:app --host 0.0.0.0 --port 8080
Create a systemd unit at /etc/systemd/system/open-webui.service for auto-start:
[Unit]
Description=OpenWebUI
After=network.target ollama.service postgresql.service redis.service
Wants=ollama.service postgresql.service redis.service
[Service]
Type=exec
User=openwebui
WorkingDirectory=/opt/open-webui/backend
Environment=PATH=/opt/open-webui/backend/venv/bin
EnvironmentFile=/opt/open-webui/.env
ExecStart=/opt/open-webui/backend/venv/bin/uvicorn main:app --host 0.0.0.0 --port 8080
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
"True sovereignty in AI isn't about owning the model weights—it's about owning the context, the history, and the infrastructure that binds them together."
— Hesham Kholef
Post-Install: Essential Configuration
Connect External Model Providers
In the UI: Settings → Admin Panel → Connections. Add any OpenAI-compatible endpoint (Together, Groq, Fireworks, local vLLM). Set API keys per-user or globally. Enable "Allow users to add their own keys" for BYOK workflows.
Enable RAG (Retrieval-Augmented Generation)
Settings → Admin Panel → Documents. Toggle Enable RAG. Configure chunk size (512–1024 tokens), overlap (50–100), and embedding model (default: nomic-embed-text via Ollama). Upload PDFs, Markdown, or URLs—OpenWebUI handles ingestion, vectorization, and citation automatically.
Configure Web Search
Set SEARCH_ENGINE=duckduckgo or searxng in environment variables. Add SEARXNG_URL if self-hosting SearXNG. Users gain real-time grounding with source citations.
Reverse Proxy & TLS (Nginx Example)
server {
listen 443 ssl http2;
server_name ai.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/ai.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/ai.yourdomain.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
}
# WebSocket for real-time streaming
location /ws {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
Model Management: Pull, Tag, and Serve
With Ollama integrated, model management happens inside OpenWebUI (Settings → Models) or via CLI:
# Inside the ollama container or host
docker exec -it ollama ollama pull llama3.1:8b
docker exec -it ollama ollama pull qwen2.5:14b-instruct
docker exec -it ollama ollama pull nemotron3-ultra:latest
# List models
docker exec -it ollama ollama list
# Run a quick test
docker exec -it ollama ollama run llama3.1:8b "Explain quantum entanglement in one paragraph."
For GPU acceleration, ensure the Ollama container has NVIDIA runtime access (--gpus all or Kubernetes device plugin). Quantized GGUF models (4-bit, 8-bit) run efficiently on consumer GPUs with 8–24 GB VRAM.
Backup, Upgrade, and Disaster Recovery
Automated Backup Script
#!/usr/bin/env bash
# backup-openwebui.sh — run daily via cron
set -euo pipefail
BACKUP_DIR="/backups/openwebui/$(date +%F)"
mkdir -p "$BACKUP_DIR"
# Database dump (PostgreSQL)
docker exec openwebui-postgres pg_dump -U openwebui openwebui | gzip > "$BACKUP_DIR/postgres.sql.gz"
# Persistent volumes
docker run --rm -v open-webui-data:/data -v "$BACKUP_DIR":/backup alpine tar czf /backup/openwebui-data.tar.gz -C /data .
docker run --rm -v ollama-data:/data -v "$BACKUP_DIR":/backup alpine tar czf /backup/ollama-data.tar.gz -C /data .
# Retain last 14 days
find /backups/openwebui -type d -mtime +14 -exec rm -rf {} +
Zero-Downtime Upgrade
For Compose: docker compose pull && docker compose up -d --remove-orphans. For Kubernetes: helm upgrade open-webui open-webui/open-webui --namespace open-webui. The rolling update strategy ensures continuous availability.
Troubleshooting Common Issues
| Symptom | Likely Cause | Fix |
|---|---|---|
| Blank page / 502 | Backend not ready or port mismatch | Check docker logs open-webui; verify OLLAMA_BASE_URL |
| Models not appearing | Ollama network unreachable | Use host.docker.internal (Mac/Win) or --network=host (Linux) |
| RAG upload fails | Missing embedding model | Pull nomic-embed-text in Ollama; verify EMBEDDING_MODEL env |
| WebSocket disconnects | Proxy timeout | Increase proxy_read_timeout to 300s in Nginx |
| Permission denied on volumes | UID/GID mismatch | Run chown -R 1000:1000 /data on host paths |
Advanced: Custom Pipelines and Functions
OpenWebUI's Functions system (Settings → Admin Panel → Functions) lets you inject Python logic into the request/response cycle. Examples:
- Guardrails: PII redaction, toxicity scoring, compliance checks
- Tool Use: Custom function calling for internal APIs, SQL, HTTP
- Routing: Send coding tasks to
deepseek-coder, creative writing tollama3.1, analysis tonemotron3 - Post-processing: Auto-format code blocks, add citations, translate responses
Functions are version-controlled, hot-reloadable, and shareable across instances—turning OpenWebUI into a programmable AI gateway.
Conclusion
You now have a production-grade, self-hosted AI workspace that rivals any SaaS offering—without the privacy trade-offs. Start with the Docker quick-start, evolve into Compose with PostgreSQL and Redis, and graduate to Kubernetes when scale demands it. Every deployment path preserves the core promise: your models, your data, your rules.
The next step is yours. Pull a model. Ingest a knowledge base. Build a pipeline. The infrastructure is ready; the only limit is what you choose to ask.
Comments (0)