Open WebUI Production-Tuning — Vollstaendiger Report
Destillat aus offizieller Doku + GitHub-Issues + LiteLLM-Docs + Community-Refs. Stand 2026-05-13.
Versions-Realitaet
- VF lauft Open WebUI v0.9.5 (verifiziert via
/api/versionEndpoint) - Agent hatte v0.6.x angenommen und auf v0.6.31-Bug verwiesen — bei uns irrelevant, wir sind viel neuer
- Image-Pin im Stack:
ghcr.io/open-webui/open-webui@sha256:e045bde3b004...(v0.9.5)
Tier 1 — Sofort-Fixes (alle umgesetzt 2026-05-13)
Token & Model-Parameter
DEFAULT_MODEL_PARAMS als globale ENV (greift wenn Custom-Model die Felder leer laesst):
{
"max_tokens": 8192,
"temperature": 0.7,
"top_p": 0.9,
"function_calling": "native"
}Wichtig: Per-Custom-Model params ueberschreibt Default. vf-sonnet hat max_tokens=16384 weil Code-Interpreter-Loops mehr brauchen.
Wirkungen:
max_tokens=8192schliesst Bedrock-Converse-Default-Loch (4096) fuer alle Modellefunction_calling=nativeist KRITISCH — Legacy-Mode invalidiert KV-Cache jede Runde, versteckte Kostentop_p=0.9Standardtemperature=0.7Default, Custom-Model kann per Use-Case anpassen (0.3 fuer Code)
Was Bedrock via LiteLLM IGNORIERT (nicht setzen, ist Noise):
top_k,seed,presence_penalty,frequency_penalty,repeat_penalty,mirostat*,num_ctx,num_keep
Code-Interpreter (Pyodide)
Offizieller Pfad: /mnt/uploads/<name>.<ext>. Open-WebUI-File-Browser listet automatisch.
KEIN display(FileLink(...)) — Jupyter-Pattern, in Pyodide unnoetig. Auto-Detect uebernimmt.
Pre-installed Packages in Pyodide: numpy, pandas, matplotlib, seaborn, scikit-learn, scipy, requests, beautifulsoup4, regex, sympy, tiktoken, pytz, micropip + stdlib.
Limitations:
- C-Extensions (torch, tensorflow, opencv) gehen nicht
- Network-Access ueber
requestsaber Browser-CORS-Begrenzungen - Worker persistent pro Session — Variablen + Files leben zwischen Code-Bloecken
- Files in IndexedDB → persistent ueber Page-Reloads
Security: ENABLE_PIP_INSTALL_FRONTMATTER_REQUIREMENTS=false setzen — verhindert dass User-Tools beliebige Packages pullen.
Performance / Streaming / Multi-User
| ENV | Wert | Wirkung |
|---|---|---|
THREAD_POOL_SIZE | 2000 | FastAPI-Default 40 reicht nicht bei 3+ Usern mit Tool-Use |
ENABLE_REALTIME_CHAT_SAVE | false | Verhindert RDS-Pool-Exhaustion durch Chunk-Write |
CHAT_RESPONSE_STREAM_DELTA_CHUNK_SIZE | 5 | Weniger Cloudflare-Roundtrips, keine spuerbare Latenz |
AIOHTTP_CLIENT_TIMEOUT | 600 | Default 300s — langes Bedrock-Reasoning |
AIOHTTP_CLIENT_TIMEOUT_TOOL_SERVER | 600 | Langes MCP-Tool |
AIOHTTP_CLIENT_TIMEOUT_TOOL_SERVER_DATA | 15 | MCP-Discovery muss schnell sein |
AIOHTTP_CLIENT_ALLOW_REDIRECTS | false | SSRF-Schutz |
AIOHTTP_POOL_CONNECTIONS_PER_HOST | 100 | LiteLLM-Bursts |
FORWARD_SESSION_INFO_HEADER_MESSAGE_ID | X-OpenWebUI-Message-Id | External-Tool-Events fuer Status-Updates im UI |
Cloudflare-Tunnel 100s-Falle (Issue #16747)
Symptom: Open WebUI sendet bei Long-Tool-Calls erst beim Tool-Result die ersten Stream-Bytes. CF-Tunnel cuttet bei 100s ohne Daten → Gateway-Error.
Stack-Side mitigated (siehe Tabelle oben). Tunnel-Side noch offen:
# cloudflared-Config (im Tunnel-Token-Dashboard)
ingress:
- hostname: vf-chat.agenticventures.de
service: http://localhost:8080
originRequest:
connectTimeout: 600s
tcpKeepAlive: 30s
noTLSVerify: true
keepAliveTimeout: 600sSecurity
| ENV | Wert | Wirkung |
|---|---|---|
ENABLE_DIRECT_CONNECTIONS | false | User koennen keine eigenen Tool-Server adden |
USER_PERMISSIONS_WORKSPACE_TOOLS_ACCESS | false | Nur Admins koennen Tools im Workspace anlegen |
Audit + Logging
| ENV | Wert |
|---|---|
LOG_FORMAT | json |
AUDIT_LOG_LEVEL | METADATA |
ENABLE_AUDIT_STDOUT | true (geht direkt zu CloudWatch) |
GLOBAL_LOG_LEVEL | INFO (Default; auf WARNING runter wenn Volume zu hoch) |
CloudWatch Logs Insights kann dann gefiltert nach Audit-Events queryen.
Branding / Locale
WEBUI_NAME="VF Chat" # schon gesetzt
DEFAULT_LOCALE="de-DE" # Default deutsch
WEBUI_URL="https://vf-chat.agenticventures.de"Lizenz-Realitaet: bei <50 Usern in 30 Tagen darf „Open WebUI”-Logo NICHT entfernt werden ohne Enterprise-License. WEBUI_NAME und Favicon-Anpassung sind OK.
Tier 2 — Mittlerer Aufwand, Wichtig
Prompt-Caching verifizieren
Mindesttoken pro Cache-Checkpoint: Sonnet 4.5/4.6 = 2048 Tokens. Unter Schwelle greift gar nichts.
vf-sonnet v2.3 hat ~3300 Tokens System-Prompt → sicher drueber.
Verifikation: Outlet-Filter-Function die cache_read_input_tokens pro Call loggt. Wenn nach 2-3 Folge-Calls im selben Chat noch 0 → Caching greift nicht, dann pruefen.
LiteLLM-Side: cache_control_injection_points ist gesetzt (in der LiteLLM-Config). Funktioniert via OpenAI→Bedrock-Uebersetzung.
Audit-Filter-Function
Schreibt pro Tool-Call: User, Model, Tokens-In/Out, Cache-Hit-Rate, geschaetzte Kosten in stdout → CloudWatch Logs Insights.
Skelett siehe Pattern-File filter-functions.
PII-Maskierungs-Filter
Erkennt DE-Telefon, Email, IBAN, Steuer-ID → [REDACTED] bevor an LLM. Wichtig fuer Kunden-Daten in Chats.
Native Function Calling explizit verifizieren
Admin → Settings → Models → ⚙️ → Function Calling. Sollte global auf „native” stehen. Per-Modell ueberschreibbar.
DEFAULT_MODEL_PARAMS deckt das ab — aber pruefen ob das UI-Feld dasselbe macht.
Tier 3 — Nice-to-have
RAG: pgvector + Bedrock Titan Embeddings
VECTOR_DB=pgvector
PGVECTOR_DB_URL=postgresql://... # gleicher RDS-Cluster
RAG_EMBEDDING_ENGINE=openai
RAG_OPENAI_API_BASE_URL=http://litellm:4000/v1
RAG_EMBEDDING_MODEL=amazon.titan-embed-text-v2:0
CONTENT_EXTRACTION_ENGINE=tika
RAG_FILE_MAX_SIZE=50
RAG_FILE_MAX_COUNT=10
RAG_ALLOWED_FILE_EXTENSIONS=.pdf,.docx,.txt,.md,.csv,.xlsx
ENABLE_RAG_LOCAL_WEB_FETCH=false # SSRFSpart ~500MB RAM/Worker (sentence-transformers raus).
Cost-Tracking pro User
Drei Wege:
- Filter-Function (Outlet) loggt pro Call User-ID + Tokens
- LiteLLM-Success-Callbacks —
success_callbacks: ["langfuse"]in LiteLLM-Config - Langfuse hosted oder self-hosted — separate Service
Empfehlung: LiteLLM-Side (Filter-Function als Backup).
2FA
Issue #1225 (59 Upvotes) — Roadmap. Nicht out-of-the-box.
Workaround: Cloudflare Access davor mit MFA (haben wir bei mcp-vf-hosted analog).
Multi-User Permissions
Wenn VF skaliert auf 5+ User:
- Admin Panel → Groups → „vf-pilot” anlegen, Andre + Christoph hinzufuegen
- Custom-Models (vf-sonnet) → Visibility: Private → Group
vf-pilotmit Read-Access - Opus 4.7 → Private →
marvin-onlyGroup
Top-10 GitHub Pain-Points fuer Operators
Nur die VF-relevanten:
| Issue | Reactions | Status | Relevanz VF |
|---|---|---|---|
| #16747 API Timeout 100s Long-Running-Tools | mittel | open, kritisch | direkt — Cloudflare-Tunnel-Side noch offen |
| #13718 KB-Loeschung loescht Collections nicht | 9 | open, bug | DSGVO-Loeschungs-Workaround: pgvector-Collection manuell droppen |
| #1225 feat: 2FA TOTP | 59 | open | Workaround: CF Access davor |
| #16940 feat: Confirming inputs zu MCP/Tools | 15 | open | Security-Win — Tool-Calls bestaetigen lassen |
| #5872 feat: Data Sources | 51 | open, core | RAG-Verbesserung, Roadmap |
Filter / Pipe / Action Functions
Vier Erweiterungs-Konzepte (nur Admin kann anlegen, fuehren beliebigen Python im Server-Prozess aus):
| Typ | Wofuer | VF-Use-Case |
|---|---|---|
| Tool | LLM ruft Funktion auf | Bereits via MCP geloest |
| Pipe | Eigenes „Model” mit custom pipe() | VF-Reporter mit auto-Quellen |
| Filter | inlet/stream/outlet | Audit, PII, Cost, Source-Citation |
| Action | Button unter Message | „Antwort als Gmail-Draft” via gsuite-MCP |
Beispiele in github.com/open-webui/pipelines/examples/filters.
Konkrete Funktionen fuer VF
1. Audit-Filter (outlet)
class Filter:
async def outlet(self, body, __user__=None, __metadata__=None):
usage = body.get("usage", {})
record = {
"user_id": __user__.get("id"),
"user_email": __user__.get("email"),
"model": __metadata__.get("model_id"),
"chat_id": __metadata__.get("chat_id"),
"prompt_tokens": usage.get("prompt_tokens"),
"completion_tokens": usage.get("completion_tokens"),
"cache_read_tokens": usage.get("cache_read_input_tokens", 0),
"cache_creation_tokens": usage.get("cache_creation_input_tokens", 0),
}
import json
print(f"[VF-AUDIT] {json.dumps(record)}") # CloudWatch
return body2. PII-Maskierung (inlet)
import re
PATTERNS = {
"iban": r"\bDE\d{2}\s?(?:\d{4}\s?){4}\d{2}\b",
"phone_de": r"\b(?:\+49|0)[1-9]\d{1,4}[\s\-/]?\d{1,10}\b",
"email": r"\b[\w._%+-]+@[\w.-]+\.\w{2,}\b",
}
# inlet: regex-replace in body["messages"][-1]["content"]3. Source-Citation-Injector (outlet)
Wenn body["sources"] vorhanden: am Ende der Antwort eine „Quellen:“-Liste prependen. Gut fuer VF-Reports.
4. Cost-Cap-Action
Action-Button „💰 Kosten” → emittet Status mit kumulierten Kosten pro Chat.
Quellen
Offiziell (hohe Verlaesslichkeit):
- docs.openwebui.com — primaer
- docs.openwebui.com/reference/env-configuration — ENV-Vars
- docs.litellm.ai/docs/completion/prompt_caching — Bedrock-Caching
- docs.aws.amazon.com/bedrock/latest/userguide/prompt-caching.html
Community (cross-verified):
- taylorwilsdon/open-webui-tools — Operator-Guide
- github.com/open-webui/pipelines — Filter/Pipe-Beispiele
GitHub Issues (real-world):
Alle aus 2025-2026.