Compare commits

..
Author SHA1 Message Date
MickLesk 7dbdc713bd Immich: point immich-ml at the moved ml_start.sh and clear failed units
The update moves ml_start.sh into app/machine-learning, but only rewrote
immich-web's ExecStart, so older containers kept starting ML from
/opt/immich/ml_start.sh and failed with 203/EXEC. Rewrite immich-ml the same
way. A crash loop before the update can also leave both units rate-limited,
which makes the final restart fail; reset them first.
2026-10-09 08:09:40 +02:00
MickLesk 21c0910a5c Immich: survive an interrupted update and a failing ML build
An update cancelled midway leaves /opt/immich/app empty, and the next run
died at once on cd /opt/immich/app/bin to enable maintenance mode (#17796).
Maintenance mode is now only toggled when immich-admin exists.

uv sync fetching the ml-models git dependency failed with "Could not resolve
host" behind DNS filters such as AdGuard while DNS itself worked (#17797);
running uv one download at a time got through. Retries now do that.

If machine learning still cannot be built, the update no longer stops with
maintenance mode on and every service down: it finishes, starts the web
service, puts the previous version back into ~/.immich so the next update
retries, and exits with an error. Updates are also announced as taking
5-15 minutes, since the first report came from cancelling one that looked
stuck.
2026-10-09 08:01:48 +02:00
9 changed files with 3 additions and 413 deletions
-14
View File
@@ -559,20 +559,6 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
</details>
## 2026-10-09
### 🆕 New Scripts
- FoldingAtHome ([#17799](https://github.com/community-scripts/ProxmoxVE/pull/17799))
- LocalAI ([#17801](https://github.com/community-scripts/ProxmoxVE/pull/17801))
- Tvheadend ([#17800](https://github.com/community-scripts/ProxmoxVE/pull/17800))
### 🚀 Updated Scripts
- #### 🔧 Refactor
- Immich: survive an interrupted update and a failing ML build [@MickLesk](https://github.com/MickLesk) ([#17798](https://github.com/community-scripts/ProxmoxVE/pull/17798))
## 2026-10-08
### 🆕 New Scripts
-52
View File
@@ -1,52 +0,0 @@
#!/usr/bin/env bash
_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: MickLesk (CanbiZ) | Co-Author: 007hacky007
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/FoldingAtHome/fah-client-bastet
APP="FoldingAtHome"
var_tags="${var_tags:-science;distributed-computing}"
var_cpu="${var_cpu:-4}"
var_ram="${var_ram:-2048}"
var_disk="${var_disk:-8}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_arm64="${var_arm64:-yes}"
var_gpu="${var_gpu:-yes}"
var_unprivileged="${var_unprivileged:-1}"
export var_fah_token="${var_fah_token:-}"
export var_fah_machine_name="${var_fah_machine_name:-}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -f /usr/bin/fah-client ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
fetch_and_deploy_from_url "https://download.foldingathome.org/releases/public/fah-client/$(arch_resolve "debian-10-64bit" "debian-stable-arm64")/release/latest.deb"
msg_ok "Folding@home is at $(dpkg-query -W -f='${Version}' fah-client)"
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}Manage it from the Folding@home Web Control:${CL}"
echo -e "${GATEWAY}${BGN}https://app.foldingathome.org/${CL}"
echo -e "${INFO}${YW}The client starts paused - press Fold once the machine shows up in your account${CL}"
echo -e "${INFO}${YW}Account token and machine name are in /etc/fah-client/config.xml${CL}"
-63
View File
@@ -1,63 +0,0 @@
#!/usr/bin/env bash
_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: Bryan Lieberman (BryanCLieberman)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://localai.io
APP="LocalAI"
var_tags="${var_tags:-ai;llm;api}"
var_cpu="${var_cpu:-4}"
var_ram="${var_ram:-8192}"
var_disk="${var_disk:-30}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_arm64="${var_arm64:-yes}"
var_gpu="${var_gpu:-yes}"
var_unprivileged="${var_unprivileged:-1}"
# Values the install script accepts up front
export var_auth="${var_auth:-no}"
export var_api_key="${var_api_key:-}"
export var_port="${var_port:-8080}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d /opt/localai ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "localai" "mudler/LocalAI"; then
msg_info "Stopping Service"
systemctl stop localai
msg_ok "Stopped Service"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "localai" "mudler/LocalAI" "singlefile" "latest" "/opt/localai" "local-ai-v*-linux-$(arch_resolve amd64 arm64)"
msg_info "Starting Service"
systemctl start localai
msg_ok "Started Service"
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}:8080${CL}"
echo -e "${INFO}${YW}Install models from the gallery in the web UI or place GGUF files in /opt/localai_data/models${CL}"
+3 -31
View File
@@ -157,6 +157,8 @@ function update_script() {
sed -i '$a\PAPERLESS_ARCHIVE_FILE_GENERATION=never' "$PAPERLESS_CONF"
fi
fi
[[ -n "$(sed -n '/^PAPERLESS_CONSUMER_IGNORE_PATTERNS=/p' "$PAPERLESS_CONF")" ]] &&
msg_warn "PAPERLESS_CONSUMER_IGNORE_PATTERNS now uses regex patterns; please verify custom values."
[[ -n "$(sed -n '/^PAPERLESS_PRE_CONSUME_SCRIPT=/p;/^PAPERLESS_POST_CONSUME_SCRIPT=/p' "$PAPERLESS_CONF")" ]] &&
msg_warn "Pre/post consume scripts no longer receive positional arguments in v3; please verify custom scripts."
msg_ok "Migrated Paperless-ngx configuration"
@@ -170,9 +172,7 @@ function update_script() {
fi
for svc in consumer scheduler task-queue webserver; do
unit="/etc/systemd/system/paperless-${svc}.service"
[[ -f "$unit" ]] || continue
sed -i 's|uv run -- |uv run --no-sync -- |g' "$unit"
grep -q '^Restart=' "$unit" || sed -i '/^\[Service\]/a Restart=on-failure\nRestartSec=5' "$unit"
[[ -f "$unit" ]] && sed -i 's|uv run -- |uv run --no-sync -- |g' "$unit"
done
$STD systemctl daemon-reload
cd /opt/paperless
@@ -181,34 +181,6 @@ function update_script() {
$STD uv run -- python manage.py migrate
msg_ok "Updated Paperless-ngx"
if ((BRIDGE_UPDATE == 0)); then
IGNORE_FIXED="$(
/opt/paperless/.venv/bin/python - /opt/paperless/paperless.conf <<'EOF'
import json, re, sys
key = "PAPERLESS_CONSUMER_IGNORE_PATTERNS="
lines = open(sys.argv[1]).read().splitlines(True)
def is_glob(p):
if p.startswith("^") or p.endswith("$"):
return False
try:
return bool(re.search(p, "scan.pdf"))
except re.error:
return True
for i, line in enumerate(lines):
if line.startswith(key):
patterns = json.loads(line[len(key):].strip().strip("'"))
fixed = ["^" + re.escape(p).replace(r"\*", ".*").replace(r"\?", ".") + "$" if is_glob(p) else p for p in patterns]
if fixed != patterns:
lines[i] = key + json.dumps(fixed) + "\n"
print(json.dumps(fixed))
open(sys.argv[1], "w").writelines(lines)
EOF
)" || IGNORE_FIXED=""
[[ -n "$IGNORE_FIXED" ]] && msg_warn "Converted glob PAPERLESS_CONSUMER_IGNORE_PATTERNS to regex (required since v3): ${IGNORE_FIXED}"
fi
if ((BRIDGE_UPDATE == 0)) && [[ "$PAPERLESS_INSTALLED_VERSION" == "2.20.15" ]]; then
$STD apt -y purge libzbar0t64 libzbar0 2>/dev/null || true
$STD apt -y autoremove 2>/dev/null || true
-58
View File
@@ -1,58 +0,0 @@
#!/usr/bin/env bash
_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: Nicolas Pastorello (opastorello)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://tvheadend.org/ | Github: https://github.com/tvheadend/tvheadend
APP="Tvheadend"
var_tags="${var_tags:-media;pvr;tv;dvr}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-2048}"
var_disk="${var_disk:-8}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
#var_arm64="${var_arm64:-no}" # unset = ask the user; set yes/no only when verified
var_unprivileged="${var_unprivileged:-1}"
export var_admin_user="${var_admin_user:-admin}"
export var_admin_pass="${var_admin_pass:-$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | cut -c1-13)}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d /var/lib/tvheadend ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
msg_info "Updating Tvheadend"
$STD apt update
$STD apt install -y tvheadend
msg_ok "Updated Tvheadend"
msg_info "Restarting Service"
systemctl restart tvheadend
msg_ok "Restarted Service"
msg_ok "Updated successfully!"
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}:9981${CL}"
echo -e "${INFO}${YW}Admin Username: ${var_admin_user}${CL}"
echo -e "${INFO}${YW}Admin Password: ${var_admin_pass}${CL}"
-49
View File
@@ -1,49 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ) | Co-Author: 007hacky007
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/FoldingAtHome/fah-client-bastet
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
color
verb_ip6
catch_errors
setting_up_container
network_check
update_os
if [[ -z "${var_fah_token:-}" ]]; then
var_fah_token=$(prompt_password "Folding@home account token (Enter to skip):" "" 120)
fi
if [[ -z "${var_fah_machine_name:-}" ]]; then
var_fah_machine_name=$(prompt_input "Folding@home machine name:" "$(hostname)" 60)
fi
if [[ ${#var_fah_machine_name} -gt 64 || "$var_fah_machine_name" == *[\<\>\;\&\'\"]* ]]; then
msg_warn "Machine name must be 1-64 characters without <>;&'\" - using $(hostname)"
var_fah_machine_name=$(hostname)
fi
msg_info "Configuring Folding@home"
mkdir -p /etc/fah-client
cat <<EOF >/etc/fah-client/config.xml
<config>
<account-token v="${var_fah_token}"/>
<machine-name v="${var_fah_machine_name}"/>
</config>
EOF
msg_ok "Configured Folding@home"
fetch_and_deploy_from_url "https://download.foldingathome.org/releases/public/fah-client/$(arch_resolve "debian-10-64bit" "debian-stable-arm64")/release/latest.deb"
setup_hwaccel "fah-client"
# The client detects GPUs only at startup, so restart it after setup_hwaccel.
msg_info "Starting Folding@home"
systemctl enable -q fah-client
safe_service_restart fah-client
msg_ok "Started Folding@home"
motd_ssh
customize
cleanup_lxc
-92
View File
@@ -1,92 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: Bryan Lieberman (BryanCLieberman)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://localai.io
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 \
libgomp1 \
libopenblas0
msg_ok "Installed Dependencies"
setup_hwaccel
var_port="${var_port:-8080}"
var_auth="${var_auth:-no}"
var_api_key="${var_api_key:-}"
if [[ "$var_auth" == "yes" ]]; then
setup_postgresql
PG_DB_NAME="localai" PG_DB_USER="localai" setup_postgresql_db
fi
fetch_and_deploy_gh_release "localai" "mudler/LocalAI" "singlefile" "latest" "/opt/localai" "local-ai-v*-linux-$(arch_resolve amd64 arm64)"
msg_info "Configuring LocalAI"
mkdir -p /opt/localai_data/models /opt/localai_data/backends
cat <<EOF >/opt/localai.env
LOCALAI_ADDRESS=0.0.0.0:${var_port}
LOCALAI_DATA_PATH=/opt/localai_data
LOCALAI_MODELS_PATH=/opt/localai_data/models
LOCALAI_BACKENDS_PATH=/opt/localai_data/backends
LOCALAI_LOG_LEVEL=info
EOF
# LocalAI refuses to start on a wildcard bind with nothing to identify callers,
# and binding the wildcard is what makes the container reachable at all.
if [[ "$var_auth" == "yes" ]]; then
cat <<EOF >>/opt/localai.env
LOCALAI_AUTH=true
LOCALAI_AUTH_DATABASE_URL=postgres://${PG_DB_USER}:${PG_DB_PASS}@localhost/${PG_DB_NAME}
LOCALAI_REGISTRATION_MODE=approval
EOF
fi
# A static key grants admin access on its own, so when it is the only thing
# guarding the API, generate one rather than leaving the server open.
if [[ -z "$var_api_key" && "$var_auth" != "yes" ]]; then
var_api_key="sk-$(openssl rand -hex 24)"
{
echo "LocalAI Credentials"
echo "API Key: ${var_api_key}"
} >>~/localai.creds
fi
if [[ -n "$var_api_key" ]]; then
echo "LOCALAI_API_KEY=${var_api_key}" >>/opt/localai.env
else
echo "#LOCALAI_API_KEY=" >>/opt/localai.env
fi
chmod 600 /opt/localai.env
msg_ok "Configured LocalAI"
msg_info "Creating Service"
cat <<EOF >/etc/systemd/system/localai.service
[Unit]
Description=LocalAI Server
Wants=network-online.target
After=network-online.target
[Service]
Type=simple
User=root
WorkingDirectory=/opt/localai
EnvironmentFile=/opt/localai.env
ExecStart=/opt/localai/localai run
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
systemctl enable -q --now localai
msg_ok "Created Service"
motd_ssh
customize
cleanup_lxc
-8
View File
@@ -109,8 +109,6 @@ Requires=redis.service
[Service]
WorkingDirectory=/opt/paperless/src
ExecStart=uv run --no-sync -- celery --app paperless beat --loglevel INFO
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
@@ -125,8 +123,6 @@ After=postgresql.service
[Service]
WorkingDirectory=/opt/paperless/src
ExecStart=uv run --no-sync -- celery --app paperless worker --loglevel INFO
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
@@ -141,8 +137,6 @@ Requires=redis.service
WorkingDirectory=/opt/paperless/src
ExecStartPre=/bin/sleep 2
ExecStart=uv run --no-sync -- python manage.py document_consumer
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
@@ -159,8 +153,6 @@ Requires=redis.service
WorkingDirectory=/opt/paperless/src
#ExecStartPre=uv run --no-sync -- python manage.py document_index reindex --if-needed --no-progress-bar
ExecStart=uv run --no-sync -- granian --interface asginl --ws --loop uvloop "paperless.asgi:application"
Restart=on-failure
RestartSec=5
Environment=GRANIAN_HOST=::
Environment=GRANIAN_PORT=8000
Environment=GRANIAN_WORKERS=1
-46
View File
@@ -1,46 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: Nicolas Pastorello (opastorello)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://tvheadend.org/ | Github: https://github.com/tvheadend/tvheadend
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
color
verb_ip6
catch_errors
setting_up_container
network_check
update_os
setup_deb822_repo \
"tvheadend" \
"https://dl.cloudsmith.io/public/tvheadend/tvheadend/gpg.C6CC06BD69B430C6.key" \
"https://dl.cloudsmith.io/public/tvheadend/tvheadend/deb/debian" \
"$(get_os_info codename)" \
"main"
var_admin_user="${var_admin_user:-admin}"
var_admin_pass="${var_admin_pass:-$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | cut -c1-13)}"
msg_info "Installing Tvheadend"
echo "tvheadend tvheadend/admin_username string ${var_admin_user}" | debconf-set-selections
echo "tvheadend tvheadend/admin_password password ${var_admin_pass}" | debconf-set-selections
$STD apt install -y tvheadend
msg_ok "Installed Tvheadend"
msg_info "Starting Service"
systemctl enable -q --now tvheadend
msg_ok "Started Service"
msg_info "Saving Credentials"
cat <<EOF >~/tvheadend.creds
Tvheadend Admin Credentials
Username: ${var_admin_user}
Password: ${var_admin_pass}
EOF
msg_ok "Saved Credentials"
motd_ssh
customize
cleanup_lxc