2025-10-11 11:29:11 -04:00
2025-09-10 16:26:35 -04:00
2025-10-03 09:38:46 -04:00
2025-10-11 11:29:11 -04:00
2025-10-03 08:41:37 -04:00
2025-09-12 10:01:18 -04:00
2025-09-26 14:28:04 -04:00
2025-10-11 11:29:11 -04:00
2025-09-10 16:14:55 -04:00
2025-10-03 09:38:46 -04:00
2025-09-10 16:26:35 -04:00

ML Stack — Local AI Orchestration Toolkit

This repository packages a complete self-hosted assistant stack around Open WebUI plus several companion services: a scheduler that can trigger chats and workflows, a docker-backed code runner, a Roku remote tool server, Nextcloud file access, SearxNG metasearch, and a headless browser UI for deep-research sessions. Everything is wired together through docker-compose.yml so the stack can be brought up on a single host.

Last updated: 2025-10-03


A (Few) Notes

  1. ports are currently exposed on most services for development purposes (e.g. 12253 for the scheduler), remove these in production or consider adding a proxy

  2. ALL DATA IS STORED IN VOLUMES!!! This means if you do docker compose down -v your data WILL dissapear. Consider mounting a persistant directory to avoid this

  3. Before starting the cluster, check if you need the different components (e.g. Nextcloud Tool Server). They are set to restart on failiure and will throw if missing env vars/credentials, which will loop endlessly

  4. If you do not use cloudflared for tunneling, please adjust the CORS policies accordingly, and consider adding a reverse proxy to either your local machine or the compose

  5. The code runner and scheduler both mount the host Docker socket. Ensure the host user/group IDs match the compose configuration (DOCKER_GID build arg defaults to 977) so containers can operate without root. This will be replaced when I enentually migrate this to a kubernetes cluster

  6. When adjusting NEXTCLOUD_ACCESS_DIRS, remember to restart ollama-nextcloud so the regex list is reloaded


Stack At A Glance

Compose service Directory / build context External ports Primary role
open-webui (image: ghcr.io/open-webui/open-webui:main) 4000 -> 8080 Chat UI, agent orchestration, embedded knowledge base & RAG powered by Postgres
postgres Persistence for Open WebUI (users, KB, events)
searxng searxng.yml 4001 -> 8080 (debug only) Private SearxNG instance used for live web search tools
coderunner coderunner/ (internal 8787) Bun service that executes pure source code inside sandboxed Docker containers
openwebui_tools tools/ (internal 1331) Python Roku remote API exposed as an OpenAPI tool server
browser browser/ 7788 -> 7788 Playwright Chromium UI for autonomous browsing / research
schedules-api scheduler/ 12253 -> 12253 Cron-style job scheduler that can open chats, call templates, and upload files
ollama-nextcloud nextcloud/ 13284 -> 1111 Nextcloud WebDAV proxy with caching and access controls

Volumes declared in compose: open-webui, pgdata, searxng_data, webui_data, schedule_data, and nextcloud_data

Caution

PLEASE I BEG OF YOU REMEMBER TO BACK THESE UP/USE A LOCAL DIRECTORY. IF YOU DO NOT AND REMOVE OR PRUNE THE VOLUMES YOU WILL LOSE ALL DATA


Service Details

Open WebUI (open-webui)

  • Runs the latest ghcr.io/open-webui/open-webui:main image with Postgres backing for durable data (open-webui and pgdata volumes)

  • .env enables the login form, optional API keys (not currently used), and forwards identifying headers so downstream tools know which user initiated a request

  • Depends on the tool containers (openwebui_tools, coderunner, schedules-api, ollama-nextcloud) via internal networking; discover their OpenAPI docs from inside the UI to register tools

Postgres (postgres)

Important

If you plan on exposing ports on this service, please move the inline credentials to the .env file

  • Standard postgres:latest image. Credentials are set inline in compose for local development

  • Health-checked with pg_isready; the data volume pgdata stores Open WebUI metadata

SearxNG (searxng)

  • Private SearxNG deployment for agent web search tasks with HTML/JSON outputs enabled

  • Mounts searxng.yml and persists internal data to searxng_data. External port 4001 is exposed only for local debugging and should be removed in production

