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/version Endpoint)
  • 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=8192 schliesst Bedrock-Converse-Default-Loch (4096) fuer alle Modelle
  • function_calling=native ist KRITISCH — Legacy-Mode invalidiert KV-Cache jede Runde, versteckte Kosten
  • top_p=0.9 Standard
  • temperature=0.7 Default, 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 requests aber 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

ENVWertWirkung
THREAD_POOL_SIZE2000FastAPI-Default 40 reicht nicht bei 3+ Usern mit Tool-Use
ENABLE_REALTIME_CHAT_SAVEfalseVerhindert RDS-Pool-Exhaustion durch Chunk-Write
CHAT_RESPONSE_STREAM_DELTA_CHUNK_SIZE5Weniger Cloudflare-Roundtrips, keine spuerbare Latenz
AIOHTTP_CLIENT_TIMEOUT600Default 300s — langes Bedrock-Reasoning
AIOHTTP_CLIENT_TIMEOUT_TOOL_SERVER600Langes MCP-Tool
AIOHTTP_CLIENT_TIMEOUT_TOOL_SERVER_DATA15MCP-Discovery muss schnell sein
AIOHTTP_CLIENT_ALLOW_REDIRECTSfalseSSRF-Schutz
AIOHTTP_POOL_CONNECTIONS_PER_HOST100LiteLLM-Bursts
FORWARD_SESSION_INFO_HEADER_MESSAGE_IDX-OpenWebUI-Message-IdExternal-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: 600s

Security

ENVWertWirkung
ENABLE_DIRECT_CONNECTIONSfalseUser koennen keine eigenen Tool-Server adden
USER_PERMISSIONS_WORKSPACE_TOOLS_ACCESSfalseNur Admins koennen Tools im Workspace anlegen

Audit + Logging

ENVWert
LOG_FORMATjson
AUDIT_LOG_LEVELMETADATA
ENABLE_AUDIT_STDOUTtrue (geht direkt zu CloudWatch)
GLOBAL_LOG_LEVELINFO (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   # SSRF

Spart ~500MB RAM/Worker (sentence-transformers raus).

Cost-Tracking pro User

Drei Wege:

  1. Filter-Function (Outlet) loggt pro Call User-ID + Tokens
  2. LiteLLM-Success-Callbackssuccess_callbacks: ["langfuse"] in LiteLLM-Config
  3. 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:

  1. Admin Panel → Groups → „vf-pilot” anlegen, Andre + Christoph hinzufuegen
  2. Custom-Models (vf-sonnet) → Visibility: Private → Group vf-pilot mit Read-Access
  3. Opus 4.7 → Private → marvin-only Group

Top-10 GitHub Pain-Points fuer Operators

Nur die VF-relevanten:

IssueReactionsStatusRelevanz VF
#16747 API Timeout 100s Long-Running-Toolsmittelopen, kritischdirekt — Cloudflare-Tunnel-Side noch offen
#13718 KB-Loeschung loescht Collections nicht9open, bugDSGVO-Loeschungs-Workaround: pgvector-Collection manuell droppen
#1225 feat: 2FA TOTP59openWorkaround: CF Access davor
#16940 feat: Confirming inputs zu MCP/Tools15openSecurity-Win — Tool-Calls bestaetigen lassen
#5872 feat: Data Sources51open, coreRAG-Verbesserung, Roadmap

Filter / Pipe / Action Functions

Vier Erweiterungs-Konzepte (nur Admin kann anlegen, fuehren beliebigen Python im Server-Prozess aus):

TypWofuerVF-Use-Case
ToolLLM ruft Funktion aufBereits via MCP geloest
PipeEigenes „Model” mit custom pipe()VF-Reporter mit auto-Quellen
Filterinlet/stream/outletAudit, PII, Cost, Source-Citation
ActionButton 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 body

2. 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):

Community (cross-verified):

GitHub Issues (real-world):

Alle aus 2025-2026.