9.3 KiB
name, description, version, tags
| name | description | version | tags | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| open-webui | Deploy, configure, and upgrade Open WebUI on app1 — vision support, image generation, RAG, model management, and admin-ai backend integration. | 1.0.0 |
|
Open WebUI
Self-hosted AI chat interface at http://ai.itpropartner.com running on app1 (152.53.36.131).
Architecture
User → Caddy (ai.itpropartner.com) → localhost:3000 → Open WebUI Docker
↓
admin-ai.itpropartner.com/v1 (LiteLLM)
↓
100+ models across providers
Deployment
# On app1: /docker/openwebui/docker-compose.yml
services:
openwebui:
image: ghcr.io/open-webui/open-webui:latest
container_name: openwebui
restart: unless-stopped
ports:
- "127.0.0.1:3000:8080"
environment:
- OPENAI_API_BASE_URL=https://admin-ai.itpropartner.com/v1
- OPENAI_API_KEY=<admin-ai-key>
- WEBUI_NAME=IT Pro Partner AI
volumes:
- openwebui_data:/app/backend/data
volumes:
openwebui_data:
external: true
Models
100+ models through admin-ai. Vision-capable: claude-sonnet-4-6, gemini-flash-latest, gemini-pro-latest.
Troubleshooting: No Models Showing Up
When OpenWebUI shows an empty model list, the API connection is failing. The DB values for openai.api_base_urls and openai.api_keys override docker-compose env vars after they've been set via the Admin UI.
Quick diagnostic
# Test connectivity from inside the container
docker exec openwebui curl -s <base_url>/v1/models -H 'Authorization: Bearer <key>' | head -c 200
# Check current DB config
sqlite3 /var/lib/docker/volumes/openwebui_data/_data/webui.db \
"SELECT key, substr(value, 1, 120) FROM config WHERE key IN ('openai.api_base_urls', 'openai.api_keys')"
Common misconfigurations
http://litellm:4000/v1— LiteLLM runs on core (netcup), not locally on app1.litellmhostname does NOT resolve from app1's Docker network. Usehttps://admin-ai.itpropartner.com/v1instead.- Wrong/missing API key — The key stored in
openai.api_keysmust be a valid LiteLLM key with access toGET /v1/models.
Fix
import sqlite3, json, time
db = sqlite3.connect('/var/lib/docker/volumes/openwebui_data/_data/webui.db')
# Fix base URL
db.execute("UPDATE config SET value = ?, updated_at = ? WHERE key = 'openai.api_base_urls'",
(json.dumps(['https://admin-ai.itpropartner.com/v1']), int(time.time())))
db.commit()
db.close()
Then restart: docker restart openwebui
Enabling Vision Support (CRITICAL)
Open WebUI uses ConfigVar environment variables — after first launch, values persist in the SQLite database and env var changes are ignored. Must update the DB directly:
import sqlite3, json, time
db = sqlite3.connect('/var/lib/docker/volumes/openwebui_data/_data/webui.db')
db.execute("""
UPDATE config
SET value = ?, updated_at = ?
WHERE key = 'models.default_metadata'
""", ('{"capabilities": {"vision": true}}', int(time.time())))
db.commit()
db.close()
Then restart: docker restart openwebui
Pitfall: Setting DEFAULT_MODEL_METADATA in docker-compose.yml only works on FIRST launch. Subsequent restarts use the DB value. Always update both — the compose file for fresh deploys AND the DB for live instances.
Web Search
Configured via DB config keys. Open WebUI supports multiple search backends — switch between them by updating web.search.engine and the corresponding credentials.
Current setup (Google PSE)
import sqlite3, time
db = sqlite3.connect('/var/lib/docker/volumes/openwebui_data/_data/webui.db')
db.execute("UPDATE config SET value = ?, updated_at = ? WHERE key = ?",
('true', int(time.time()), 'web.search.enable'))
db.execute("UPDATE config SET value = ?, updated_at = ? WHERE key = ?",
('"google_pse"', int(time.time()), 'web.search.engine'))
db.commit()
Google PSE keys are already in the DB:
web.search.google_pse_api_keyweb.search.google_pse_engine_id
Switching search engines
"searxng"— usesweb.search.searxng_query_url(public instances are rate-limited; deploy your own)"google_pse"— uses Google Programmable Search Engine (pre-configured, works reliably)- Other backends: brave, kagi, serpapi, tavily, etc. — each needs its own API key row
Enabling web search in chat
Users click the 🌐 toggle in the chat input to enable web search per-message. Results are injected as RAG context with inline citations.
MCP Connectivity
Open WebUI natively supports MCP Streamable HTTP connections. Add via Admin Settings → External Tools (UI) or directly in the SQLite DB.
Adding an MCP server via DB
import sqlite3, json, time
db = sqlite3.connect('/var/lib/docker/volumes/openwebui_data/_data/webui.db')
row = db.execute("SELECT value FROM config WHERE key='tool_server.connections'").fetchone()
current = json.loads(row[0]) if row else []
new_conn = {
'url': 'http://host.docker.internal:8899/mcp', # Use host.docker.internal for Docker→host
'type': 'mcp', # NOT 'openapi'
'auth_type': 'none', # 'none', 'bearer', or 'oauth_2.1'
'key': '',
'config': {
'enable': True,
'function_name_filter_list': '', # Leave empty to expose all tools
'access_grants': [{'principal_type': 'group', 'principal_id': '<group-id>', 'permission': 'read'}]
},
'info': {'name': 'My MCP Server', 'description': '...'}
}
current.append(new_conn)
db.execute("UPDATE config SET value = ?, updated_at = ? WHERE key = ?",
(json.dumps(current), int(time.time()), 'tool_server.connections'))
db.commit()
Then restart: docker restart openwebui
MCP vs OpenAPI connection types
- MCP (Streamable HTTP): Type
"mcp"— stateful, tool-rich, follows MCP protocol - OpenAPI: Type
"openapi"— stateless REST, follows OpenAPI spec
Pitfall: Using "openapi" as the type for an MCP server URL causes an infinite loading spinner and browser console error. Always use "mcp" for MCP servers.
Access Control
MCP servers are admin-only to add. Grant user access via access_grants — assign to a group so all users in that group get the tools.
Docker→host addressing
When Open WebUI runs in Docker and the MCP server is on the host, use http://host.docker.internal:<port>/mcp instead of localhost.
Configured via admin-ai → Gemini Imagen:
- Engine: openai (OpenAI-compatible API)
- Model:
gemini/imagen-4.0-generate-001 - Size: 2048x2048
Enabled in DB config: ('image_generation.enable', 'true')
Document Upload (RAG)
PDFs, files, and documents are processed through the built-in RAG pipeline:
- Embedding model:
sentence-transformers/all-MiniLM-L6-v2(downloaded from HuggingFace on first use) - Vector DB: ChromaDB (SQLite-backed, local)
- PDF extraction: page-based mode, PDF image extraction enabled
- Chunk size: 1000, overlap: 100
DB Config Reference
Database: /var/lib/docker/volumes/openwebui_data/_data/webui.db
Schema: config(key TEXT PRIMARY KEY, value JSON, updated_at BIGINT)
Key rows to know about:
| key | purpose |
|---|---|
models.default_metadata |
Vision, image_gen capabilities |
image_generation.enable |
Image gen toggle |
image_generation.model |
Active image gen model |
openai.api_base_urls |
Backend API URL |
openai.api_keys |
Backend API key |
user.permissions |
Feature flags per role |
Restart
cd /docker/openwebui && docker compose down && docker compose up -d
# or for quick restart:
docker restart openwebui
Upgrades
cd /docker/openwebui
docker compose pull
docker compose down && docker compose up -d
# Re-apply vision metadata (config may reset on major upgrades)
Pitfalls
- ConfigVar persistence: After first launch, env vars like
DEFAULT_MODEL_METADATAare ignored. Always update the SQLite DB directly for running instances. Set both env AND DB for fresh deploys. - Container name conflict:
docker compose downsometimes leaves the container name reserved. Usedocker rm -f openwebuibeforedocker compose up. - No sqlite3 in container: Use Python
sqlite3module on the host, pointing at the Docker volume path. - Model list refresh: Models from admin-ai are fetched at startup. If admin-ai models change, restart Open WebUI to refresh.
- MCP type mismatch: Using
"openapi"connection type for an MCP server crashes the frontend with an infinite loading spinner. Always use"mcp". - Web search engine switch: Google PSE is pre-configured and reliable. Public SearXNG instances are rate-limited — deploy your own if you need SearXNG.
http://litellm:4000/v1won't resolve: LiteLLM runs on core (netcup), not locally on app1. Thelitellmhostname doesn't resolve from app1's Docker network. Always usehttps://admin-ai.itpropartner.com/v1as the base URL. This is the most common cause of "no models showing up."- UI overrides env vars in DB:
openai.api_base_urlsandopenai.api_keysset via Admin UI persist in the SQLite DB and override docker-compose environment variables. When models disappear, check the DB values first, not the compose file.