Files
hermes-skills/skills/devops/open-webui/SKILL.md
T

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.