Open WebUI
Open WebUI
Self-hosted chat interface for a remote Ollama instance, with retrieval-augmented web search. Runs in the default namespace of the k3s cluster, fronted by Traefik.
Deployment
| Item | Value |
|---|---|
| Image | ghcr.io/open-webui/open-webui:latest |
| Namespace | default |
| Replicas | 1 (Recreate strategy) |
| Node placement | Pinned to cm4-left via nodeSelector |
| Service | ClusterIP, port 8080 |
| Ingress | Traefik IngressRoute — chat.prod-k3s.iot-proxmox.net / www.chat.prod-k3s.iot-proxmox.net, TLS via the shared local-example-com-tls wildcard cert |
| Storage | open-webui-data PVC, 5Gi, longhorn storage class, mounted at /app/backend/data |
| Auto-reload | reloader.stakater.com/auto: "true" |
Configuration
Open WebUI points at an external Ollama server rather than running its own model runtime:
| Env var | Value |
|---|---|
OLLAMA_BASE_URL | https://ollama.intel.iot-proxmox.net |
ENABLE_RAG_WEB_SEARCH | True |
RAG_WEB_SEARCH_ENGINE | searxng |
RAG_WEB_SEARCH_RESULT_COUNT | 3 |
RAG_WEB_SEARCH_CONCURRENT_REQUESTS | 10 |
WEBUI_SECRET_KEY | Sourced from the open-webui-secrets Secret |
TZ | America/New_York |
Why longhorn and not local-path
The PVC uses the longhorn storage class rather than local-path. The volume holds real, growing user data (chat history, accounts, uploaded documents, webui.db) and the pod isn’t pinned by node affinity for scheduling purposes in a way that guarantees it always lands on the same node as a local-path volume — longhorn replicates across nodes and binds Immediate, avoiding the failure mode where a local-path PV is stranded on a downed node.
WEBUI_SECRET_KEY gotcha
If WEBUI_SECRET_KEY isn’t set explicitly, Open WebUI writes an auto-generated key to /app/backend/.webui_secret_key — outside the PVC-backed DATA_DIR. Every pod restart would then regenerate the key and invalidate all logged-in sessions. This is worked around by setting WEBUI_SECRET_KEY explicitly via the open-webui-secrets Secret; rotating that secret logs every user out.
Readiness/liveness probes
Cold start downloads the RAG embedding model (sentence-transformers/all-MiniLM-L6-v2) from Hugging Face before the server starts listening — this took roughly 10 minutes on first boot, hence generous probe settings (initialDelaySeconds: 30, failureThreshold: 60 on both probes against GET /health). Without this, Traefik routes to the pod before it’s ready and every request 502s until the download finishes.
Migrated from Docker Compose
Originally ran as a Docker container on a separate Intel NUC host (chat.intel.iot-proxmox.net). Converted to this cluster’s Kubernetes pattern (Deployment + ClusterIP Service + PVC + Traefik IngressRoute) with the hostname updated to chat.prod-k3s.iot-proxmox.net to match every other app already migrated. PUID/PGID and host-path /etc/localtime mounts were dropped (not applicable to this image or a multi-node cluster) in favor of a TZ env var.