239 lines
9.3 KiB
Markdown
239 lines
9.3 KiB
Markdown
---
|
|
name: open-webui
|
|
description: Deploy, configure, and upgrade Open WebUI on app1 — vision support, image generation, RAG, model management, and admin-ai backend integration.
|
|
version: 1.0.0
|
|
tags: [open-webui, ai, chat, vision, rag, app1, admin-ai, docker]
|
|
---
|
|
|
|
# Open WebUI
|
|
|
|
Self-hosted AI chat interface at `http://ai.itpropartner.com` running on app1 (152.53.36.131).
|
|
|
|
## Architecture
|
|
|
|
```text
|
|
User → Caddy (ai.itpropartner.com) → localhost:3000 → Open WebUI Docker
|
|
↓
|
|
admin-ai.itpropartner.com/v1 (LiteLLM)
|
|
↓
|
|
100+ models across providers
|
|
```
|
|
|
|
## Deployment
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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. `litellm` hostname does NOT resolve from app1's Docker network. Use `https://admin-ai.itpropartner.com/v1` instead.
|
|
- **Wrong/missing API key** — The key stored in `openai.api_keys` must be a valid LiteLLM key with access to `GET /v1/models`.
|
|
|
|
### Fix
|
|
|
|
```python
|
|
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:
|
|
|
|
```python
|
|
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)
|
|
|
|
```python
|
|
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_key`
|
|
- `web.search.google_pse_engine_id`
|
|
|
|
### Switching search engines
|
|
|
|
- `"searxng"` — uses `web.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
|
|
|
|
```python
|
|
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
|
|
|
|
```bash
|
|
cd /docker/openwebui && docker compose down && docker compose up -d
|
|
# or for quick restart:
|
|
docker restart openwebui
|
|
```
|
|
|
|
## Upgrades
|
|
|
|
```bash
|
|
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_METADATA` are ignored. Always update the SQLite DB directly for running instances. Set both env AND DB for fresh deploys.
|
|
- **Container name conflict:** `docker compose down` sometimes leaves the container name reserved. Use `docker rm -f openwebui` before `docker compose up`.
|
|
- **No sqlite3 in container:** Use Python `sqlite3` module 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/v1` won't resolve:** LiteLLM runs on core (netcup), not locally on app1. The `litellm` hostname doesn't resolve from app1's Docker network. Always use `https://admin-ai.itpropartner.com/v1` as the base URL. This is the most common cause of "no models showing up."
|
|
- **UI overrides env vars in DB:** `openai.api_base_urls` and `openai.api_keys` set 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.
|