openwebui/skills/openwebui-layer/SKILL.md
Open WebUI with auto-configured LLM providers, MCP servers, and Jupyter code execution. MUST be invoked before any work involving: the openwebui candy, Open WebUI configuration, LLM provider auto-detection, or MCP server discovery for Open WebUI.
npx skillsauth add overthinkos/overthink-plugins openwebui-layerInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
| Property | Value |
|----------|-------|
| Dependencies | python, supervisord |
| Volumes | data -> /opt/data |
| Ports | 8080 |
| Aliases | open-webui -> open-webui |
| Services | openwebui (supervisord, autostart) |
| Install files | pixi.toml, task:, openwebui-entrypoint |
| Variable | Value |
|----------|-------|
| DATA_DIR | /opt/data |
| PORT | 8080 |
| DOCKER | true |
| ENABLE_DIRECT_CONNECTIONS | true |
| ENABLE_CODE_EXECUTION | true |
| ENABLE_PERSISTENT_CONFIG | false |
| Variable | Description |
|----------|-------------|
| OPENROUTER_API_KEY | API key for OpenRouter (maps to OPENAI_API_KEY with OpenRouter base URL) |
| OLLAMA_API_KEY | API key for Ollama Cloud inference |
| OLLAMA_HOST | Local Ollama server URL (auto-injected by ollama candy env_provide) |
| OPENAI_API_KEY | Direct OpenAI API key |
| OPENAI_API_BASE_URL | OpenAI-compatible API base URL |
| WEBUI_AUTH | Enable authentication (default: true) |
| WEBUI_ADMIN_EMAIL | Admin account email for first-start setup |
| CHARLY_MCP_SERVERS | JSON array of MCP servers (auto-injected by mcp_provide candies) |
| Name | Description |
|------|-------------|
| jupyter | JupyterLab CRDT MCP server for notebook manipulation |
| chrome-devtools | Chrome DevTools MCP server for browser automation |
secret: field)Auto-generated, stored in credential store (keyring/config-file fallback):
| Secret | Env Fallback | Purpose | Auto-gen path |
|--------|-------------|---------|---------------|
| webui-secret-key | WEBUI_SECRET_KEY | JWT + encryption key (CRITICAL: losing it breaks all sessions and OAuth tokens) | charly config time, ProvisionPodmanSecrets |
| admin-password | WEBUI_ADMIN_PASSWORD | Admin account password — declared as secret_require: | charly bundle add time, ensureCandySecret |
Provisioned as Secret=charly-openwebui-<name>,type=env,target=<ENV> in the quadlet. The entrypoint checks env vars first (from type=env injection), then file mounts at /run/secrets/ as fallback.
First-run admin login: WEBUI_ADMIN_PASSWORD auto-generates as a 32-byte hex random value if not pre-set. To retrieve the auto-generated password and log in for the first time:
charly secrets get charly/secret WEBUI_ADMIN_PASSWORD
Override with a specific password before the first deploy:
charly secrets set charly/secret WEBUI_ADMIN_PASSWORD <password>
charly config openwebui # picks up the override
.secrets file)User-provided API keys stored via charly secrets gpg:
charly secrets gpg set OPENROUTER_API_KEY sk-or-xxx
charly config openwebui --env-file .secrets # Decrypts + injects at config time
The openwebui-entrypoint runs on EVERY start (no sentinel — ENABLE_PERSISTENT_CONFIG=false means env vars always override database config):
type=env) or /run/secrets/ file mountsOLLAMA_HOST -> OLLAMA_BASE_URL (Ollama server)OPENROUTER_API_KEY -> OPENAI_API_KEY + OPENAI_API_BASE_URL=https://openrouter.ai/api/v1OLLAMA_API_KEY -> OPENAI_API_KEY + OPENAI_API_BASE_URL=https://api.ollama.com/v1CHARLY_MCP_SERVERS JSON -> builds TOOL_SERVER_CONNECTIONS JSON for Open WebUICODE_EXECUTION_ENGINE=jupyteropen-webui serveThe entrypoint translates charly's CHARLY_MCP_SERVERS format into Open WebUI's expected TOOL_SERVER_CONNECTIONS JSON:
[{
"type": "mcp",
"url": "http://charly-jupyter:8888/mcp",
"spec_type": "url", "spec": "", "path": "",
"auth_type": "", "key": "",
"config": {"enable": true},
"info": {"id": "", "name": "jupyter", "description": "MCP: jupyter"}
}]
Key fields: type must be "mcp" (not "openapi"), config.enable must be true.
ENABLE_PERSISTENT_CONFIG=falseThis is the critical architectural decision. Without it, Open WebUI's database config overrides environment variables after the first admin-panel save. With it disabled, env vars ALWAYS win — so the entrypoint's dynamic configuration (LLM providers, MCP servers, Jupyter) works reliably on every restart. No sentinel-guarded config patching needed (unlike hermes).
port_relay NeededOpen WebUI binds to 0.0.0.0:8080 by default. The port_relay field is only for services that bind to 127.0.0.1 (like Chrome DevTools on port 9222). Using port_relay with Open WebUI causes a socat/Open WebUI port conflict on eth0.
[pypi-dependencies] (NOT [feature.default.pypi-dependencies] — the default feature is reserved in pixi)pip install open-webui in the pixi environment (~500MB+ of dependencies)autorestart=true handles transient failures.# charly.yml
openwebui:
base: fedora
candy:
- agent-forwarding
- openwebui
- dbus
- charly
ports:
- "8080:8080"
/charly-languages:python -- Python runtime dependency/charly-infrastructure:supervisord -- process manager dependency/charly-hermes:hermes -- alternative AI agent with similar MCP/LLM auto-config pattern/charly-core:charly-config -- charly config openwebui --update-all for service discovery/charly-build:secrets -- charly secrets for Secret Service / GPG credential management/charly-core:service -- charly service status openwebui for runtime management/charly-build:charly-mcp-cmd -- probe the MCP servers openwebui consumes (auto-configured into TOOL_SERVER_CONNECTIONS from CHARLY_MCP_SERVERS): charly check live <provider-image> --filter mcp shows what tools openwebui will see and verifies liveness before debugging openwebui itself./charly-openwebui:openwebui -- the deployed box/charly-jupyter:jupyter -- deploy alongside for MCP notebook access and code execution/charly-ollama:ollama -- deploy alongside for local LLM inference/charly-hermes:hermes -- alternative AI frontend (CLI-based agent vs web UI)MUST be invoked when the task involves the openwebui candy, Open WebUI configuration, LLM provider auto-detection, MCP server discovery for Open WebUI, or the openwebui entrypoint. Invoke this skill BEFORE reading source code or launching Explore agents.
/charly-image:layer — candy authoring reference (charly.yml schema, task verbs, service declarations)/charly-check:check — declarative testing (check: block, charly check box, charly check live)tools
Use when authoring or modifying a charly PLUGIN — a candy with a `plugin:` block that contributes Providers (verbs/kinds/deploy-targets/steps/builders/commands), its own CUE schema, builtin (compiled-in) or external (out-of-tree git repo). Covers the unified Provider model, the per-plugin CUE-schema contract (single source → Go params for dev + schema-over-Describe RPC for runtime), the SDK, and the loader.
tools
The CUE data-validation / configuration CLI (cue), pinned to v0.16.1. Use when working with the cue candy, installing the cue binary into a box or onto a target:local dev host, or running the offline schema-vendoring pipeline that feeds charly's egress validation.
tools
CUE EGRESS validation — validating (and, where it adds value, generating) the config files charly WRITES to a system BEFORE the bytes hit disk. MUST be invoked before working on charly/egress.go, the vendored schemas under candy/plugin-egress/egress-schemas/vendor/, the ValidateEgress / registerVendoredEgressKind path, the offline `task cue:vendor` pipeline, or adding an egress schema for any written artifact (cloud-init, k8s manifests, traefik routes, runtime config, install ledger, systemd/quadlet units, ssh_config, libvirt XML).
tools
Kubernetes cluster-probe declarative check verb — the `kube:` check verb (nodes, pods, ingress, storage class, addon health, apply/delete, and arbitrary resource GETs) served out-of-process by the candy/plugin-kube plugin (vendored client-go; no external kubectl required).