Files

109 lines
4.0 KiB
Markdown

# Open WebUI Configuration via SQLite
Open WebUI v0.10+ stores persistent config as JSON key/value pairs in its SQLite database at `/app/backend/data/webui.db` (Docker volume: `/var/lib/docker/volumes/openwebui_data/_data/webui.db`).
After the first launch, Docker `ConfigVar` environment variables are **ignored** — the DB is the single source of truth. All configuration changes after initial setup must be made directly in SQLite.
## Schema
```sql
CREATE TABLE config (
"key" TEXT NOT NULL,
value JSON NOT NULL,
updated_at BIGINT,
PRIMARY KEY ("key")
);
```
## Essential config keys
### Model capabilities (vision, image generation)
```sql
-- Enable vision for all models (required for image upload in chat)
UPDATE config SET value = '{"capabilities": {"vision": true}}', updated_at = <unix_ts>
WHERE key = 'models.default_metadata';
```
Without this, image upload is disabled in Open WebUI regardless of which vision-capable models are connected.
### Image generation
```sql
-- Enable image generation feature
UPDATE config SET value = 'true', updated_at = <unix_ts> WHERE key = 'image_generation.enable';
-- Engine/model is stored in separate keys
-- Engine: openai, automatic1111, comfyui, gemini
UPDATE config SET value = '"openai"', updated_at = <unix_ts> WHERE key = 'image_generation.engine';
UPDATE config SET value = '"gemini/imagen-4.0-generate-001"', updated_at = <unix_ts> WHERE key = 'image_generation.model';
```
### Web search
```sql
-- Enable web search
UPDATE config SET value = 'true', updated_at = <unix_ts> WHERE key = 'web.search.enable';
-- Set engine: searxng, google_pse, brave, serpapi, etc.
UPDATE config SET value = '"google_pse"', updated_at = <unix_ts> WHERE key = 'web.search.engine';
```
Public SearXNG instances (searx.be, search.sapti.me, etc.) are heavily rate-limited (403/429). Google PSE is the reliable fallback but uses API quota. Self-hosted SearXNG is ideal.
### MCP tool server connections
```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 []
# Remove duplicates by port
current = [c for c in current if '<port>' not in c.get('url', '')]
current.append({
'url': 'http://host.docker.internal:<PORT>/mcp',
'type': 'mcp', # CRITICAL: not 'openapi'
'auth_type': 'none',
'key': '',
'headers': None,
'config': {
'enable': True,
'function_name_filter_list': '',
'access_grants': [{
'principal_type': 'group',
'principal_id': '<group-id>', # from DB: SELECT value FROM config WHERE key='ui.default_group_id'
'permission': 'read'
}]
},
'info': {'id': '', 'name': 'Server Name', 'description': 'What it does'}
})
db.execute("UPDATE config SET value = ?, updated_at = ? WHERE key = ?",
(json.dumps(current), int(time.time()), 'tool_server.connections'))
db.commit()
db.close()
# Then: docker restart openwebui
```
### User features/permissions
```sql
-- Check image_generation and other feature flags
SELECT value FROM config WHERE key = 'user.permissions';
-- Look for JSON path: $.features.image_generation
```
## Change workflow
1. Update the DB: `python3 -c "..."` (sqlite3 write)
2. Verify: `SELECT value FROM config WHERE key = '...'`
3. Restart: `docker restart openwebui`
4. Wait 10-15 seconds for health check
## Pitfalls
- **ConfigVar env vars are dead on restart** — After first launch, `DEFAULT_MODEL_METADATA` and other ConfigVar env vars in docker-compose are silently ignored. The DB wins.
- **Quoting in shell** — When running Python SQLite updates through SSH, use single-quoted Python strings and double-quoted SQL identifiers to avoid escaping hell. Better: write a .py script, scp it, run it.
- **Group ID discovery** — The principal_id for access grants is found at `SELECT value FROM config WHERE key='ui.default_group_id'`. This changes per installation.