Code Runner (coderunner)

  • Bun-based HTTP server that accepts pure source code plus optional extra files, then runs the workload in a throwaway Docker container pinned to an allow-listed base image per language

  • Enforces strict limits (--network=none, read-only root FS, tmpfs workdir, CPU/memory caps, dropped capabilities). Supported Languages:

    • python
    • node
    • bun
    • bash
    • ruby
    • go
    • rust
    • java
    • c
    • cpp
  • Exposes GET /openapi.json and POST /execute inside the internal network (http://coderunner:8787). Requires the host Docker socket to spawn child sandboxes; the compose file mounts it read-only with matching group ID.

Roku Tool Server (openwebui_tools)

  • Lightweight Python HTTP server that proxies Roku remote commands

  • Reads ROKU_IP from .env; returns helpful errors when the IP is missing or the device is offline

  • Serves GET /roku/openapi.json for automatic tool registration and handles GET /roku/{command} requests. Supported command list matches the enum in spec/roku.openapi.json (navigation, inputs, power, volume, remote finder)

Browser Research UI (browser)

  • Builds the upstream browser-use/web-ui project, installs Chromium plus dependencies, and launches the UI on port 7788

  • Runs as an unprivileged user (uid 1000) with dedicated tmpfs directories and a webui_data volume for persisted history/state

  • Configure resolution, telemetry, and default LLM via browser/.env or container environment variables

  • The browser-use docs can be found at https://docs.browser-use.com/

Scheduler API (schedules-api)

  • Bun/Node cron worker that lets you schedule Open WebUI chats or template-driven jobs using authenticated user tokens

  • Persists schedule definitions to schedule_data (JSON payload) and can store uploaded supporting files under the same volume

  • Reads workflow templates from the bundled scheduler/templates.json. To inject custom templates, mount a host file or populate the root-level templates.json/ directory and update the compose volume mapping

  • Key endpoints (documented in scheduler/openapi.json):

    • GET /openapi.json: tool contract.
    • POST /api/schedules: create or replace a schedule (cron or one-shot ISO timestamp). Validates feature flags, attachments, and template references
    • GET /api/schedules: list schedules scoped to the calling user (identified via Open WebUI bearer token)
    • DELETE /api/schedules/{name}: remove a schedule the user owns
  • Includes a static UI in scheduler/public/ for manual interaction. Uses node-cron to avoid overlapping executions; failed jobs clean themselves up

Nextcloud Files Tool (ollama-nextcloud)

  • Express + WebDAV proxy that exposes a simple JSON API for browsing, downloading, and uploading files stored in Nextcloud

  • Environment variables (configured in .env):

    • NEXTCLOUD_APP_ID / NEXTCLOUD_APP_PASS / NEXTCLOUD_WEBDAV_ADDR: service credentials
    • NEXTCLOUD_ACCESS_DIRS: JSON array of regex strings that whitelist readable paths (e.g. ["^/Notes", "^/School"]). When unset, the tool has full access
  • Cached downloads are stored under /tmp using an embedded SQLite index (cache.ts). The server keeps ETags in sync and reuses cached bytes when possible unless bypasscache is requested

  • Major endpoints (see nextcloud/openapi.json):

    • GET /openapi.json: discovery document for tool registration.
    • POST /file: fetch a file. Automatically caches and returns metadata + content-type.
    • POST /dir: list directory contents (shallow or recursive).
    • PUT /file: upload via multipart form-data (optional recursive dir creation, never overwrites existing files).

Cloudflared Tunnel Config

  • cloudflared-tunnel-config.yml maps friendly hostnames to the local services (Ollama, Open WebUI, tool servers). Use it as a blueprint when exposing the stack through Cloudflare Tunnels.

Configuration (.env)

ROKU_IP=

WEBUI_URL=

# use built-in login form (username/password)
ENABLE_LOGIN_FORM="true"

# forward identity on outbound model requests (if you're going to use openAI/external LLM)
ENABLE_FORWARD_USER_INFO_HEADERS="true"

# allow user api keys for the scheduler calling OWUIs
ENABLE_API_KEY_AUTH="true"

NEXTCLOUD_APP_ID=
NEXTCLOUD_APP_PASS=
NEXTCLOUD_WEBDAV_ADDR=
NEXTCLOUD_ACCESS_DIRS=

Running the Stack

  1. Install Docker and Docker

  2. Populate .env with the correct Roku and Nextcloud settings plus any Open WebUI options

  3. Build images (pull base layers and bake GID overrides where needed):

    docker compose build --pull
    
  4. Launch everything:

    docker compose up -d
    
  5. Open WebUI is available on http://localhost:4000 (use credentials from the UI setup). The supporting services are reachable on the ports listed above or through the internal Docker network

To inspect logs for a specific service:

docker compose logs -f coderunner

Bring the stack down (volumes persist):

docker compose down

Registering Tool Servers in Open WebUI

Inside Open WebUI (Settings --> Tools --> Add tool server), point to the internal URLs:

  • Code runner: http://coderunner:8787/openapi.json
  • Scheduler: http://schedules-api:12253/openapi.json
  • Nextcloud files: http://ollama-nextcloud:1111/openapi.json
  • Roku remote: http://openwebui_tools:1331/roku/openapi.json

These should be fully internal in the docker network. If you expose them consider using a reverse proxy/authentication


Data, Volumes, and Shared Paths

  • open-webui volume: Open WebUI application state (uploads, knowledge base, configs)
  • pgdata volume: Postgres cluster data directory
  • searxng_data volume: SearxNG runtime files
  • webui_data volume: browser-use web UI session data
  • schedule_data volume: scheduler persisted schedules and stored file attachments
  • nextcloud_data volume: temp storage for cached Nextcloud content

Important

Back up the volumes you care about before upgrading images


License

The repository and reference code are released under Apache-2.0 (see LICENSE).

S
Description
My openWebUI/searxng configs, plugins, RAG server, as well as a custom program that runs the AI's code in isolated Docker containers
https://owebui.ion606.com
Readme Apache-2.0 350 KiB
Languages
TypeScript 61.7%
Python 30.1%
Dockerfile 8.2%