Lessons Learned — Open WebUI Build
Kritische Erkenntnisse aus dem Sprint die im Pattern-File nachzupflegen + bei Folge-Kunden mitbedenken sind.
Open WebUI Stack-Architektur
1. Open WebUI hat KEIN natives Bedrock-Support
Architektur-Philosophie: nur OpenAI-API-compatible im Core. Bedrock-Modelle muessen ueber LiteLLM-Proxy als Sidecar laufen.
Konkret im Stack:
- LiteLLM-Container im selben Fargate-Task, port 4000
- Open WebUI Env
OPENAI_API_BASE_URLS=http://localhost:4000/v1 - LiteLLM Master-Key in Secrets Manager, geshared zwischen open-webui + litellm
- TaskRole bekommt Bedrock-Invoke-Permissions, LiteLLM nutzt die via IAM
- LiteLLM-Config inline via sh-c-Heredoc (kein Mount-Volume)
Alternativen: AWS Bedrock Access Gateway (single-purpose), Bedrock Mantle (nur open-weight). Wir bleiben bei LiteLLM weil multi-provider.
2. Open WebUI hat KEIN MongoDB-Support
Im Gegensatz zu LibreChat (das nur MongoDB hat). Open WebUI nutzt Peewee ORM → SQLite, PostgreSQL, MySQL.
Fail-Pattern den wir hatten: LibreChat-Pattern-Carryover war Mongo-Sidecar im Stack. Beim ersten Boot: RuntimeError: Unrecognized or unsupported scheme: "mongodb". Komplett Mongo raus, SQLite-Default genutzt.
3. SQLite-auf-EFS-NFS ist NICHT production-tauglich
DAS ist der Killer der den Stack mehrfach hat haengen lassen.
Symptom: Browser-Request-Storm (~18 parallele /api/config-Calls beim Page-Load) + SQLite-File-Lock auf EFS-NFS (5-10ms Latency pro Lock-Op statt 50µs auf SSD) → Worker-Pool blockiert komplett → UI antwortet nicht mehr.
Workarounds die wir gemacht haben:
UVICORN_WORKERS=2→ zweiter Worker faengt Hang auf, eliminiert ihn nicht- Custom-Model mit attached MCP-Tools → weniger UI-State-Refreshes durch Tools-Toggle
- Manuelles Stop-Task-Restart wenn’s haengt
Echter Fix (PFLICHT-Followup): RDS PostgreSQL t4g.micro Single-AZ, +14 €/Mo. Postgres macht MVCC, parallele Reads ohne Lock-Block.
4. WEBUI_SYSTEM_PROMPT existiert NICHT als Env-Var
Mein erster Versuch einen globalen System-Prompt zu setzen. Open WebUI hat keinen globalen-System-Prompt-via-Env-Var.
Korrekte Setup-Pfade:
- Per-User-Setting via
POST /api/v1/users/user/settings/updatemit{"ui": {"system": "..."}} - Per-Modell via Custom Model ueber
POST /api/v1/models/createmitparams.system. Dort substituiert Open WebUI auch{{CURRENT_DATE}},{{USER_NAME}}etc.
Empfehlung: Custom-Model-Setup, weil multi-user-tauglich. So gemacht mit Modell vf-sonnet.
5. Template-Variables {{CURRENT_DATE}} greifen nur in Custom-Model
Open WebUI substituiert {{CURRENT_DATE}}, {{CURRENT_WEEKDAY}}, {{CURRENT_TIME}}, {{USER_NAME}}, {{USER_EMAIL}}, {{USER_ROLE}} zur Request-Zeit — aber nur im Custom-Model-System-Prompt, nicht in der ui.system User-Setting (wo’s literal als String mitgeschickt wird).
6. Tool-Server URL/Path-Split-Bug bei MCP Streamable-HTTP
Open WebUI’s Tool-Server-Schema hat url + path getrennt. Bei MCP-Streamable-HTTP-Type: path wird beim Discovery-Call ignoriert, URL muss komplett sein.
Konfig die funktioniert:
{
"url": "https://mcp-vf.agenticventures.de/mcp",
"path": "",
"type": "mcp",
"auth_type": "oauth_2.1"
}Konfig die nicht funktioniert (Open WebUI sendet POST zu / statt /mcp):
{
"url": "https://mcp-vf.agenticventures.de",
"path": "/mcp"
}7. API-Keys: ENABLE_API_KEYS=true als Env-Var nicht Default
Default ist false. Wenn man programmatic die API ansprechen will: env-var setzen, Container muss neu starten, dann ist enable_api_keys in /api/config true.
Plus: Admin-Account muss erst registriert sein (mit ENABLE_INITIAL_ADMIN_SIGNUP=true durch den ersten Signup, der dann automatisch Admin wird).
8. ENABLE_OLLAMA_API=false setzen wenn kein Ollama
Default: Open WebUI versucht host.docker.internal:11434 zu erreichen. In unserem Fargate-Setup: 500-Errors auf /ollama/api/version, die ueber Lifecycle das Admin Panel kaputtmachen.
9. minHealthyPercent: 100 fuer Make-Before-Break
Default-CDK ist minHealthyPercent: 0 mit desiredCount: 1 → ECS killt alten Task vor neuem HEALTHY = ~90s Tunnel-Downtime bei jedem Deploy.
Mit minHealthyPercent: 100 + maxHealthyPercent: 200: temporaer 2 Tasks waehrend Rolling-Deploy, alter bleibt bis neuer ready ist.
10. API-Key-Auth via Authorization: Bearer sk-...
Open WebUI API-Keys haben Format sk-<32 hex chars> = 35 Zeichen total. Auth via Authorization: Bearer sk-....
Falls Key-Validation fail-t obwohl er korrekt aussieht: Container wurde inzwischen restartet, Key in DB ggf. nicht persistiert. Neuen Key erstellen.
Cloudflare-Tunnel-Setup
11. API-Token vs Connector-Token unterscheiden
- CF-API-Token (
cfut_...) — fuer Account-API-Calls (Tunnel-Create, DNS-Edit). Wir nutzen das fuer Setup. - Tunnel-Connector-Token (
eyJhIjoi...-Base64-JSON, ~200 Zeichen) — fuer cloudflared-Daemon-Auth zum Tunnel. Wir speichern das in AWS Secrets Manager.
Beim ersten Setup: API-Token in tmp/cf-build-token parken (kein Inline-Embed in Shell weil Sandbox blockt), nach Setup Force-Delete.
12. Make-vor-DNS-Aktivierung
Tunnel + Ingress-Config + Token in Secret VOR DNS-CNAME-Anlage — sonst hat man kurz 1033-Errors.
Bedrock-Specifics
13. EU-CRIS-Profile-IDs sind Pflicht
eu.anthropic.claude-sonnet-4-6 (mit eu.-Prefix) statt anthropic.claude-sonnet-4-6. Nackte Foundation-Model-IDs ohne Region-Prefix werfen API-Errors.
In LiteLLM-Config: model: bedrock/eu.anthropic.claude-...
14. Bedrock-Model-Access pro Account aktivieren
Bedrock-Modelle sind nicht pauschal verfuegbar, jedes muss in der Bedrock-Console → Model Access explicit angehakt werden. Self-Service-Approval fuer Anthropic-Models, sofort aktiv.
VF-Stack: Sonnet 4.6 + Haiku 4.5 sind aktiv, Opus 4.7 NICHT — Marvin muss noch klicken.
15. Bedrock-EU hat KEINE Image-Generation-Models
Nur Embedding-Image-Models in Frankfurt. Nova Canvas, Stable Diffusion etc. sind us-only. Fuer DSGVO-Kunden mit Image-Gen-Wunsch: ueber Replicate-MCP, nicht Bedrock — siehe bedrock-eu-image-gen-limitation.
16. Prompt-Caching via LiteLLM
Bedrock-Claude unterstuetzt Prompt-Caching. LiteLLM-Config: supports_prompt_caching: true pro Modell + cache_control_injection_points in litellm_settings. Cached Input ist 90% billiger als regular Input. Greift erst ab ~1024 Tokens System-Prefix.
17. Bedrock-Cold-Start nach Stack-Restart
Erster Bedrock-Call nach Container-Restart kann 15-20s dauern (Connection-Pool-Aufbau). Folge-Calls sub-2s. Kein Bug — Normal.
Open WebUI Best Practices
18. Custom-Model statt nackter LiteLLM-Modell-Name
Open WebUI’s Custom-Models kann man mit:
- System-Prompt
- Pre-attached Tool-IDs (
meta.toolIds) - Description (sichtbar im Dropdown)
- Profile-Image
Statt claude-sonnet-4-6 direkt anzubieten, bauen wir vf-sonnet als Custom-Model mit allem drin. Default-Model im Stack auf vf-sonnet. User sieht „Sonnet 4.6 (VF Standard)” im Dropdown.
19. Task-Models vs Chat-Models
Open WebUI braucht ein „Task-Model” fuer interne Tasks (Chat-Title-Generation, Tag-Extraction, Search-Query-Optimization). Default nutzt das selbe wie Chat → teuer.
TASK_MODEL=claude-haiku-4-5 macht Sinn — Haiku kostet 3.3× weniger als Sonnet, fuer interne Tasks reicht’s.
20. Tool-Schemas sind der groesste Bedrock-Cost-Treiber
114 Tools × 150-300 Tokens je Tool = 17-34k Tokens NUR FUER TOOL-SCHEMAS, bei jedem Request. Mit Prompt-Caching auf 90% reduzierbar.
Plus: User kann pro Chat Tools deselektieren — bei einem „nur-Papierkram”-Chat sind die TicketPAY + M365 Tools nicht noetig.
Sandbox + Permissions
21. Inline-Embedded-API-Tokens werden geblockt
Anthropic-Sandbox blockt Shell-Calls mit API-Tokens die aus dem User-Message kommen. Loesung: User schreibt Token in AWS Secrets Manager via einen einzelnen aws secretsmanager create-secret-Call, Agent liest dann inline mit aws secretsmanager get-secret-value | curl ....
22. Destruktive Operations brauchen explizites OK
aws cloudformation delete-stack, aws secretsmanager delete-secret --force-delete-without-recovery, ecs stop-task etc. werden vom Sandbox haeufig geblockt mit „needs explicit user confirmation”. Antwort: vor jedem destruktiven Step Marvin’s „los” abwarten.
Pricing + DSGVO
23. VF-Self-Cost-Konditionen (Marvin’s Entscheidung 2026-05-12)
Vibe Factory bekommt Hosting zum Selbstkostenpreis (~65 €/Mo nach RDS-Migration) plus Bedrock 1:1 Pass-Through. Plus Sunset-Clause ist Pflicht: „diese Pilot-Konditionen gelten bis 2026-08-31, danach review”.
Anti-Pattern: Self-Cost-Setup mit unbegrenzter Bedrock-Inclusion → Cost-Risk fuer dich bei VF-Token-Spike.
24. DSGVO-konform durch Region-Lock in LiteLLM-Config
DSGVO-Compliance durchsetzen ueber LiteLLM-Whitelist: nur Bedrock-EU-CRIS-Profile in model_list. User koennen nichts anderes auswaehlen. Plus model_info.region als Display-Feld → User sieht „EU (Frankfurt)” im Dropdown neben Modell-Name.
25. Forward-User-Info-Headers fuer Per-User-MCP-Audit
ENABLE_FORWARD_USER_INFO_HEADERS=true schickt X-OpenWebUI-User-Email etc. an MCP-Server. mcp-vf-hosted nutzt das fuer Per-User-Audit-Trail (statt nur JWT-Subject-Hash).