stack.basicstack.de/apps/openwebui/README.md
CTO b2ee3ffa67 feat(openwebui): deploy Open WebUI v0.11.3 with Pocket ID OIDC (DEV-567)
Adds the Open WebUI stack at openwebui.basicstack.de:

- Namespace `openwebui`, ArgoCD Application with auto-sync + selfHeal
- Own Postgres 16 + pgvector (`pgvector/pgvector:pg16`, 20Gi encrypted PVC,
  fsn1-pinned); VECTOR_DB=pgvector, extension auto-created
- Own Redis 7 (2Gi encrypted PVC, fsn1-pinned) used both as cache and as
  websocket manager (db=1)
- Hetzner Object Storage bucket `openwebui-basicstack` (hel1, path-style)
  for file uploads; shared project S3 credentials
- Traefik ingress + Let's Encrypt TLS
- Pocket ID client `Open WebUI` (PKCE on) restricted to groups
  `openwebui_admins` and `openwebui_users`; `andreas.leinen@basicstack.de`
  is member of both and gets admin via OAUTH_ADMIN_ROLES
- Password login disabled (`ENABLE_LOGIN_FORM=false`, `ENABLE_SIGNUP=false`)

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-09-12 14:06:56 +00:00

3.4 KiB

Open WebUI (openwebui.basicstack.de)

Self-hosted LLM front-end — Open WebUI.

Stack

  • App: ghcr.io/open-webui/open-webui:v0.11.3 (Deployment, 1 replica, Recreate strategy)
  • Database: Postgres 16 + pgvector (pgvector/pgvector:pg16, StatefulSet, PVC 20Gi on hcloud-volumes-encrypted)
  • Vector DB: pgvector in the same Postgres instance (VECTOR_DB=pgvector, extension auto-created on first start)
  • Cache / websocket manager: Redis 7 (StatefulSet, PVC 2Gi on hcloud-volumes-encrypted, WEBSOCKET_MANAGER=redis on db=1)
  • Object storage: Hetzner Object Storage bucket openwebui-basicstack (region hel1, path-style)
  • Auth: Pocket ID OIDC — Open WebUI client, restricted to openwebui_admins / openwebui_users. Sign-up via OAuth only (ENABLE_LOGIN_FORM=false, ENABLE_SIGNUP=false)
  • Ingress: Traefik, TLS via letsencrypt-prod (DNS-01)
  • Node placement: all stateful pods pinned to Hetzner location fsn1 (matches CSI-encrypted PVCs)

Files

File Purpose
namespace.yaml Namespace declaration
postgres.yaml Postgres+pgvector StatefulSet + Service (fsn1-pinned)
redis.yaml Redis StatefulSet + Service (fsn1-pinned)
openwebui.yaml App Deployment + Service + Ingress (+ PVC for local cache)
postgres-credentials-sealed.yaml Sealed Postgres user/db/password
app-secrets-sealed.yaml Sealed WEBUI_SECRET_KEY, DATABASE_URL, PGVECTOR_DB_URL, REDIS_URL, WEBSOCKET_REDIS_URL
oidc-sealed.yaml Sealed OIDC client id + secret
s3-sealed.yaml Sealed S3 access key, secret, endpoint, region, bucket

Deployment references

  • Argo Application: apps/app-openwebui.yaml
  • Pocket ID OIDC client id: 3ffbd06b-12cc-4562-bbe5-da4433962870 (PKCE enabled, group restriction on, allowed groups: openwebui_admins, openwebui_users)
  • Pocket ID groups: openwebui_admins (737f4b7f-63f2-42b5-98bb-4e96c4a80546), openwebui_users (74b0af52-0942-4cb6-b37a-83d87d203e32)
  • OIDC redirect URI: https://openwebui.basicstack.de/oauth/oidc/callback
  • Role mapping: OIDC groups claim → Open WebUI roles. openwebui_admins → admin, openwebui_users → user.
  • Initial admin: andreas.leinen@basicstack.de (member of both groups; OAUTH_ADMIN_ROLES=openwebui_admins)
  • DNS: openwebui.basicstack.de A → 138.199.128.63 (cluster ingress)
  • S3 endpoint: https://hel1.your-objectstorage.com bucket openwebui-basicstack (CORS whitelisted to https://openwebui.basicstack.de). S3 credentials are shared with the Hetzner project (same key used for outline-basicstack, basicstack-backup).

Deferred / follow-ups

  • Model providers (Ollama / OpenAI): none wired yet. Add OLLAMA_BASE_URL or OPENAI_API_BASE_URL/OPENAI_API_KEY via a sealed secret when a backend is chosen.
  • RAG embeddings: RAG_EMBEDDING_ENGINE=default (local). Switch to openai + RAG_OPENAI_* for hosted embeddings when a provider is picked.
  • Content extraction (Tika): not deployed. Add CONTENT_EXTRACTION_ENGINE=tika + TIKA_SERVER_URL once a Tika service is available if PDF/Docx ingestion is required.
  • SMTP: Open WebUI has no built-in mailer; not wired.
  • HA: single replica with Recreate strategy; Redis websocket manager already in place, so scaling to N replicas only requires bumping spec.replicas (Postgres/Redis remain single-instance).