diff --git a/.icons/openwebui.svg b/.icons/openwebui.svg new file mode 100644 index 000000000..06f676458 --- /dev/null +++ b/.icons/openwebui.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/registry/coder-labs/modules/open-webui/README.md b/registry/coder-labs/modules/open-webui/README.md new file mode 100644 index 000000000..3f468fa24 --- /dev/null +++ b/registry/coder-labs/modules/open-webui/README.md @@ -0,0 +1,37 @@ +--- +display_name: Open WebUI +description: A self-hosted AI chat interface supporting various LLM providers +icon: ../../../../.icons/openwebui.svg +verified: true +tags: [ai, llm, chat, web-ui, python] +--- + +# Open WebUI + +Open WebUI is a user-friendly web interface for interacting with Large Language Models. It provides a ChatGPT-like interface that can connect to various LLM providers including OpenAI, Ollama, and more. + +This module installs and runs Open WebUI using Python and pip within your Coder workspace. + +## Prerequisites + +- **Python 3.11 or higher** must be installed in your image (with `venv` module) +- Port 7800 (default) or your custom port must be available + +For Ubuntu/Debian, you can install Python 3.11 from [deadsnakes PPA](https://launchpad.net/~deadsnakes/+archive/ubuntu/ppa): + +```shell +sudo add-apt-repository -y ppa:deadsnakes/ppa +sudo apt-get update +sudo apt-get install -y python3.11 python3.11-venv +``` + +## Basic Usage + +```tf +module "open-webui" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/coder-labs/open-webui/coder" + version = "0.9.0" + agent_id = coder_agent.main.id +} +``` \ No newline at end of file diff --git a/registry/coder-labs/modules/open-webui/main.tf b/registry/coder-labs/modules/open-webui/main.tf new file mode 100644 index 000000000..6729bc447 --- /dev/null +++ b/registry/coder-labs/modules/open-webui/main.tf @@ -0,0 +1,72 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + coder = { + source = "coder/coder" + version = ">= 2.5" + } + } +} + +# Add required variables for your modules and remove any unneeded variables +variable "agent_id" { + type = string + description = "The ID of a Coder agent." +} + +variable "http_server_log_path" { + type = string + description = "The path to log Open WebUI to." + default = "/tmp/open-webui.log" +} + +variable "http_server_port" { + type = number + description = "The port to run Open WebUI on." + default = 7800 +} + +variable "share" { + type = string + default = "owner" + validation { + condition = var.share == "owner" || var.share == "authenticated" || var.share == "public" + error_message = "Incorrect value. Please set either 'owner', 'authenticated', or 'public'." + } +} + +variable "order" { + type = number + description = "The order determines the position of app in the UI presentation. The lowest order is shown first and apps with equal order are sorted by name (ascending order)." + default = null +} + +variable "group" { + type = string + description = "The name of a group that this app belongs to." + default = null +} + +resource "coder_script" "open-webui" { + agent_id = var.agent_id + display_name = "open-webui" + icon = "/icon/openwebui.svg" + script = templatefile("${path.module}/run.sh", { + HTTP_SERVER_LOG_PATH : var.http_server_log_path, + HTTP_SERVER_PORT : var.http_server_port, + }) + run_on_start = true +} + +resource "coder_app" "open-webui" { + agent_id = var.agent_id + slug = "open-webui" + display_name = "Open WebUI" + url = "http://localhost:${var.http_server_port}" + icon = "/icon/openwebui.svg" + subdomain = true + share = var.share + order = var.order + group = var.group +} diff --git a/registry/coder-labs/modules/open-webui/run.sh b/registry/coder-labs/modules/open-webui/run.sh new file mode 100755 index 000000000..aef089392 --- /dev/null +++ b/registry/coder-labs/modules/open-webui/run.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env sh + +set -eu + +printf '\033[0;1mInstalling Open WebUI...\n\n' + +check_python_version() { + python_cmd="$1" + if command -v "$python_cmd" > /dev/null 2>&1; then + version=$("$python_cmd" --version 2>&1 | awk '{print $2}') + major=$(echo "$version" | cut -d. -f1) + minor=$(echo "$version" | cut -d. -f2) + if [ "$major" -eq 3 ] && [ "$minor" -ge 11 ]; then + echo "$python_cmd" + return 0 + fi + fi + return 1 +} + +PYTHON_CMD="" +for cmd in python3.13 python3.12 python3.11 python3 python; do + if result=$(check_python_version "$cmd"); then + PYTHON_CMD="$result" + echo "✅ Found suitable Python: $PYTHON_CMD ($($PYTHON_CMD --version 2>&1))" + break + fi +done + +if [ -z "$PYTHON_CMD" ]; then + echo "❌ Python 3.11 or higher is required but not found." + echo "" + echo "Please install Python 3.11+ in your image. For example on Ubuntu/Debian:" + echo " sudo add-apt-repository -y ppa:deadsnakes/ppa" + echo " sudo apt-get update" + echo " sudo apt-get install -y python3.11 python3.11-venv" + exit 1 +fi + +VENV_DIR="$HOME/.open-webui-venv" +if [ ! -d "$VENV_DIR" ]; then + echo "📦 Creating virtual environment..." + "$PYTHON_CMD" -m venv "$VENV_DIR" +fi +. "$VENV_DIR/bin/activate" + +if ! pip show open-webui > /dev/null 2>&1; then + echo "📦 Installing Open WebUI..." + pip install open-webui + echo "🥳 Open WebUI has been installed" +else + echo "✅ Open WebUI is already installed" +fi + +echo "👷 Starting Open WebUI in background..." +echo "Check logs at ${HTTP_SERVER_LOG_PATH}" + +open-webui serve --host 0.0.0.0 --port "${HTTP_SERVER_PORT}" > "${HTTP_SERVER_LOG_PATH}" 2>&1 & + +echo "🥳 Open WebUI is ready. HTTP server is listening on port ${HTTP_SERVER_PORT}"