Compare commits

..

15 Commits

Author SHA1 Message Date
Marcin Tojek 9525e2d4d1 cleanup 2025-12-03 15:49:43 +01:00
Marcin Tojek e07e289698 test 2025-12-03 15:28:23 +01:00
Marcin Tojek 1be384252e test 2025-12-03 15:26:01 +01:00
Marcin Tojek 8fa6be0edf test 2025-12-03 15:14:04 +01:00
Marcin Tojek 82c86db196 test 2025-12-03 15:12:00 +01:00
Marcin Tojek 019d735fdd fix: rename variables to HTTP_SERVER_PORT and HTTP_SERVER_LOG_PATH 2025-12-03 14:07:29 +00:00
Marcin Tojek 520a2947e1 Revert "fixes"
This reverts commit abe133afe8.
2025-12-03 15:01:42 +01:00
Marcin Tojek abe133afe8 fixes 2025-12-03 14:56:35 +01:00
Marcin Tojek 5335c85495 fixes 2025-12-03 14:55:09 +01:00
Marcin Tojek d6a18d8419 fix: restore LOG_PATH and PORT variable assignments from templatefile 2025-12-03 13:52:40 +00:00
Marcin Tojek d03588356e fix: remove running process check 2025-12-03 13:22:04 +00:00
Marcin Tojek 6e94ecc165 fix: use venv instead of pip install --user
- Remove automatic Python installation - user must have Python 3.11+ in image
- Use virtual environment (~/.open-webui-venv) to avoid externally-managed-environment error
- Add set -e to fail script on errors
- Update README with installation instructions
2025-12-03 11:42:17 +00:00
Marcin Tojek 25636524d3 fixes 2 2025-12-03 12:34:01 +01:00
Marcin Tojek 504be92cf4 fixes 2025-12-03 12:19:25 +01:00
Marcin Tojek 35f93c663f feat: add open-webui module for coder-labs
- Installs Open WebUI via pip (Python 3.11+ required)
- Auto-installs Python 3.11 from deadsnakes PPA if not available
- Configurable port, share level, logging
- Subdomain support for clean URLs
2025-12-03 09:37:54 +00:00
8 changed files with 189 additions and 30 deletions
+5
View File
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg viewBox="0 0 500 500" xmlns="http://www.w3.org/2000/svg">
<circle cx="250" cy="250" r="250" fill="#fff"/>
<path d="m335 150h40v200h-40zm-130 0a100 100 0 1 0 0 200 100 100 0 1 0 0-200zm0 40a60 60 0 1 1 0 120 60 60 0 1 1 0-120z"/>
</svg>

After

Width:  |  Height:  |  Size: 293 B

@@ -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
}
```
@@ -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
}
+60
View File
@@ -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}"
@@ -12,12 +12,12 @@ Run [Amp CLI](https://ampcode.com/) in your workspace to access Sourcegraph's AI
```tf
module "amp-cli" {
source = "registry.coder.com/coder-labs/sourcegraph-amp/coder"
version = "2.1.0"
agent_id = coder_agent.example.id
amp_api_key = var.amp_api_key
install_amp = true
agentapi_version = "latest"
source = "registry.coder.com/coder-labs/sourcegraph-amp/coder"
version = "2.0.2"
agent_id = coder_agent.example.id
sourcegraph_amp_api_key = var.sourcegraph_amp_api_key
install_sourcegraph_amp = true
agentapi_version = "2.0.2"
}
```
@@ -48,7 +48,7 @@ variable "amp_api_key" {
module "amp-cli" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder-labs/sourcegraph-amp/coder"
amp_version = "2.1.0"
amp_version = "2.0.2"
agent_id = coder_agent.example.id
amp_api_key = var.amp_api_key # recommended for tasks usage
workdir = "/home/coder/project"
@@ -55,7 +55,7 @@ variable "install_agentapi" {
variable "agentapi_version" {
type = string
description = "The version of AgentAPI to install."
default = "v0.11.1"
default = "v0.10.0"
}
variable "cli_app" {
@@ -160,16 +160,6 @@ variable "mcp" {
default = null
}
variable "mode" {
type = string
description = "Set the agent mode (free, rush, smart) — controls the model, system prompt, and tool selection. Default: smart"
default = "smart"
validation {
condition = contains(["", "free", "rush", "smart"], var.mode)
error_message = "Invalid mode. Select one from (free, rush, smart)"
}
}
data "external" "env" {
program = ["sh", "-c", "echo '{\"CODER_AGENT_TOKEN\":\"'$CODER_AGENT_TOKEN'\",\"CODER_AGENT_URL\":\"'$CODER_AGENT_URL'\"}'"]
}
@@ -180,7 +170,6 @@ locals {
default_base_config = jsonencode({
"amp.anthropic.thinking.enabled" = true
"amp.todos.enabled" = true
"amp.terminal.animation" = false
})
user_config = jsondecode(var.base_amp_config != "" ? var.base_amp_config : local.default_base_config)
@@ -248,7 +237,6 @@ module "agentapi" {
ARG_AMP_START_DIRECTORY='${var.workdir}' \
ARG_AMP_TASK_PROMPT='${base64encode(var.ai_prompt)}' \
ARG_REPORT_TASKS='${var.report_tasks}' \
ARG_MODE='${var.mode}' \
/tmp/start.sh
EOT
@@ -1,4 +1,9 @@
#!/bin/bash
if [ -f "$HOME/.bashrc" ]; then
source "$HOME"/.bashrc
fi
set -euo pipefail
# ANSI colors
@@ -29,7 +29,6 @@ echo "--------------------------------"
printf "Workspace: %s\n" "$ARG_AMP_START_DIRECTORY"
printf "Task Prompt: %s\n" "$ARG_AMP_TASK_PROMPT"
printf "ARG_REPORT_TASKS: %s\n" "$ARG_REPORT_TASKS"
printf "ARG_MODE: %s\n" "$ARG_MODE"
echo "--------------------------------"
ensure_command amp
@@ -51,13 +50,6 @@ else
printf "amp_api_key not provided\n"
fi
ARGS=()
if [ -n "$ARG_MODE" ]; then
printf "Running agent in: %s mode" "$ARG_MODE"
ARGS+=(--mode "$ARG_MODE")
fi
if [ -n "$ARG_AMP_TASK_PROMPT" ]; then
if [ "$ARG_REPORT_TASKS" == "true" ]; then
printf "amp task prompt provided : %s" "$ARG_AMP_TASK_PROMPT\n"
@@ -66,8 +58,8 @@ if [ -n "$ARG_AMP_TASK_PROMPT" ]; then
PROMPT="$ARG_AMP_TASK_PROMPT"
fi
# Pipe the prompt into amp, which will be run inside agentapi
agentapi server --type amp --term-width=67 --term-height=1190 -- bash -c "echo \"$PROMPT\" | amp" "${ARGS[@]}"
agentapi server --type amp --term-width=67 --term-height=1190 -- bash -c "echo \"$PROMPT\" | amp"
else
printf "No task prompt given.\n"
agentapi server --type amp --term-width=67 --term-height=1190 -- amp "${ARGS[@]}"
agentapi server --type amp --term-width=67 --term-height=1190 -- amp
fi