From bf71c946986e62213eddad299807d9f666f45dbc Mon Sep 17 00:00:00 2001 From: a55uka <59313695+a55uka@users.noreply.github.com> Date: Mon, 19 Oct 2026 15:24:49 +0000 Subject: [PATCH 1/2] New script: Obico Self-hosted Obico server (AI failure detection & remote monitoring for OctoPrint/Klipper) as bare-metal install: daphne web, celery worker+beat, redis, and the CPU (ONNX) ml_api, deployed from the upstream release branch. Feature request: community-scripts/ProxmoxVE#1581 --- ct/obico.sh | 94 ++++++++++++++++++++++++ install/obico-install.sh | 154 +++++++++++++++++++++++++++++++++++++++ json/obico.json | 49 +++++++++++++ 3 files changed, 297 insertions(+) create mode 100644 ct/obico.sh create mode 100644 install/obico-install.sh create mode 100644 json/obico.json diff --git a/ct/obico.sh b/ct/obico.sh new file mode 100644 index 0000000000..35373934f1 --- /dev/null +++ b/ct/obico.sh @@ -0,0 +1,94 @@ +#!/usr/bin/env bash +_CS_DEFAULT_URL="https://raw.githubusercontent.com/community-scripts/DevScripts/main" +_cs_boot="${COMMUNITY_SCRIPTS_CORE_DIR:-$(dirname "${BASH_SOURCE[0]}")/../../core}/core/build.func" +source "$_cs_boot" 2>/dev/null || source <(curl -fsSL "${COMMUNITY_SCRIPTS_CORE_URL:-https://raw.githubusercontent.com/community-scripts/core/main}/core/build.func") +# Copyright (c) 2021-2026 community-scripts ORG +# Author: a55uka (a55uka) +# License: MIT | https://github.com/community-scripts/DevScripts/raw/main/LICENSE +# Source: https://github.com/TheSpaghettiDetective/obico-server + +APP="Obico" +var_tags="${var_tags:-3d-printing;monitoring;ai}" +var_cpu="${var_cpu:-4}" +var_ram="${var_ram:-4096}" +var_disk="${var_disk:-15}" +var_os="${var_os:-debian}" +var_version="${var_version:-13}" +#var_arm64="${var_arm64:-yes}" # unset = ask the user; set yes/no only when verified +var_unprivileged="${var_unprivileged:-1}" + +header_info "$APP" +variables +color +catch_errors + +function update_script() { + header_info + check_container_storage + check_container_resources + + if [[ ! -d /opt/obico ]]; then + msg_error "No ${APP} Installation Found!" + exit + fi + + if check_for_gh_branch "obico" "TheSpaghettiDetective/obico-server" "release"; then + msg_info "Stopping Services" + systemctl stop obico-tasks obico-web obico-ml-api + msg_ok "Stopped Services" + + create_backup /opt/obico/.env + + # No CLEAN_INSTALL: db.sqlite3, media, static_build, .venv and .env are + # gitignored in the upstream repo and survive reset --hard + clean -fd. + fetch_and_deploy_gh_branch "obico" "TheSpaghettiDetective/obico-server" "release" "/opt/obico" + sed -i "s/^VERSION=.*/VERSION=$(cat ~/.obico)/" /opt/obico/.env + + MOONRAKER_SHA=$(grep -oP 'checkout \K[a-f0-9]{40}' /opt/obico/backend/Dockerfile.base) + if [[ -n "$MOONRAKER_SHA" && "$(git -C /opt/moonraker rev-parse HEAD 2>/dev/null)" != "$MOONRAKER_SHA" ]]; then + msg_info "Updating Moonraker Metadata Library" + [[ -d /opt/moonraker/.git ]] || $STD git clone https://github.com/Arksine/moonraker.git /opt/moonraker + $STD git -C /opt/moonraker fetch --depth 1 origin "$MOONRAKER_SHA" + $STD git -C /opt/moonraker checkout "$MOONRAKER_SHA" + msg_ok "Updated Moonraker Metadata Library" + fi + + msg_info "Updating Python Environments" + cd /opt/obico/backend + $STD uv pip install -p .venv/bin/python -r requirements.txt + $STD uv pip install -p .venv/bin/python importlib_metadata==8.2.0 + cd /opt/obico/ml_api + $STD uv pip install -p .venv/bin/python -r requirements.txt onnxruntime==1.31.0 opencv-python-headless==4.12.0.88 + msg_ok "Updated Python Environments" + + if [[ "$(tr -d '\r' /dev/null) +ML_API_TOKEN=$(random_password 32) +cat </opt/obico/.env +DJANGO_SECRET_KEY=${DJANGO_SECRET_KEY} +REDIS_URL=redis://127.0.0.1:6379 +DATABASE_URL=sqlite:////opt/obico/backend/db.sqlite3 +INTERNAL_MEDIA_HOST=http://127.0.0.1:3334 +ML_API_HOST=http://127.0.0.1:3333 +ML_API_TOKEN=${ML_API_TOKEN} +OCTOPRINT_TUNNEL_PORT_RANGE=0-0 +VERSION=$(cat ~/.obico) +PYTHONPATH=/opt/moonraker +EOF +chmod 600 /opt/obico/.env +msg_ok "Configured Obico" + +msg_info "Initializing Database" +set -a +source /opt/obico/.env +set +a +cd /opt/obico/backend +$STD .venv/bin/python manage.py migrate --noinput +$STD .venv/bin/python manage.py collectstatic --noinput +$STD .venv/bin/python manage.py site --add "${LOCAL_IP}:3334" +msg_ok "Initialized Database" + +msg_info "Creating Services" +cat </etc/systemd/system/obico-ml-api.service +[Unit] +Description=Obico ML API +Wants=network-online.target +After=network-online.target + +[Service] +Type=simple +User=root +WorkingDirectory=/opt/obico/ml_api +EnvironmentFile=/opt/obico/.env +ExecStart=/opt/obico/ml_api/.venv/bin/gunicorn --bind 127.0.0.1:3333 --workers 1 --timeout 120 wsgi +Restart=on-failure +RestartSec=5 + +[Install] +WantedBy=multi-user.target +EOF + +cat </etc/systemd/system/obico-web.service +[Unit] +Description=Obico Web Server +Wants=network-online.target obico-ml-api.service +After=network-online.target redis-server.service obico-ml-api.service + +[Service] +Type=simple +User=root +WorkingDirectory=/opt/obico/backend +EnvironmentFile=/opt/obico/.env +ExecStart=/opt/obico/backend/.venv/bin/daphne -b 0.0.0.0 -p 3334 config.routing:application +Restart=on-failure +RestartSec=5 + +[Install] +WantedBy=multi-user.target +EOF + +cat </etc/systemd/system/obico-tasks.service +[Unit] +Description=Obico Celery Worker +Wants=network-online.target +After=network-online.target redis-server.service obico-web.service + +[Service] +Type=simple +User=root +WorkingDirectory=/opt/obico/backend +EnvironmentFile=/opt/obico/.env +ExecStart=/opt/obico/backend/.venv/bin/celery -A config worker --beat -l info -c 2 -Q realtime,celery +Restart=on-failure +RestartSec=5 + +[Install] +WantedBy=multi-user.target +EOF +systemctl enable -q --now obico-ml-api obico-web obico-tasks +msg_ok "Created Services" + +msg_info "Waiting for Obico to start" +for ((i = 1; i <= 45; i++)); do + curl -fsS http://127.0.0.1:3334/hc/ >/dev/null 2>&1 && break + sleep 2 +done +if ! curl -fsS http://127.0.0.1:3334/hc/ >/dev/null 2>&1; then + msg_error "Obico did not respond within 90s. Check 'journalctl -u obico-web -u obico-ml-api -u obico-tasks'" + exit 150 +fi +msg_ok "Obico is running" + +motd_ssh +customize +cleanup_lxc diff --git a/json/obico.json b/json/obico.json new file mode 100644 index 0000000000..8f913cbc1d --- /dev/null +++ b/json/obico.json @@ -0,0 +1,49 @@ +{ + "name": "Obico", + "slug": "obico", + "categories": [ + 16 + ], + "date_created": "2026-10-19", + "type": "ct", + "updateable": true, + "privileged": false, + "interface_port": 3334, + "documentation": "https://www.obico.io/docs/server-guides/", + "website": "https://www.obico.io/", + "repository": "https://github.com/TheSpaghettiDetective/obico-server", + "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/obico.webp", + "description": "Obico is a self-hosted server for 3D printing monitoring and remote control. It links to OctoPrint or Klipper printers and runs an AI failure-detection model (spaghetti detection) on the webcam stream. Print from anywhere, watch live video, and get notified when a print fails.", + "install_methods": [ + { + "type": "default", + "script": "ct/obico.sh", + "config_path": "/opt/obico/.env", + "resources": { + "cpu": 4, + "ram": 4096, + "hdd": 15, + "os": "Debian", + "version": "13" + } + } + ], + "default_credentials": { + "username": "root@example.com", + "password": "supersecret" + }, + "notes": [ + { + "text": "Log in at http://:3334/admin with root@example.com / supersecret and change the password immediately.", + "type": "warning" + }, + { + "text": "Point the Obico plugin (OctoPrint) or moonraker-obico (Klipper) at http://:3334 to link printers.", + "type": "info" + }, + { + "text": "Email notifications need SMTP settings in /opt/obico/.env (see dotenv.example), then restart the services.", + "type": "info" + } + ] +} From ebb5101d468f156d25de38322c0537b0fc5f79bc Mon Sep 17 00:00:00 2001 From: a55uka <59313695+a55uka@users.noreply.github.com> Date: Mon, 19 Oct 2026 16:48:30 +0000 Subject: [PATCH 2/2] Obico: expose ML API for external clients (e.g. Bambuddy) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bambuddy's Obico integration calls the ML API directly on :3333 (/hc/ must answer 'ok', /p/?img= for detection), so bind it to 0.0.0.0 — ML_API_TOKEN gates everything but the health check. Note it in the JSON metadata. --- install/obico-install.sh | 5 ++++- json/obico.json | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/install/obico-install.sh b/install/obico-install.sh index d5fb89c2b9..f4f16994fa 100644 --- a/install/obico-install.sh +++ b/install/obico-install.sh @@ -90,7 +90,10 @@ Type=simple User=root WorkingDirectory=/opt/obico/ml_api EnvironmentFile=/opt/obico/.env -ExecStart=/opt/obico/ml_api/.venv/bin/gunicorn --bind 127.0.0.1:3333 --workers 1 --timeout 120 wsgi +# Bound to 0.0.0.0 because external clients (e.g. Bambuddy's Obico integration) +# call the ML API directly; ML_API_TOKEN from /opt/obico/.env gates every +# endpoint but the health check. +ExecStart=/opt/obico/ml_api/.venv/bin/gunicorn --bind 0.0.0.0:3333 --workers 1 --timeout 120 wsgi Restart=on-failure RestartSec=5 diff --git a/json/obico.json b/json/obico.json index 8f913cbc1d..094b4fee02 100644 --- a/json/obico.json +++ b/json/obico.json @@ -42,7 +42,7 @@ "type": "info" }, { - "text": "Email notifications need SMTP settings in /opt/obico/.env (see dotenv.example), then restart the services.", + "text": "For Bambuddy's AI failure detection, enter http://:3333 as the Obico ML URL and the ML_API_TOKEN from /opt/obico/.env.", "type": "info" } ]