Compare commits

..

1 Commits

Author SHA1 Message Date
CanbiZ (MickLesk)
c24c9996a3 fix(misc): use /usr/bin/install to prevent function shadowing
Bare 'install' can be shadowed when scripts define their own install() function, causing hangs. Use absolute path /usr/bin/install in alpine-tools.func and build.func to match the fix already applied to tools.func.
2026-03-26 10:03:31 +01:00
9 changed files with 13 additions and 355 deletions

View File

@@ -428,26 +428,6 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
## 2026-03-26
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- Immich: Bump to 2.6.2 | use start.sh in service, ensure DB_HOSTNAME in .env | Fix Rights Issue with ZFS Shares [@MickLesk](https://github.com/MickLesk) ([#13199](https://github.com/community-scripts/ProxmoxVE/pull/13199))
- #### ✨ New Features
- SparkyFitness: add garmin microservice as addon [@tomfrenzel](https://github.com/tomfrenzel) ([#12642](https://github.com/community-scripts/ProxmoxVE/pull/12642))
### 💾 Core
- #### 🐞 Bug Fixes
- tools.func: pin npm to 11.11.0 to work around Node.js 22.22.2 regression [@MickLesk](https://github.com/MickLesk) ([#13296](https://github.com/community-scripts/ProxmoxVE/pull/13296))
- #### 🔧 Refactor
- core: use /usr/bin/install to prevent function shadowing [@MickLesk](https://github.com/MickLesk) ([#13299](https://github.com/community-scripts/ProxmoxVE/pull/13299))
## 2026-03-25
### 🚀 Updated Scripts

View File

@@ -1,63 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/tphakala/birdnet-go
APP="BirdNET"
var_tags="${var_tags:-monitoring;ai;nature}"
var_cpu="${var_cpu:-4}"
var_ram="${var_ram:-2048}"
var_disk="${var_disk:-12}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
var_gpu="${var_gpu:-no}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -f /usr/local/bin/birdnet-go ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "birdnet" "tphakala/birdnet-go"; then
msg_info "Stopping Service"
systemctl stop birdnet
msg_ok "Stopped Service"
fetch_and_deploy_gh_release "birdnet" "tphakala/birdnet-go" "prebuild" "latest" "/opt/birdnet" "birdnet-go-linux-amd64.tar.gz"
msg_info "Deploying Binary"
cp /opt/birdnet/birdnet-go /usr/local/bin/birdnet-go
chmod +x /usr/local/bin/birdnet-go
cp -r /opt/birdnet/libtensorflowlite_c.so /usr/local/lib/ || true
ldconfig
msg_ok "Deployed Binary"
msg_info "Starting Service"
systemctl start birdnet
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 "${TAB}${GATEWAY}${BGN}http://${IP}:8080${CL}"

View File

@@ -109,7 +109,7 @@ EOF
msg_ok "Image-processing libraries up to date"
fi
RELEASE="v2.6.2"
RELEASE="v2.6.1"
if check_for_gh_release "Immich" "immich-app/immich" "${RELEASE}" "each release is tested individually before the version is updated. Please do not open issues for this"; then
if [[ $(cat ~/.immich) > "2.5.1" ]]; then
msg_info "Enabling Maintenance Mode"
@@ -214,10 +214,7 @@ EOF
cd "$SRC_DIR"/machine-learning
mkdir -p "$ML_DIR"
# chown excluding upload dir contents (may be a mount with restricted permissions)
chown immich:immich "$INSTALL_DIR"
find "$INSTALL_DIR" -maxdepth 1 -mindepth 1 ! -name upload -exec chown -R immich:immich {} +
chown immich:immich "${UPLOAD_DIR:-$INSTALL_DIR/upload}" 2>/dev/null || true
chown -R immich:immich "$INSTALL_DIR"
chown immich:immich ./uv.lock
export VIRTUAL_ENV="${ML_DIR}"/ml-venv
export UV_HTTP_TIMEOUT=300
@@ -266,20 +263,7 @@ EOF
[[ ! -f /usr/bin/immich ]] && ln -sf "$APP_DIR"/cli/bin/immich /usr/bin/immich
[[ ! -f /usr/bin/immich-admin ]] && ln -sf "$APP_DIR"/bin/immich-admin /usr/bin/immich-admin
if ! grep -q '^DB_HOSTNAME=' "$INSTALL_DIR"/.env; then
sed -i '/^DB_DATABASE_NAME/a DB_HOSTNAME=127.0.0.1' "$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
sed -i "s|^ExecStart=.*|ExecStart=${APP_DIR}/bin/start.sh|" /etc/systemd/system/immich-web.service
systemctl daemon-reload
fi
# chown excluding upload dir contents (may be a mount with restricted permissions)
chown immich:immich "$INSTALL_DIR"
find "$INSTALL_DIR" -maxdepth 1 -mindepth 1 ! -name upload -exec chown -R immich:immich {} +
chown immich:immich "${UPLOAD_DIR:-$INSTALL_DIR/upload}" 2>/dev/null || true
chown -R immich:immich "$INSTALL_DIR"
if [[ "${MAINT_MODE:-0}" == 1 ]]; then
msg_info "Disabling Maintenance Mode"
cd /opt/immich/app/bin

View File

@@ -1,56 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/tphakala/birdnet-go
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 \
libasound2 \
sox \
alsa-utils \
ffmpeg
msg_ok "Installed Dependencies"
fetch_and_deploy_gh_release "birdnet" "tphakala/birdnet-go" "prebuild" "latest" "/opt/birdnet" "birdnet-go-linux-amd64.tar.gz"
msg_info "Setting up BirdNET"
cp /opt/birdnet/birdnet-go /usr/local/bin/birdnet-go
chmod +x /usr/local/bin/birdnet-go
cp -r /opt/birdnet/libtensorflowlite_c.so /usr/local/lib/ || true
ldconfig
mkdir -p /opt/birdnet/data/clips
msg_ok "Set up BirdNET"
msg_info "Creating Service"
cat <<EOF >/etc/systemd/system/birdnet.service
[Unit]
Description=BirdNET
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=/opt/birdnet/data
ExecStart=/usr/local/bin/birdnet-go realtime
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl enable -q --now birdnet
msg_ok "Created Service"
motd_ssh
customize
cleanup_lxc

View File

@@ -295,7 +295,7 @@ ML_DIR="${APP_DIR}/machine-learning"
GEO_DIR="${INSTALL_DIR}/geodata"
mkdir -p {"${APP_DIR}","${UPLOAD_DIR}","${GEO_DIR}","${INSTALL_DIR}"/cache}
fetch_and_deploy_gh_release "Immich" "immich-app/immich" "tarball" "v2.6.2" "$SRC_DIR"
fetch_and_deploy_gh_release "Immich" "immich-app/immich" "tarball" "v2.6.1" "$SRC_DIR"
PNPM_VERSION="$(jq -r '.packageManager | split("@")[1] | split("+")[0]' ${SRC_DIR}/package.json)"
NODE_VERSION="24" NODE_MODULE="pnpm@${PNPM_VERSION}" setup_nodejs
@@ -344,11 +344,7 @@ msg_ok "Installed Immich Server, Web and Plugin Components"
cd "$SRC_DIR"/machine-learning
$STD useradd -U -s /usr/sbin/nologin -r -M -d "$INSTALL_DIR" immich
mkdir -p "$ML_DIR"
# chown excluding upload dir contents (may be a mount with restricted permissions)
chown immich:immich "$INSTALL_DIR"
find "$INSTALL_DIR" -maxdepth 1 -mindepth 1 ! -name upload -exec chown -R immich:immich {} +
chown immich:immich "$UPLOAD_DIR" 2>/dev/null || true
mkdir -p "$ML_DIR" && chown -R immich:immich "$INSTALL_DIR"
export VIRTUAL_ENV="${ML_DIR}/ml-venv"
export UV_HTTP_TIMEOUT=300
if [[ -f ~/.openvino ]]; then
@@ -473,7 +469,8 @@ User=immich
Group=immich
UMask=0077
WorkingDirectory=${APP_DIR}
ExecStart=${APP_DIR}/bin/start.sh
EnvironmentFile=${INSTALL_DIR}/.env
ExecStart=/usr/bin/node ${APP_DIR}/dist/main
Restart=on-failure
SyslogIdentifier=immich-web
StandardOutput=append:/var/log/immich/web.log
@@ -503,11 +500,7 @@ StandardError=append:/var/log/immich/ml.log
[Install]
WantedBy=multi-user.target
EOF
chown -R immich:immich /var/log/immich
# chown excluding upload dir contents (may be a mount with restricted permissions)
chown immich:immich "$INSTALL_DIR"
find "$INSTALL_DIR" -maxdepth 1 -mindepth 1 ! -name upload -exec chown -R immich:immich {} +
chown immich:immich "$UPLOAD_DIR" 2>/dev/null || true
chown -R immich:immich "$INSTALL_DIR" /var/log/immich
systemctl enable -q --now immich-ml.service immich-web.service
msg_ok "Modified user, created env file, scripts and services"

View File

@@ -40,7 +40,6 @@ sed \
-e "s|^SPARKY_FITNESS_SERVER_HOST=.*|SPARKY_FITNESS_SERVER_HOST=localhost|" \
-e "s|^SPARKY_FITNESS_SERVER_PORT=.*|SPARKY_FITNESS_SERVER_PORT=3010|" \
-e "s|^SPARKY_FITNESS_FRONTEND_URL=.*|SPARKY_FITNESS_FRONTEND_URL=http://${LOCAL_IP}:80|" \
-e "s|^GARMIN_MICROSERVICE_URL=.*|GARMIN_MICROSERVICE_URL=http://${LOCAL_IP}:8000|" \
-e "s|^SPARKY_FITNESS_API_ENCRYPTION_KEY=.*|SPARKY_FITNESS_API_ENCRYPTION_KEY=$(openssl rand -hex 32)|" \
-e "s|^BETTER_AUTH_SECRET=.*|BETTER_AUTH_SECRET=$(openssl rand -hex 32)|" \
"/etc/sparkyfitness/.env"

View File

@@ -6233,8 +6233,8 @@ function setup_nodejs() {
ensure_apt_working || return 1
# Pin npm to 11.11.0 to work around Node.js 22.22.2 regression (nodejs/node#62425)
$STD npm install -g npm@11.11.0 2>/dev/null || true
# Just update npm to latest
$STD npm install -g npm@latest 2>/dev/null || true
cache_installed_version "nodejs" "$NODE_VERSION"
msg_ok "Update Node.js $NODE_VERSION"
@@ -6298,12 +6298,12 @@ function setup_nodejs() {
return 1
fi
# Pin npm to 11.11.0 to work around Node.js 22.22.2 regression (nodejs/node#62425)
# Update to latest npm (with version check to avoid incompatibility)
local NPM_VERSION
NPM_VERSION=$(npm -v 2>/dev/null || echo "0")
if [[ "$NPM_VERSION" != "0" ]]; then
$STD npm install -g npm@11.11.0 2>/dev/null || {
msg_warn "Failed to update npm to 11.11.0 (continuing with bundled npm $NPM_VERSION)"
$STD npm install -g npm@latest 2>/dev/null || {
msg_warn "Failed to update npm to latest version (continuing with bundled npm $NPM_VERSION)"
}
fi

View File

@@ -1,173 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: Tom Frenzel (tomfrenzel)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/CodeWithCJ/SparkyFitness
if ! command -v curl &>/dev/null; then
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
apt-get update >/dev/null 2>&1
apt-get install -y curl >/dev/null 2>&1
fi
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/error_handler.func)
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "sparkyfitness-garmin" "addon"
# Enable error handling
set -Eeuo pipefail
trap 'error_handler' ERR
load_functions
# ==============================================================================
# CONFIGURATION
# ==============================================================================
APP="SparkyFitness Garmin Microservice"
APP_TYPE="addon"
INSTALL_PATH="/opt/sparkyfitness-garmin"
CONFIG_PATH="/etc/sparkyfitness-garmin/.env"
SERVICE_PATH="/etc/systemd/system/sparkyfitness-garmin.service"
DEFAULT_PORT=8000
# ==============================================================================
# OS DETECTION
# ==============================================================================
if ! grep -qE 'ID=debian|ID=ubuntu' /etc/os-release 2>/dev/null; then
echo -e "${CROSS} Unsupported OS detected. This script only supports Debian and Ubuntu."
exit 238
fi
# ==============================================================================
# SparkyFitness LXC DETECTION
# ==============================================================================
if [[ ! -d /opt/sparkyfitness ]]; then
echo -e "${CROSS} No SparkyFitness installation detected. This addon must be installed within a container that already has SparkyFitness installed."
exit 238
fi
# ==============================================================================
# UNINSTALL
# ==============================================================================
function uninstall() {
msg_info "Uninstalling ${APP}"
systemctl disable --now sparkyfitness-garmin.service &>/dev/null || true
rm -rf "$SERVICE_PATH" "$CONFIG_PATH" "$INSTALL_PATH" ~/.sparkyfitness-garmin
msg_ok "${APP} has been uninstalled"
}
# ==============================================================================
# UPDATE
# ==============================================================================
function update() {
if check_for_gh_release "sparkyfitness-garmin" "CodeWithCJ/SparkyFitness"; then
PYTHON_VERSION="3.13" setup_uv
msg_info "Stopping service"
systemctl stop sparkyfitness-garmin.service &>/dev/null || true
msg_ok "Stopped service"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "sparkyfitness-garmin" "CodeWithCJ/SparkyFitness" "tarball" "latest" $INSTALL_PATH
msg_info "Starting service"
systemctl start sparkyfitness-garmin
msg_ok "Started service"
msg_ok "Updated successfully"
exit
fi
}
# ==============================================================================
# INSTALL
# ==============================================================================
function install() {
PYTHON_VERSION="3.13" setup_uv
fetch_and_deploy_gh_release "sparkyfitness-garmin" "CodeWithCJ/SparkyFitness" "tarball" "latest" $INSTALL_PATH
msg_info "Setting up ${APP}"
mkdir -p "/etc/sparkyfitness-garmin"
cp "/opt/sparkyfitness-garmin/docker/.env.example" $CONFIG_PATH
cd $INSTALL_PATH/SparkyFitnessGarmin
$STD uv venv --clear .venv
$STD uv pip install -r requirements.txt
sed -i -e "s|^#\?GARMIN_MICROSERVICE_URL=.*|GARMIN_MICROSERVICE_URL=http://${LOCAL_IP}:${DEFAULT_PORT}|" $CONFIG_PATH
cat <<EOF >/etc/systemd/system/sparkyfitness-garmin.service
[Unit]
Description=${APP}
After=network.target sparkyfitness-server.service
Requires=sparkyfitness-server.service
[Service]
Type=simple
WorkingDirectory=$INSTALL_PATH/SparkyFitnessGarmin
EnvironmentFile=$CONFIG_PATH
ExecStart=$INSTALL_PATH/SparkyFitnessGarmin/.venv/bin/python3 -m uvicorn main:app --host 0.0.0.0 --port ${DEFAULT_PORT}
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl enable -q --now sparkyfitness-garmin
msg_ok "Set up ${APP} - reachable at http://${LOCAL_IP}:${DEFAULT_PORT}"
msg_ok "You might need to update the GARMIN_MICROSERVICE_URL in your SparkyFitness .env file to http://${LOCAL_IP}:${DEFAULT_PORT}"
}
# ==============================================================================
# MAIN
# ==============================================================================
header_info
ensure_usr_local_bin_persist
get_lxc_ip
# Handle type=update (called from update script)
if [[ "${type:-}" == "update" ]]; then
if [[ -d "$INSTALL_PATH" ]]; then
update
else
msg_error "${APP} is not installed. Nothing to update."
exit 233
fi
exit 0
fi
# Check if already installed
if [[ -d "$INSTALL_PATH" && -n "$(ls -A "$INSTALL_PATH" 2>/dev/null)" ]]; then
msg_warn "${APP} is already installed."
echo ""
echo -n "${TAB}Uninstall ${APP}? (y/N): "
read -r uninstall_prompt
if [[ "${uninstall_prompt,,}" =~ ^(y|yes)$ ]]; then
uninstall
exit 0
fi
echo -n "${TAB}Update ${APP}? (y/N): "
read -r update_prompt
if [[ "${update_prompt,,}" =~ ^(y|yes)$ ]]; then
update
exit 0
fi
msg_warn "No action selected. Exiting."
exit 0
fi
# Fresh installation
msg_warn "${APP} is not installed."
echo ""
echo -e "${TAB}${INFO} This will install:"
echo -e "${TAB} - UV (Python Version Manager)"
echo -e "${TAB} - SparkyFitness Garmin Microservice"
echo ""
echo -n "${TAB}Install ${APP}? (y/N): "
read -r install_prompt
if [[ "${install_prompt,,}" =~ ^(y|yes)$ ]]; then
install
else
msg_warn "Installation cancelled. Exiting."
exit 0
fi

View File

@@ -1,6 +0,0 @@
_____ __ _______ __ ______ _ __ ____ _
/ ___/____ ____ ______/ /____ __/ ____(_) /_____ ___ __________ / ____/___ __________ ___ (_)___ / |/ (_)_____________ ________ ______ __(_)_______
\__ \/ __ \/ __ `/ ___/ //_/ / / / /_ / / __/ __ \/ _ \/ ___/ ___/ / / __/ __ `/ ___/ __ `__ \/ / __ \ / /|_/ / / ___/ ___/ __ \/ ___/ _ \/ ___/ | / / / ___/ _ \
___/ / /_/ / /_/ / / / ,< / /_/ / __/ / / /_/ / / / __(__ |__ ) / /_/ / /_/ / / / / / / / / / / / / / / / / / /__/ / / /_/ (__ ) __/ / | |/ / / /__/ __/
/____/ .___/\__,_/_/ /_/|_|\__, /_/ /_/\__/_/ /_/\___/____/____/ \____/\__,_/_/ /_/ /_/ /_/_/_/ /_/ /_/ /_/_/\___/_/ \____/____/\___/_/ |___/_/\___/\___/
/_/ /____/