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 +# 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 + +[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..094b4fee02 --- /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": "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" + } + ] +}