Compare commits

...

8 Commits

Author SHA1 Message Date
MickLesk
ee8316a085 Kima-Hub: install the Python services into a uv venv
pip3 installed into the system Python with PIP_BREAK_SYSTEM_PACKAGES and
stopped once a dependency wanted a newer idna than Debian's python3-idna,
which pip cannot uninstall (no RECORD file) (#17784). The analyzers now run
from /opt/kima-hub/venv on a uv-managed Python 3.13.
2026-10-08 14:53:11 +02:00
MickLesk
a0300a02c9 CLIProxyAPI: keep plugins and data across updates
The clean install wiped /opt/cliproxyapi including plugins/ and data/, so
every update removed installed plugins and their data (#17750).
2026-10-08 14:53:11 +02:00
MickLesk
daf99e9d61 Homarr: replace the musl better-sqlite3 that v2.3.0 ships for Debian
The build-debian tarballs of v2.3.0 carry the Alpine build of
better_sqlite3.node, so the DB migration dies with ERR_DLOPEN_FAILED on
libc.musl and Homarr no longer starts after an update (#17783,
homarr-labs/homarr#7097). When the bundled module is musl, swap in
better-sqlite3's own glibc prebuild for the running Node ABI. The update runs
the check outside the release check, so containers already on 2.3.0 are
repaired too; it does nothing once upstream ships a correct tarball.
2026-10-08 14:53:10 +02:00
MickLesk
a2475416c9 BookOrbit: retry the client build when the bundler crashes
Since rolldown 1.2.8, vite build dies at random with SIGSEGV or SIGBUS
(rolldown#10860, closed upstream), which stopped the 3.3.0 update with exit
139 (#17753). Retry the client build up to three times before giving up.
2026-10-08 09:47:00 +02:00
MickLesk
2d0f0de182 Immich: only mention the HEIC patch when it applies
On 3.3.0 the sharp call it rewrites is gone, so every run printed "pattern not found, skipped" into the spinner line and then "Patched". Check for the pattern first and stay silent otherwise.
2026-10-08 09:25:38 +02:00
MickLesk
53a69bbaba Immich: stop when uv sync keeps failing
After three failed attempts the loop still reported the machine-learning step as done, so an update ended in "Updated successfully" with no usable venv and immich-ml failing on start. Exit with an error instead.
2026-10-08 09:24:58 +02:00
MickLesk
22cd9219d6 Immich: run machine learning on Python 3.13
3.3.0 requires Python >=3.12 for machine learning and upstream builds both its CPU and OpenVINO images on 3.13. The CPU path still pinned 3.11, so uv sync failed on every update and install (#17762).
2026-10-08 09:24:22 +02:00
MickLesk
a2a2e5a7b4 Immich: pin v3.3.0 again
Reapplies #17759, reverted in #17767 because machine learning broke on 3.3.0; the fixes follow.
2026-10-08 09:23:40 +02:00
8 changed files with 67 additions and 51 deletions

View File

@@ -48,7 +48,12 @@ function update_script() {
$STD corepack prepare "pnpm@${PNPM_VERSION}" --activate
$STD pnpm install --frozen-lockfile
$STD pnpm --filter client run build-only
# vite's bundler (rolldown) crashes at random on some builds, rolldown#10860.
for attempt in 1 2 3; do
$STD pnpm --filter client run build-only && break
[[ $attempt -eq 3 ]] && { msg_error "Client build failed three times"; exit 1; }
msg_warn "Client build failed (attempt $attempt), retrying"
done
$STD pnpm --filter server run build
cp -r /opt/bookorbit/client/dist /opt/bookorbit/server/public
mkdir -p /opt/bookorbit/server/migrations

View File

@@ -39,7 +39,7 @@ function update_script() {
create_backup /opt/cliproxyapi/config.yaml
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "cliproxyapi" "router-for-me/CLIProxyAPI" "prebuild" "latest" "/opt/cliproxyapi" "CLIProxyAPI_*_linux_$(arch_resolve "amd64" "aarch64").tar.gz"
CLEAN_INSTALL=1 CLEAN_INSTALL_KEEP="plugins data" fetch_and_deploy_gh_release "cliproxyapi" "router-for-me/CLIProxyAPI" "prebuild" "latest" "/opt/cliproxyapi" "CLIProxyAPI_*_linux_$(arch_resolve "amd64" "aarch64").tar.gz"
restore_backup

View File

@@ -85,6 +85,18 @@ EOF
msg_ok "Started Services"
msg_ok "Updated successfully!"
fi
# v2.3.0's Debian build ships a musl better-sqlite3 (homarr-labs/homarr#7097).
mapfile -t MUSL_MODULES < <(find /opt/homarr -name better_sqlite3.node -exec grep -aqE "ld-musl|libc\.musl" {} \; -print)
if ((${#MUSL_MODULES[@]})); then
msg_info "Replacing musl better-sqlite3 build"
BSQ_VERSION=$(jq -r .version /opt/homarr/node_modules/better-sqlite3/package.json)
curl_with_retry "https://github.com/WiseLibs/better-sqlite3/releases/download/v${BSQ_VERSION}/better-sqlite3-v${BSQ_VERSION}-node-v$(node -p process.versions.modules)-linux-$(arch_resolve "x64" "arm64").tar.gz" /tmp/better-sqlite3.tar.gz
tar -xzf /tmp/better-sqlite3.tar.gz -C /tmp build/Release/better_sqlite3.node
for module in "${MUSL_MODULES[@]}"; do cp /tmp/build/Release/better_sqlite3.node "$module"; done
rm -rf /tmp/better-sqlite3.tar.gz /tmp/build
systemctl restart homarr
msg_ok "Replaced musl better-sqlite3 build"
fi
exit
}

View File

@@ -77,7 +77,7 @@ EOF
BASE_DIR=${STAGING_DIR}/base-images
SOURCE_DIR=${STAGING_DIR}/image-source
cd /tmp
RELEASE="v3.2.4"
RELEASE="v3.3.0"
if [[ -f ~/.intel_version ]]; then
INTEL_SRC="https://raw.githubusercontent.com/immich-app/immich/${RELEASE}/machine-learning"
curl -fsSL "${INTEL_SRC}/scripts/install-intel-runtime.sh" -o ./intel-runtime 2>/dev/null ||
@@ -274,12 +274,13 @@ EOF
msg_info "Updating Intel OpenVINO machine-learning"
for attempt in $(seq 1 3); do
$STD sudo --preserve-env=VIRTUAL_ENV,UV_HTTP_TIMEOUT -Pnu immich uv sync --extra openvino --no-dev --active --link-mode copy -n -p "${ML_PYTHON}" --managed-python && break
[[ $attempt -lt 3 ]] && msg_warn "uv sync attempt $attempt failed, retrying..." && sleep 10
[[ $attempt -eq 3 ]] && { msg_error "uv sync failed three times, the machine-learning environment was not built"; exit 1; }
msg_warn "uv sync attempt $attempt failed, retrying..." && sleep 10
done
patchelf --clear-execstack "${VIRTUAL_ENV}/lib/python3.13/site-packages/onnxruntime/capi/onnxruntime_pybind11_state.cpython-313-$(arch_resolve "x86_64" "aarch64")-linux-gnu.so"
msg_ok "Updated Intel OpenVINO machine-learning"
else
ML_PYTHON="python3.11"
ML_PYTHON="python3.13"
msg_info "Pre-installing Python ${ML_PYTHON} for machine-learning"
for attempt in $(seq 1 3); do
$STD sudo --preserve-env=VIRTUAL_ENV -Pnu immich uv python install "${ML_PYTHON}" && break
@@ -289,7 +290,8 @@ EOF
msg_info "Updating machine-learning"
for attempt in $(seq 1 3); do
$STD sudo --preserve-env=VIRTUAL_ENV,UV_HTTP_TIMEOUT -Pnu immich uv sync --extra cpu --no-dev --active --link-mode copy -n -p "${ML_PYTHON}" --managed-python && break
[[ $attempt -lt 3 ]] && msg_warn "uv sync attempt $attempt failed, retrying..." && sleep 10
[[ $attempt -eq 3 ]] && { msg_error "uv sync failed three times, the machine-learning environment was not built"; exit 1; }
msg_warn "uv sync attempt $attempt failed, retrying..." && sleep 10
done
msg_ok "Updated machine-learning"
fi
@@ -333,6 +335,10 @@ EOF
sed -i -e '$a\' "$INSTALL_DIR"/.env
echo "IMMICH_HELMET_FILE=true" >>"$INSTALL_DIR"/.env
fi
if ! grep -q 'MODEL_REVISION' "$INSTALL_DIR"/.env; then
sed -i -e '$a\' "$INSTALL_DIR"/.env
echo "MACHINE_LEARNING_MODEL_REVISION=v2" >>"$INSTALL_DIR"/.env
fi
if grep -q 'ExecStart=/usr/bin/node' /etc/systemd/system/immich-web.service; then
sed -i '/^EnvironmentFile=/d' /etc/systemd/system/immich-web.service
@@ -341,25 +347,12 @@ EOF
fi
# MickLesk temporary patch for HEIC thumbnail gen
msg_info "Patching media.repository.js"
MEDIA_REPO_JS="/opt/immich/app/dist/repositories/media.repository.js"
if [[ -f "$MEDIA_REPO_JS" ]]; then
python3 - <<'PY'
from pathlib import Path
p = Path('/opt/immich/app/dist/repositories/media.repository.js')
s = p.read_text()
old = "(0, sharp_1.default)(input).metadata()"
new = "(0, sharp_1.default)(input, { unlimited: true, limitInputPixels: false }).metadata()"
if new in s:
print('hotfix already there')
elif old in s:
p.write_text(s.replace(old, new, 1))
print('hotfix applied')
else:
print('pattern not found, skipped')
PY
if grep -qF "(0, sharp_1.default)(input).metadata()" "$MEDIA_REPO_JS" 2>/dev/null; then
msg_info "Patching media.repository.js"
sed -i '0,/(0, sharp_1\.default)(input)\.metadata()/s//(0, sharp_1.default)(input, { unlimited: true, limitInputPixels: false }).metadata()/' "$MEDIA_REPO_JS"
msg_ok "Patched media.repository.js"
fi
msg_ok "Patched media.repository.js"
# chown excluding upload dir contents (may be a mount with restricted permissions)
chown immich:immich "$INSTALL_DIR"

View File

@@ -33,7 +33,12 @@ PNPM_VERSION=$(jq -r '.packageManager | ltrimstr("pnpm@")' /opt/bookorbit/packag
$STD corepack prepare "pnpm@${PNPM_VERSION}" --activate
$STD pnpm install --frozen-lockfile
$STD pnpm --filter client run build-only
# vite's bundler (rolldown) crashes at random on some builds, rolldown#10860.
for attempt in 1 2 3; do
$STD pnpm --filter client run build-only && break
[[ $attempt -eq 3 ]] && { msg_error "Client build failed three times"; exit 1; }
msg_warn "Client build failed (attempt $attempt), retrying"
done
$STD pnpm --filter server run build
cp -r /opt/bookorbit/client/dist /opt/bookorbit/server/public
mkdir -p /opt/bookorbit/server/migrations

View File

@@ -25,6 +25,18 @@ NODE_VERSION=$(curl -s https://raw.githubusercontent.com/homarr-labs/homarr/dev/
setup_nodejs
fetch_and_deploy_gh_release "homarr" "homarr-labs/homarr" "prebuild" "latest" "/opt/homarr" "build-debian-$(arch_resolve).tar.gz"
# v2.3.0's Debian build ships a musl better-sqlite3 (homarr-labs/homarr#7097).
mapfile -t MUSL_MODULES < <(find /opt/homarr -name better_sqlite3.node -exec grep -aqE "ld-musl|libc\.musl" {} \; -print)
if ((${#MUSL_MODULES[@]})); then
msg_info "Replacing musl better-sqlite3 build"
BSQ_VERSION=$(jq -r .version /opt/homarr/node_modules/better-sqlite3/package.json)
curl_with_retry "https://github.com/WiseLibs/better-sqlite3/releases/download/v${BSQ_VERSION}/better-sqlite3-v${BSQ_VERSION}-node-v$(node -p process.versions.modules)-linux-$(arch_resolve "x64" "arm64").tar.gz" /tmp/better-sqlite3.tar.gz
tar -xzf /tmp/better-sqlite3.tar.gz -C /tmp build/Release/better_sqlite3.node
for module in "${MUSL_MODULES[@]}"; do cp /tmp/build/Release/better_sqlite3.node "$module"; done
rm -rf /tmp/better-sqlite3.tar.gz /tmp/build
msg_ok "Replaced musl better-sqlite3 build"
fi
msg_info "Installing Homarr"
mkdir -p /opt/homarr_db
touch /opt/homarr_db/db.sqlite

View File

@@ -13,7 +13,7 @@ setting_up_container
network_check
update_os
RELEASE="v3.2.4"
RELEASE="v3.3.0"
if lscpu | grep -q 'GenuineIntel'; then
echo ""
echo ""
@@ -442,12 +442,13 @@ if [[ -f ~/.openvino ]]; then
msg_info "Installing Intel OpenVINO machine-learning"
for attempt in $(seq 1 3); do
$STD sudo --preserve-env=VIRTUAL_ENV,UV_HTTP_TIMEOUT -Pnu immich uv sync --extra openvino --no-dev --active --link-mode copy -n -p "${ML_PYTHON}" --managed-python && break
[[ $attempt -lt 3 ]] && msg_warn "uv sync attempt $attempt failed, retrying..." && sleep 10
[[ $attempt -eq 3 ]] && { msg_error "uv sync failed three times, the machine-learning environment was not built"; exit 1; }
msg_warn "uv sync attempt $attempt failed, retrying..." && sleep 10
done
patchelf --clear-execstack "${VIRTUAL_ENV}/lib/python3.13/site-packages/onnxruntime/capi/onnxruntime_pybind11_state.cpython-313-$(arch_resolve "x86_64" "aarch64")-linux-gnu.so"
msg_ok "Installed Intel OpenVINO machine-learning"
else
ML_PYTHON="python3.11"
ML_PYTHON="python3.13"
msg_info "Pre-installing Python ${ML_PYTHON} for machine-learning"
for attempt in $(seq 1 3); do
$STD sudo --preserve-env=VIRTUAL_ENV -Pnu immich uv python install "${ML_PYTHON}" && break
@@ -457,7 +458,8 @@ else
msg_info "Installing machine-learning"
for attempt in $(seq 1 3); do
$STD sudo --preserve-env=VIRTUAL_ENV,UV_HTTP_TIMEOUT -Pnu immich uv sync --extra cpu --no-dev --active --link-mode copy -n -p "${ML_PYTHON}" --managed-python && break
[[ $attempt -lt 3 ]] && msg_warn "uv sync attempt $attempt failed, retrying..." && sleep 10
[[ $attempt -eq 3 ]] && { msg_error "uv sync failed three times, the machine-learning environment was not built"; exit 1; }
msg_warn "uv sync attempt $attempt failed, retrying..." && sleep 10
done
msg_ok "Installed machine-learning"
fi
@@ -488,25 +490,12 @@ ln -s "$GEO_DIR" "$APP_DIR"
msg_ok "Installed GeoNames data"
# MickLesk temporary patch for HEIC thumbnail gen
msg_info "Patching media.repository.js"
MEDIA_REPO_JS="/opt/immich/app/dist/repositories/media.repository.js"
if [[ -f "$MEDIA_REPO_JS" ]]; then
python3 - <<'PY'
from pathlib import Path
p = Path('/opt/immich/app/dist/repositories/media.repository.js')
s = p.read_text()
old = "(0, sharp_1.default)(input).metadata()"
new = "(0, sharp_1.default)(input, { unlimited: true, limitInputPixels: false }).metadata()"
if new in s:
print('hotfix already there')
elif old in s:
p.write_text(s.replace(old, new, 1))
print('hotfix applied')
else:
print('pattern not found, skipped')
PY
if grep -qF "(0, sharp_1.default)(input).metadata()" "$MEDIA_REPO_JS" 2>/dev/null; then
msg_info "Patching media.repository.js"
sed -i '0,/(0, sharp_1\.default)(input)\.metadata()/s//(0, sharp_1.default)(input, { unlimited: true, limitInputPixels: false }).metadata()/' "$MEDIA_REPO_JS"
msg_ok "Patched media.repository.js"
fi
msg_ok "Patched media.repository.js"
mkdir -p /var/log/immich
touch /var/log/immich/{web.log,ml.log}
@@ -537,6 +526,7 @@ MACHINE_LEARNING_CACHE_FOLDER=${INSTALL_DIR}/cache
## - inference speed while reducing accuracy
## - Default is FP32
# MACHINE_LEARNING_OPENVINO_PRECISION=FP16
MACHINE_LEARNING_MODEL_REVISION=v2
IMMICH_MEDIA_LOCATION=${UPLOAD_DIR}
EOF

View File

@@ -20,15 +20,14 @@ $STD apt install -y \
openssl \
ffmpeg \
python3 \
python3-pip \
python3-dev \
python3-numpy \
redis-server
msg_ok "Installed Dependencies"
PG_VERSION="16" PG_MODULES="pgvector" setup_postgresql
PG_DB_NAME="kima" PG_DB_USER="kima" PG_DB_GRANT_SUPERUSER="true" setup_postgresql_db
NODE_VERSION="24" setup_nodejs
PYTHON_VERSION="3.13" setup_uv
msg_info "Configuring Redis"
systemctl enable -q --now redis-server
@@ -37,8 +36,8 @@ msg_ok "Configured Redis"
fetch_and_deploy_gh_release "kima-hub" "Chevron7Locked/kima-hub" "tarball"
msg_info "Installing Python Dependencies"
export PIP_BREAK_SYSTEM_PACKAGES=1
$STD pip3 install --no-cache-dir \
$STD uv venv --python 3.13 /opt/kima-hub/venv
$STD uv pip install --no-cache --python /opt/kima-hub/venv \
tensorflow \
essentia-tensorflow \
redis \
@@ -174,7 +173,7 @@ Environment=BATCH_SIZE=10
Environment=SLEEP_INTERVAL=5
Environment=NUM_WORKERS=2
Environment=THREADS_PER_WORKER=1
ExecStart=/usr/bin/python3 /opt/kima-hub/services/audio-analyzer/analyzer.py
ExecStart=/opt/kima-hub/venv/bin/python /opt/kima-hub/services/audio-analyzer/analyzer.py
Restart=on-failure
RestartSec=10
@@ -197,7 +196,7 @@ Environment=BACKEND_URL=http://localhost:3006
Environment=MUSIC_PATH=/music
Environment=SLEEP_INTERVAL=5
Environment=NUM_WORKERS=1
ExecStart=/usr/bin/python3 /opt/kima-hub/services/audio-analyzer-clap/analyzer.py
ExecStart=/opt/kima-hub/venv/bin/python /opt/kima-hub/services/audio-analyzer-clap/analyzer.py
Restart=on-failure
RestartSec=10