open-webui-ultimate-stack
Health Warn
- License — License: MIT
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Low visibility — Only 7 GitHub stars
Code Pass
- Code scan — Scanned 12 files during light audit, no dangerous patterns found
Permissions Pass
- Permissions — No dangerous permissions requested
No AI report is available for this listing yet.
Production-grade Open WebUI deployment with RAG, private web search, OCR, local TTS, and MCP tool servers. Supports both standalone Docker Compose and Docker Swarm.
open-webui-ultimate-stack
Open WebUI deployment with RAG, private web search, OCR, local TTS, and MCP tool servers.
Includes a curated library of tools, filters, and function pipes, pushed automatically on every deploy via the internal API.
Provides standalone docker-compose.yml and a production-ready Docker Swarm docker-stack-compose.yml.
Quick Start
For single-host / Docker Compose deployments:
git clone https://github.com/BitWise-0x/open-webui-ultimate-stack && cd open-webui-ultimate-stack && ./bootstrap.sh
bootstrap.sh copies env examples, generates secrets, validates your configuration, and starts the stack. Open WebUI will be available at http://localhost:3000.
For additional deployment details, including Docker Swarm, see the Deployment section below.
Architecture
graph TD
User["👤 User / Browser"]
subgraph Core
owui["<b>openwebui</b><br>ghcr.io/open-webui/open-webui:0.12.3<br>:8080 → :3000"]
db["<b>db</b><br>pgvector/pgvector:0.8.7-pg17<br>:5432"]
redis["<b>redis</b><br>valkey/valkey:9.1-alpine<br>:6379"]
end
subgraph Search & Documents
searxng["<b>searxng</b><br>searxng/searxng:2026.10.16<br>:8080 → :8888"]
tika["<b>tika</b><br>apache/tika:4.1.0-1-full<br>:9998"]
end
subgraph AI Integrations
edgetts["<b>edgetts</b><br>openai-edge-tts<br>:5050"]
mcpo["<b>mcposerver</b><br>ghcr.io/open-webui/mcpo:git-788ff92<br>runs postgres-mcp 0.3.0<br>:8000"]
jupyter["<b>jupyter</b><br>quay.io/jupyter/scipy-notebook<br>:8888 (isolated network)"]
end
subgraph Automation
tools["<b>tools-init</b><br>python:3.12-slim<br>one-shot"]
end
User -->|":3000"| owui
owui --> db
owui --> redis
owui --> searxng
owui --> tika
owui --> edgetts
owui --> mcpo
owui -->|"code interpreter"| jupyter
searxng --> redis
mcpo -->|"postgres-mcp, read-only"| db
tools -.->|"API push on deploy"| owui
Services
Core
|
Search & Documents
|
AI Integrations
|
Automation
|
Tools & Extensions
FiltersPipeline filters that run on every message to pre- or post-process input and output.
|
ToolsNative tool-use extensions the model can call during a conversation.
|
Function PipesFull pipeline functions that replace or augment the model's response loop.
|
ComfyUI Workflows (
|
Repository Structure
open-webui-ultimate-stack/
├── docker-compose.yml Standalone: local / single-host
├── docker-stack-compose.yml Docker Swarm: production
├── .env.example Top-level variables (STACK_NAME, DATA_ROOT, OWUI_TAG, TIKA_TAG, etc.)
├── .gitignore
├── bootstrap.sh Setup, secrets generation, validation, and deployment
├── scripts/
│ ├── deploy-swarm.sh Swarm deploy: network, volumes, conf sync, deploy
│ ├── remove-swarm.sh Swarm teardown (preserves data volumes)
│ └── install-tools.sh Auto-push tools/filters/pipes via REST API
├── conf/
│ ├── wait-for-services.sh TCP dependency gate for Swarm services
│ ├── searxng/ settings.yml (overrides on upstream defaults), limiter.toml
│ ├── tika/ tika-config.json (Tika 4: parsers, Tesseract OCR, memory)
│ ├── mcposerver/ config.json.example (template; config.json gitignored), uv-overrides.txt
│ ├── postgres/init/ Custom entrypoint: pgvector init + auto-upgrade
│ └── tools/
│ ├── filters/ Python pipeline filters (auto-deployed)
│ ├── tools/ Python tool definitions (auto-deployed)
│ ├── functions/ Python pipes and functions (auto-deployed)
│ └── extras/ ComfyUI API workflows and sample data
├── docs/
│ ├── post-config.md Post-deployment manual configuration guide
│ └── passwordreset.md Emergency password reset runbook
├── env/ Per-service env.example files
│ ├── owui.env.example
│ ├── db.env.example
│ ├── edgetts.env.example
│ ├── mcp.env.example
│ ├── searxng.env.example
│ ├── jupyter.env.example
│ └── tools-init.env.example
└── README.md
Configuration
Environment Files
| File | Purpose |
|---|---|
.env |
Top-level: STACK_NAME, DATA_ROOT, ROUTER_NAME, ROOT_DOMAIN, BACKEND_NETWORK_NAME, JUPYTER_NETWORK_NAME, OWUI_TAG, TIKA_TAG, REDIS_DATA_ROOT |
env/owui.env |
Open WebUI: model connections and keys, RAG, websocket, TTS, image gen, code interpreter, permissions, agentic features |
env/db.env |
PostgreSQL credentials (POSTGRES_DB, POSTGRES_USER, POSTGRES_PASSWORD) |
env/searxng.env |
SearXNG secret, base URL, Granian server settings |
env/jupyter.env |
JUPYTER_TOKEN for the code-interpreter kernel |
env/edgetts.env |
Default voice, speed, format |
env/mcp.env |
DATABASE_URL for mcpo proxy |
env/tools-init.env |
Admin credentials used by tools-init to authenticate and push tools on every deploy |
All passwords and tokens default to change_me and are auto-generated by bootstrap.sh on first run. The postgres password is synced across env/db.env, env/owui.env, env/mcp.env, and conf/mcposerver/config.json, and the Jupyter token from env/jupyter.env into env/owui.env, automatically.
Service Configuration
| Directory | Purpose |
|---|---|
conf/searxng/ |
SearXNG settings (overrides merged onto the image's defaults) and rate limiter config |
conf/tika/ |
Tika 4 config: PDF parsing, Tesseract OCR languages and timeouts, forked-JVM memory |
conf/mcposerver/ |
MCP-to-OpenAPI proxy config: config.json.example is the template; config.json is generated on first run and gitignored; uv-overrides.txt holds the dependency overrides uvx applies to the MCP servers |
conf/postgres/init/ |
Custom PostgreSQL entrypoint that auto-creates and upgrades the pgvector extension on every container start |
Scripts
bootstrap.sh
Single entry point for both standalone and Swarm deployments. Handles the full setup lifecycle:
- Copies
env/*.env.examplefiles toenv/*.env(skips existing) - Stops if
.envpins Tika 3 (TIKA_TAG=3.x), which cannot read the Tika 4 config - Generates cryptographic secrets for
WEBUI_SECRET_KEY,SEARXNG_SECRET,JUPYTER_TOKEN, andPOSTGRES_PASSWORD - Syncs the Jupyter token into
env/owui.env(adding the line if an olderowui.envlacks it) - Brings an older
conf/mcposerver/config.jsonup to date: replaces apostgres-mcp-serverconfig withpostgres-mcp, and adds the uv overrides file to apostgres-mcpconfig that lacks it (edited in place withjqorpython3, so other MCP servers are kept) - Syncs the postgres password into all files that reference it (
owui.env,mcp.env,mcposerver/config.json) - Validates required configuration (admin email/password, Swarm-specific vars)
- Syncs admin credentials from
env/owui.envintoenv/tools-init.env - Starts the stack (
docker compose up -dfor standalone, or callsdeploy-swarm.shfor Swarm)
./bootstrap.sh # Standalone (Docker Compose)
./bootstrap.sh --swarm # Docker Swarm
Safe to re-run — skips existing env files and only regenerates secrets that are still set to change_me.
scripts/deploy-swarm.sh
Called by bootstrap.sh --swarm. Handles Swarm-specific infrastructure setup:
- Validates
DATA_ROOTis mounted and reachable, and thatTIKA_TAGis a 4.x tag - Creates service data directories on the shared filesystem with correct ownership
- Generates
POSTGRES_PASSWORDif still set tochange_me(with volume-exists safety check) - Generates
SEARXNG_SECRET,WEBUI_SECRET_KEYandJUPYTER_TOKENif needed, and syncs the Jupyter token intoenv/owui.env - Creates the backend overlay network using the CIDR from
FORWARDED_ALLOW_IPS, and the privatejupyteroverlay - Creates external volumes (
postgresdata,searxngcache) - Syncs
conf/directories toDATA_ROOTvia rsync (tools, postgres init, searxng, tika, mcposerver), removing Tika 3 and uWSGI leftovers from earlier versions - Brings the deployed
mcposerver/config.jsonup to date (replaces apostgres-mcp-serverconfig, adds the uv overrides file in place) and injects the postgres password using Python (handles special characters) - Sets directory ownership (
999:999for postgres/redis,977:977for searxng,1000:1000for jupyter) - If
OWUI_TAGdiffers from the running image, scalesopenwebuito 0 so migrations run with no old replica attached - Deploys the stack with
docker stack deploy
scripts/install-tools.sh
Runs inside the tools-init container on every deploy. Authenticates with Open WebUI via the REST API and pushes all Python files from conf/tools/ (filters, tools, and function pipes) with upsert support — creates new items or updates existing ones.
scripts/remove-swarm.sh
Removes the Swarm stack while preserving external volumes and the overlay network. Prints instructions for manual cleanup if needed.
conf/wait-for-services.sh
POSIX-compatible TCP dependency gate for Docker Swarm. Since Swarm does not support depends_on, this script blocks service startup until all specified host:port pairs are reachable via TCP, then execs into the real entrypoint.
Used by:
- searxng — waits for
redis:6379 - mcposerver — waits for
db:5432 - tools-init — waits for
openwebui:8080
Auto-detects the TCP check method: python3 or python first, then nc only if it supports -z (the SearXNG image ships a BusyBox nc without it). Configurable via WAIT_TIMEOUT (default: 120s) and WAIT_INTERVAL (default: 2s). The tools-init service overrides WAIT_TIMEOUT=300 because Open WebUI's first boot (DB migrations + function module loading + frontmatter pip installs) can run several minutes before port 8080 is reachable.
conf/postgres/init/entrypoint.sh
Custom PostgreSQL entrypoint that wraps the official docker-entrypoint.sh:
- Removes stale
postmaster.pid(safe for Swarm rescheduling after crash) - Starts the official entrypoint in the background
- Waits for PostgreSQL to accept connections (up to 300s)
- Creates the pgvector (
vector) extension if it doesn't exist - Upgrades the extension to match the installed shared library version
- Forwards
SIGTERM/SIGINT/SIGQUITto the postgres process
Deployment
Standalone (local / single host)
Uses docker-compose.yml with local volumes, depends_on health checks, and ports exposed to the host.
Set these before running:
| File | Variable | Description |
|---|---|---|
env/owui.env |
WEBUI_ADMIN_EMAIL |
Admin account email |
env/owui.env |
WEBUI_ADMIN_PASSWORD |
Admin password (uppercase, lowercase, digit, special char, 8+ chars) |
env/owui.env |
OLLAMA_BASE_URL |
Optional — your Ollama instance URL |
env/owui.env |
OPENAI_API_KEYS |
Optional: <openai>;<openrouter>;<anthropic> keys, same order as OPENAI_API_BASE_URLS (disable unused ones in OPENAI_API_CONFIGS) |
Note:
env/tools-init.envmust have matchingOWUI_ADMIN_EMAILandOWUI_ADMIN_PASSWORD—bootstrap.shsyncs them automatically fromenv/owui.envwhenever the values differ.
Then run:
./bootstrap.sh
Open WebUI will be available at http://localhost:3000. SearXNG is exposed on http://localhost:8888 for optional direct access.
Docker Swarm
Uses docker-stack-compose.yml with external overlay network, external named volumes, bind mounts from a shared filesystem (DATA_ROOT), and wait-for-services.sh as a TCP dependency gate (Swarm does not support depends_on).
Set these before running:
| File | Variable | Description |
|---|---|---|
.env |
STACK_NAME |
Stack name (default: open-webui) |
.env |
DATA_ROOT |
Shared filesystem path accessible from all Swarm nodes (GlusterFS, NFS, etc.) |
.env |
ROUTER_NAME |
Subdomain for CORS and Traefik labels (e.g. openwebui) |
.env |
ROOT_DOMAIN |
Base domain for CORS and Traefik labels (e.g. yourdomain.com) |
.env |
BACKEND_NETWORK_NAME |
Overlay network name (default: open-webui_backend) |
.env |
JUPYTER_NETWORK_NAME |
Private overlay for the jupyter kernel (default: open-webui_jupyter) |
.env |
OWUI_TAG |
Open WebUI image tag (default: 0.12.3); see Upgrading |
.env |
TIKA_TAG |
Apache Tika image tag, must be 4.x (default: 4.1.0-1) |
.env |
REDIS_DATA_ROOT |
Optional — separate high-IOPS mount for Redis data (defaults to DATA_ROOT) |
env/owui.env |
WEBUI_ADMIN_EMAIL |
Admin account email |
env/owui.env |
WEBUI_ADMIN_PASSWORD |
Admin password (uppercase, lowercase, digit, special char, 8+ chars) |
env/owui.env |
OLLAMA_BASE_URL |
Optional — your Ollama instance URL |
env/owui.env |
OPENAI_API_KEYS |
Optional: <openai>;<openrouter>;<anthropic> keys, same order as OPENAI_API_BASE_URLS |
env/owui.env |
FORWARDED_ALLOW_IPS |
Overlay subnet CIDR — deploy-swarm.sh uses this to create the network (e.g. 10.0.13.0/24) |
env/searxng.env |
SEARXNG_BASE_URL |
Set to http://searxng:8080/ for Swarm (standalone default http://localhost:8888/ won't work) |
Note:
WEBUI_ADMIN_EMAILandWEBUI_ADMIN_PASSWORDmust match in bothenv/owui.envandenv/tools-init.env.bootstrap.sh --swarmsyncs them automatically whenever the values differ.
Then run:
./bootstrap.sh --swarm
Safe to re-run on redeploy or update — re-syncs conf/ to DATA_ROOT and redeploys the stack without touching existing secrets or data volumes.
What deploy-swarm.sh does
Local repo Shared filesystem (DATA_ROOT)
───────────── ─────────────────────────────
conf/tools/ ──rsync──► open-webui/tools/
conf/postgres/init/ ──rsync──► open-webui/postgres/init/
conf/searxng/ ──rsync──► open-webui/searxng/conf/
conf/tika/ ──rsync──► open-webui/tika/conf/
conf/mcposerver/ ──rsync──► open-webui/mcposerver/conf/
conf/wait-for-services.sh ──cp──► open-webui/scripts/wait-for-services.sh
scripts/install-tools.sh ──cp──► open-webui/tools/install-tools.sh
The deploy script also creates the overlay networks (backend from the FORWARDED_ALLOW_IPS CIDR, plus the private jupyter overlay), external volumes, the jupyter work directory, sets directory ownership, injects the postgres password into mcposerver/config.json, and runs docker stack deploy.
Monitoring
docker stack ps ${STACK_NAME:-open-webui}
docker service logs -f ${STACK_NAME:-open-webui}_openwebui
Teardown
Remove stack (preserves data volumes by default):
./scripts/remove-swarm.sh
To also remove data volumes after removal (destroys all data):
docker volume rm ${STACK_NAME:-open-webui}_postgresdata ${STACK_NAME:-open-webui}_searxngcache
docker network rm ${BACKEND_NETWORK_NAME:-open-webui_backend} ${JUPYTER_NETWORK_NAME:-open-webui_jupyter}
Standalone vs Swarm Differences
| Feature | Standalone (docker-compose.yml) |
Swarm (docker-stack-compose.yml) |
|---|---|---|
| Orchestration | Docker Compose | Docker Swarm |
| Service dependencies | depends_on with health checks |
wait-for-services.sh TCP gate |
| Volumes | Local named volumes | Bind mounts from DATA_ROOT + external named volumes |
| Networking | Bridge networks (backend, plus a private jupyter network) |
Overlay networks (backend with configurable subnet, plus a private jupyter overlay) |
| Exposed ports | 3000 (WebUI), 8888 (SearXNG) |
None — use a reverse proxy (Traefik labels included, commented) |
| Replicas | 1 per service | 2 for openwebui, 1 for all others |
| Restart policy | unless-stopped |
any (also restarts after a clean exit such as a node drain); on-failure for the one-shot tools-init |
| Config files | Mounted directly from ./conf/ |
Synced via rsync to shared filesystem |
| CORS | Not configured | CORS_ALLOW_ORIGIN set from ROUTER_NAME.ROOT_DOMAIN |
Post-Deployment Configuration
Once the stack is running, some settings require manual configuration via the Admin Panel. See the Post-Configuration Guide for:
- MCP connections (GitHub, gitmcp.io) via native Streamable HTTP
- Native function calling and the Legacy opt-out
- Anthropic (Claude) connection, and Open WebUI's own Anthropic-compatible API
- Code interpreter (Jupyter) and its security model
- Environment variables and API keys for third-party services
- Filter activation and Valve configuration
- ComfyUI workflow imports and model setup
- Function pipe and tool Valve tuning
Upgrading
Images are pinned, so nothing changes until you change it. Open WebUI releases usually carry database migrations:
- Back up Postgres (commands in the guide).
- Set
OWUI_TAGin.env(standalone: create.envnext todocker-compose.ymlwith just that line). - Re-run
./bootstrap.shor./bootstrap.sh --swarm. On Swarm,deploy-swarm.shscalesopenwebuito 0 before the new image starts, because upstream does not support rolling updates across migrations.
Coming from a pre-0.12 version of this stack (Open WebUI :main, Tika 3, SearXNG 2025.7): pull, re-run bootstrap.sh, then follow the one-time checklist in Upgrading from a pre-0.12 version. ENABLE_PERSISTENT_CONFIG=true keeps your existing settings in the database, so a few of them (most importantly the Tika server version) have to be changed once in the Admin UI, or document uploads fail.
Credits
The tools, filters, and function pipes bundled in conf/tools/ were authored primarily by
Haervwe from the
open-webui-tools project.
Additional contributions by:
tan-yong-sheng, pupphelper, Zed Unknown, and justinrahb.
All tools retain their original author metadata in their docstring headers.
Useful Resources
Read the full write-up: The Open WebUI Ultimate Stack: A Production Deployment for the LLM Interface Era — covers architecture, deployment, and the full suite of bundled tools, filters, and function pipes.
License
MIT License: see LICENSE for details.
Reviews (0)
Sign in to leave a review.
Leave a reviewNo results found