Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 93 additions & 0 deletions ct/obico.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#!/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}" # arm64 verified: CI install + health check passed
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

fetch_and_deploy_gh_branch "obico" "TheSpaghettiDetective/obico-server" "release" "/opt/obico"
Comment thread
CrazyWolf13 marked this conversation as resolved.
Resolved
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

IMPORTLIB_METADATA_PIN=$(grep -oP 'importlib_metadata==\K[0-9.]+' /opt/obico/backend/Dockerfile.base)
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==${IMPORTLIB_METADATA_PIN}"
cd /opt/obico/ml_api
$STD uv pip install -p .venv/bin/python -r requirements.txt onnxruntime opencv-python-headless
msg_ok "Updated Python Environments"

if [[ "$(tr -d '\r' </opt/obico/ml_api/model/model-weights.onnx.sha256)" != "$(sha256sum /model_cache/ml_api/onnx/model-weights.onnx | cut -d' ' -f1)" ]]; then
msg_info "Downloading Failure Detection Model"
bash /opt/obico/ml_api/scripts/fetch_verified.sh "$(tr -d '\r' </opt/obico/ml_api/model/model-weights.onnx.url)" /model_cache/ml_api/onnx/model-weights.onnx 50000000 "$(tr -d '\r' </opt/obico/ml_api/model/model-weights.onnx.sha256)"
msg_ok "Downloaded Failure Detection Model"
fi

msg_info "Running Database Migrations"
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
msg_ok "Ran Database Migrations"

msg_info "Starting Services"
systemctl start obico-ml-api obico-web obico-tasks
msg_ok "Started Services"
msg_ok "Updated successfully!"
fi
exit
}

start
build_container
description

msg_ok "Completed successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW}Access it using the following URL:${CL}"
echo -e "${GATEWAY}${BGN}http://${IP}:3334${CL}"
150 changes: 150 additions & 0 deletions install/obico-install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
#!/usr/bin/env bash

# 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

source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
color
verb_ip6
catch_errors
setting_up_container
network_check
update_os

msg_info "Installing Dependencies"
$STD apt install -y \
libmagic1 \
redis-server
systemctl enable -q --now redis-server
msg_ok "Installed Dependencies"

setup_ffmpeg

fetch_and_deploy_gh_branch "obico" "TheSpaghettiDetective/obico-server" "release" "/opt/obico"
PYTHON_VERSION="3.12" setup_uv

msg_info "Setting up Python Environments"
IMPORTLIB_METADATA_PIN=$(grep -oP 'importlib_metadata==\K[0-9.]+' /opt/obico/backend/Dockerfile.base) # tracked from upstream's Dockerfile.base
cd /opt/obico/backend
$STD uv venv --python 3.12 .venv
$STD uv pip install -p .venv/bin/python -r requirements.txt
$STD uv pip install -p .venv/bin/python "importlib_metadata==${IMPORTLIB_METADATA_PIN}"
cd /opt/obico/ml_api
$STD uv venv --python 3.12 .venv
$STD uv pip install -p .venv/bin/python -r requirements.txt onnxruntime opencv-python-headless
msg_ok "Set up Python Environments"

msg_info "Installing Moonraker Metadata Library"
MOONRAKER_SHA=$(grep -oP 'checkout \K[a-f0-9]{40}' /opt/obico/backend/Dockerfile.base) # pinned clone as in backend/Dockerfile.base, imported via PYTHONPATH
$STD git clone https://github.com/Arksine/moonraker.git /opt/moonraker
$STD git -C /opt/moonraker checkout "$MOONRAKER_SHA"
msg_ok "Installed Moonraker Metadata Library"

msg_info "Downloading Failure Detection Model"
mkdir -p /model_cache/ml_api/onnx
bash /opt/obico/ml_api/scripts/fetch_verified.sh "$(tr -d '\r' </opt/obico/ml_api/model/model-weights.onnx.url)" /model_cache/ml_api/onnx/model-weights.onnx 50000000 "$(tr -d '\r' </opt/obico/ml_api/model/model-weights.onnx.sha256)" # upstream's checksum-verifying downloader, URL and sha256 from sidecar files
msg_ok "Downloaded Failure Detection Model"

msg_info "Configuring Obico"
DJANGO_SECRET_KEY=$(cd /opt/obico/backend && .venv/bin/python -c 'import secrets; print(secrets.token_urlsafe())' 2>/dev/null)
ML_API_TOKEN=$(random_password 32)
cat <<EOF >/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 <<EOF >/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 0.0.0.0:3333 --workers 1 --timeout 120 wsgi # 0.0.0.0 for external clients (e.g. Bambuddy); ML_API_TOKEN gates everything but the health check
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

cat <<EOF >/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 <<EOF >/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
53 changes: 53 additions & 0 deletions json/obico.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
{
"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/",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing architectures

"website": "https://www.obico.io/",
"repository": "https://github.com/TheSpaghettiDetective/obico-server",
"architectures": [
"amd64",
"arm64"
],
"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://<IP>: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://<IP>:3334 to link printers.",
"type": "info"
},
{
"text": "For Bambuddy's AI failure detection, enter http://<IP>:3333 as the Obico ML URL and the ML_API_TOKEN from /opt/obico/.env.",
"type": "info"
}
]
}
Loading