mirror of
https://github.com/community-scripts/ProxmoxVE.git
synced 2026-05-20 15:34:58 +02:00
Compare commits
1 Commits
fix/meilis
...
fix/rustde
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
044d4dc238 |
57
CHANGELOG.md
57
CHANGELOG.md
@@ -458,63 +458,6 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
|
|||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## 2026-05-08
|
|
||||||
|
|
||||||
### 🚀 Updated Scripts
|
|
||||||
|
|
||||||
- #### 🐞 Bug Fixes
|
|
||||||
|
|
||||||
- fix(homepage): fix ERR_PNPM_IGNORED_BUILDS error [@Sergih28](https://github.com/Sergih28) ([#14315](https://github.com/community-scripts/ProxmoxVE/pull/14315))
|
|
||||||
|
|
||||||
- #### ✨ New Features
|
|
||||||
|
|
||||||
- tools.func: add setup_nltk as new function [@MickLesk](https://github.com/MickLesk) ([#14314](https://github.com/community-scripts/ProxmoxVE/pull/14314))
|
|
||||||
|
|
||||||
## 2026-05-07
|
|
||||||
|
|
||||||
### 🚀 Updated Scripts
|
|
||||||
|
|
||||||
- #### 🐞 Bug Fixes
|
|
||||||
|
|
||||||
- termix: create /tmp/nginx before nginx -t [@MickLesk](https://github.com/MickLesk) ([#14312](https://github.com/community-scripts/ProxmoxVE/pull/14312))
|
|
||||||
- The Lounge: Fix service not starting automaticaly [@tremor021](https://github.com/tremor021) ([#14311](https://github.com/community-scripts/ProxmoxVE/pull/14311))
|
|
||||||
- netbird-lxc: fix installation check [@MickLesk](https://github.com/MickLesk) ([#14309](https://github.com/community-scripts/ProxmoxVE/pull/14309))
|
|
||||||
- databasus: Backup and secure configuration file [@MickLesk](https://github.com/MickLesk) ([#14308](https://github.com/community-scripts/ProxmoxVE/pull/14308))
|
|
||||||
- vm: update disk image URL for Ubuntu 25.04 [@MickLesk](https://github.com/MickLesk) ([#14290](https://github.com/community-scripts/ProxmoxVE/pull/14290))
|
|
||||||
|
|
||||||
- #### ✨ New Features
|
|
||||||
|
|
||||||
- pangolin: bump version to 1.18.3 [@MickLesk](https://github.com/MickLesk) ([#14297](https://github.com/community-scripts/ProxmoxVE/pull/14297))
|
|
||||||
|
|
||||||
### 🗑️ Deleted Scripts
|
|
||||||
|
|
||||||
- Remove: LiteLLM [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#14294](https://github.com/community-scripts/ProxmoxVE/pull/14294))
|
|
||||||
|
|
||||||
### 💾 Core
|
|
||||||
|
|
||||||
- #### ✨ New Features
|
|
||||||
|
|
||||||
- update-apps: some improvements [@MickLesk](https://github.com/MickLesk) ([#14275](https://github.com/community-scripts/ProxmoxVE/pull/14275))
|
|
||||||
|
|
||||||
## 2026-05-06
|
|
||||||
|
|
||||||
### 🆕 New Scripts
|
|
||||||
|
|
||||||
- Hoodik ([#14279](https://github.com/community-scripts/ProxmoxVE/pull/14279))
|
|
||||||
|
|
||||||
### 🚀 Updated Scripts
|
|
||||||
|
|
||||||
- #### 🐞 Bug Fixes
|
|
||||||
|
|
||||||
- Pelican-Panel: create backup subdirectory before copying storage [@MickLesk](https://github.com/MickLesk) ([#14274](https://github.com/community-scripts/ProxmoxVE/pull/14274))
|
|
||||||
- Rustdeskserver: remove redundant else with undefined RELEASE var [@MickLesk](https://github.com/MickLesk) ([#14272](https://github.com/community-scripts/ProxmoxVE/pull/14272))
|
|
||||||
|
|
||||||
### 🧰 Tools
|
|
||||||
|
|
||||||
- #### 🔧 Refactor
|
|
||||||
|
|
||||||
- AdguardHome-Sync replace ifconfig with hostname -I for IP detection [@MickLesk](https://github.com/MickLesk) ([#14273](https://github.com/community-scripts/ProxmoxVE/pull/14273))
|
|
||||||
|
|
||||||
## 2026-05-05
|
## 2026-05-05
|
||||||
|
|
||||||
### 🆕 New Scripts
|
### 🆕 New Scripts
|
||||||
|
|||||||
@@ -35,8 +35,6 @@ function update_script() {
|
|||||||
msg_ok "Stopped Databasus"
|
msg_ok "Stopped Databasus"
|
||||||
|
|
||||||
msg_info "Backing up Configuration"
|
msg_info "Backing up Configuration"
|
||||||
[[ ! -f /.env && -f /opt/databasus/.env ]] && cp /opt/databasus/.env /.env
|
|
||||||
chmod 600 /.env
|
|
||||||
cp /.env /opt/databasus.env.bak
|
cp /.env /opt/databasus.env.bak
|
||||||
chmod 600 /opt/databasus.env.bak
|
chmod 600 /opt/databasus.env.bak
|
||||||
msg_ok "Backed up Configuration"
|
msg_ok "Backed up Configuration"
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
__ __ ___ __
|
|
||||||
/ / / /___ ____ ____/ (_) /__
|
|
||||||
/ /_/ / __ \/ __ \/ __ / / //_/
|
|
||||||
/ __ / /_/ / /_/ / /_/ / / ,<
|
|
||||||
/_/ /_/\____/\____/\__,_/_/_/|_|
|
|
||||||
|
|
||||||
6
ct/headers/litellm
Normal file
6
ct/headers/litellm
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
__ _ __ __ __ __ ___
|
||||||
|
/ / (_) /____ / / / / / |/ /
|
||||||
|
/ / / / __/ _ \/ / / / / /|_/ /
|
||||||
|
/ /___/ / /_/ __/ /___/ /___/ / / /
|
||||||
|
/_____/_/\__/\___/_____/_____/_/ /_/
|
||||||
|
|
||||||
@@ -54,7 +54,6 @@ function update_script() {
|
|||||||
msg_info "Updating Homepage (Patience)"
|
msg_info "Updating Homepage (Patience)"
|
||||||
RELEASE=$(get_latest_github_release "gethomepage/homepage")
|
RELEASE=$(get_latest_github_release "gethomepage/homepage")
|
||||||
cd /opt/homepage
|
cd /opt/homepage
|
||||||
echo 'onlyBuiltDependencies=*' >> .npmrc
|
|
||||||
$STD pnpm install
|
$STD pnpm install
|
||||||
$STD pnpm update --no-save caniuse-lite
|
$STD pnpm update --no-save caniuse-lite
|
||||||
export NEXT_PUBLIC_VERSION="v$RELEASE"
|
export NEXT_PUBLIC_VERSION="v$RELEASE"
|
||||||
|
|||||||
64
ct/hoodik.sh
64
ct/hoodik.sh
@@ -1,64 +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/hudikhq/hoodik
|
|
||||||
|
|
||||||
APP="Hoodik"
|
|
||||||
var_tags="${var_tags:-cloud;storage}"
|
|
||||||
var_cpu="${var_cpu:-1}"
|
|
||||||
var_ram="${var_ram:-1024}"
|
|
||||||
var_disk="${var_disk:-5}"
|
|
||||||
var_os="${var_os:-debian}"
|
|
||||||
var_version="${var_version:-13}"
|
|
||||||
var_unprivileged="${var_unprivileged:-1}"
|
|
||||||
|
|
||||||
header_info "$APP"
|
|
||||||
variables
|
|
||||||
color
|
|
||||||
catch_errors
|
|
||||||
|
|
||||||
function update_script() {
|
|
||||||
header_info
|
|
||||||
check_container_storage
|
|
||||||
check_container_resources
|
|
||||||
|
|
||||||
if [[ ! -f /opt/hoodik/hoodik ]]; then
|
|
||||||
msg_error "No ${APP} Installation Found!"
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
|
|
||||||
if check_for_gh_release "hoodik" "hudikhq/hoodik"; then
|
|
||||||
msg_info "Stopping Service"
|
|
||||||
systemctl stop hoodik
|
|
||||||
msg_ok "Stopped Service"
|
|
||||||
|
|
||||||
msg_info "Backing up Configuration"
|
|
||||||
cp /opt/hoodik/.env /opt/hoodik.env.bak
|
|
||||||
msg_ok "Backed up Configuration"
|
|
||||||
|
|
||||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "hoodik" "hudikhq/hoodik" "prebuild" "latest" "/opt/hoodik" "*x86_64.tar.gz"
|
|
||||||
|
|
||||||
msg_info "Restoring Configuration"
|
|
||||||
cp /opt/hoodik.env.bak /opt/hoodik/.env
|
|
||||||
rm -f /opt/hoodik.env.bak
|
|
||||||
msg_ok "Restored Configuration"
|
|
||||||
|
|
||||||
msg_info "Starting Service"
|
|
||||||
systemctl start hoodik
|
|
||||||
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}:5443/auth/register${CL}"
|
|
||||||
67
ct/litellm.sh
Normal file
67
ct/litellm.sh
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
#!/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: stout01
|
||||||
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||||
|
# Source: https://github.com/BerriAI/litellm
|
||||||
|
|
||||||
|
APP="LiteLLM"
|
||||||
|
var_tags="${var_tags:-ai;interface}"
|
||||||
|
var_cpu="${var_cpu:-2}"
|
||||||
|
var_ram="${var_ram:-2048}"
|
||||||
|
var_disk="${var_disk:-4}"
|
||||||
|
var_os="${var_os:-debian}"
|
||||||
|
var_version="${var_version:-13}"
|
||||||
|
var_unprivileged="${var_unprivileged:-1}"
|
||||||
|
|
||||||
|
header_info "$APP"
|
||||||
|
variables
|
||||||
|
color
|
||||||
|
catch_errors
|
||||||
|
|
||||||
|
function update_script() {
|
||||||
|
header_info
|
||||||
|
check_container_storage
|
||||||
|
check_container_resources
|
||||||
|
|
||||||
|
if [[ ! -f /etc/systemd/system/litellm.service ]]; then
|
||||||
|
msg_error "No ${APP} Installation Found!"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
msg_info "Stopping Service"
|
||||||
|
systemctl stop litellm
|
||||||
|
msg_ok "Stopped Service"
|
||||||
|
|
||||||
|
VENV_PATH="/opt/litellm/.venv"
|
||||||
|
PYTHON_VERSION="3.13" USE_UVX="YES" setup_uv
|
||||||
|
|
||||||
|
msg_info "Updating LiteLLM"
|
||||||
|
$STD "$VENV_PATH/bin/python" -m pip install --upgrade litellm[proxy] prisma
|
||||||
|
$STD "$VENV_PATH/bin/prisma" generate
|
||||||
|
msg_ok "LiteLLM updated"
|
||||||
|
|
||||||
|
msg_info "Updating DB Schema"
|
||||||
|
$STD /opt/litellm/.venv/bin/litellm --config /opt/litellm/litellm.yaml --use_prisma_db_push --skip_server_startup
|
||||||
|
msg_ok "DB Schema Updated"
|
||||||
|
|
||||||
|
msg_info "Updating Service"
|
||||||
|
sed -i 's|ExecStart=uv --directory=/opt/litellm run litellm|ExecStart=/opt/litellm/.venv/bin/litellm|' /etc/systemd/system/litellm.service
|
||||||
|
systemctl daemon-reload
|
||||||
|
msg_ok "Updated Service"
|
||||||
|
|
||||||
|
msg_info "Starting Service"
|
||||||
|
systemctl start litellm
|
||||||
|
msg_ok "Started 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 "${TAB}${GATEWAY}${BGN}http://${IP}:4000${CL}"
|
||||||
@@ -81,7 +81,11 @@ STARTEOF
|
|||||||
cp -r /opt/mealie/frontend/dist/* /opt/mealie/mealie/frontend/
|
cp -r /opt/mealie/frontend/dist/* /opt/mealie/mealie/frontend/
|
||||||
msg_ok "Copied Frontend"
|
msg_ok "Copied Frontend"
|
||||||
|
|
||||||
setup_nltk "averaged_perceptron_tagger_eng" "/nltk_data"
|
msg_info "Updating NLTK Data"
|
||||||
|
mkdir -p /nltk_data/
|
||||||
|
cd /opt/mealie
|
||||||
|
$STD uv run python -m nltk.downloader -d /nltk_data averaged_perceptron_tagger_eng
|
||||||
|
msg_ok "Updated NLTK Data"
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
systemctl start mealie
|
systemctl start mealie
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ function update_script() {
|
|||||||
check_container_storage
|
check_container_storage
|
||||||
check_container_resources
|
check_container_resources
|
||||||
|
|
||||||
if [[ ! -d /var/lib/netbird/ ]]; then
|
if [[ ! -f /etc/netbird/config.json ]]; then
|
||||||
msg_error "No ${APP} Installation Found!"
|
msg_error "No ${APP} Installation Found!"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
|
|||||||
# Source: https://pangolin.net/ | Github: https://github.com/fosrl/pangolin
|
# Source: https://pangolin.net/ | Github: https://github.com/fosrl/pangolin
|
||||||
|
|
||||||
APP="Pangolin"
|
APP="Pangolin"
|
||||||
PANGOLIN_VERSION="${PANGOLIN_VERSION:-1.18.3}"
|
PANGOLIN_VERSION="${PANGOLIN_VERSION:-1.18.2}"
|
||||||
var_tags="${var_tags:-proxy}"
|
var_tags="${var_tags:-proxy}"
|
||||||
var_cpu="${var_cpu:-2}"
|
var_cpu="${var_cpu:-2}"
|
||||||
var_ram="${var_ram:-4096}"
|
var_ram="${var_ram:-4096}"
|
||||||
|
|||||||
@@ -164,7 +164,13 @@ function update_script() {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
setup_nltk "snowball_data stopwords punkt_tab" "/usr/share/nltk_data"
|
msg_info "Updating NLTK Data"
|
||||||
|
cd /opt/paperless
|
||||||
|
$STD uv run python -m nltk.downloader -d /usr/share/nltk_data snowball_data
|
||||||
|
$STD uv run python -m nltk.downloader -d /usr/share/nltk_data stopwords
|
||||||
|
$STD uv run python -m nltk.downloader -d /usr/share/nltk_data punkt_tab ||
|
||||||
|
$STD uv run python -m nltk.downloader -d /usr/share/nltk_data punkt
|
||||||
|
msg_ok "Updated NLTK Data"
|
||||||
|
|
||||||
msg_info "Starting all Paperless-ngx Services"
|
msg_info "Starting all Paperless-ngx Services"
|
||||||
systemctl start paperless-consumer paperless-webserver paperless-scheduler paperless-task-queue
|
systemctl start paperless-consumer paperless-webserver paperless-scheduler paperless-task-queue
|
||||||
|
|||||||
@@ -46,7 +46,6 @@ function update_script() {
|
|||||||
msg_ok "Stopped Service"
|
msg_ok "Stopped Service"
|
||||||
|
|
||||||
cp -a /opt/pelican-panel/.env /opt/backup
|
cp -a /opt/pelican-panel/.env /opt/backup
|
||||||
mkdir -p /opt/backup/storage/app/
|
|
||||||
cp -a /opt/pelican-panel/storage/app/public /opt/backup/storage/app/
|
cp -a /opt/pelican-panel/storage/app/public /opt/backup/storage/app/
|
||||||
|
|
||||||
SQLITE_INSTALL=$(ls /opt/pelican-panel/database/*.sqlite 1>/dev/null 2>&1 && echo "true" || echo "false")
|
SQLITE_INSTALL=$(ls /opt/pelican-panel/database/*.sqlite 1>/dev/null 2>&1 && echo "true" || echo "false")
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ function update_script() {
|
|||||||
msg_ok "Stopped Service"
|
msg_ok "Stopped Service"
|
||||||
|
|
||||||
fetch_and_deploy_gh_release "threadfin-app" "threadfin/threadfin" "singlefile" "latest" "/opt/threadfin" "Threadfin_linux_amd64"
|
fetch_and_deploy_gh_release "threadfin-app" "threadfin/threadfin" "singlefile" "latest" "/opt/threadfin" "Threadfin_linux_amd64"
|
||||||
mv /opt/threadfin/threadfin-app /opt/threadfin/threadfin
|
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
systemctl start threadfin
|
systemctl start threadfin
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ msg_info "Installing Homepage (Patience)"
|
|||||||
mkdir -p /opt/homepage/config
|
mkdir -p /opt/homepage/config
|
||||||
cd /opt/homepage
|
cd /opt/homepage
|
||||||
cp /opt/homepage/src/skeleton/* /opt/homepage/config
|
cp /opt/homepage/src/skeleton/* /opt/homepage/config
|
||||||
echo 'onlyBuiltDependencies=*' >> .npmrc
|
|
||||||
$STD pnpm install
|
$STD pnpm install
|
||||||
export NEXT_PUBLIC_VERSION="v$RELEASE"
|
export NEXT_PUBLIC_VERSION="v$RELEASE"
|
||||||
export NEXT_PUBLIC_REVISION="source"
|
export NEXT_PUBLIC_REVISION="source"
|
||||||
|
|||||||
@@ -1,58 +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/hudikhq/hoodik
|
|
||||||
|
|
||||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
|
||||||
color
|
|
||||||
verb_ip6
|
|
||||||
catch_errors
|
|
||||||
setting_up_container
|
|
||||||
network_check
|
|
||||||
update_os
|
|
||||||
|
|
||||||
fetch_and_deploy_gh_release "hoodik" "hudikhq/hoodik" "prebuild" "latest" "/opt/hoodik" "*x86_64.tar.gz"
|
|
||||||
|
|
||||||
msg_info "Configuring Hoodik"
|
|
||||||
mkdir -p /opt/hoodik_data
|
|
||||||
JWT_SECRET=$(openssl rand -base64 32 | tr -dc 'a-zA-Z0-9' | cut -c1-32)
|
|
||||||
cat <<EOF >/opt/hoodik/.env
|
|
||||||
DATA_DIR=/opt/hoodik_data
|
|
||||||
HTTP_PORT=5443
|
|
||||||
HTTP_ADDRESS=0.0.0.0
|
|
||||||
JWT_SECRET=${JWT_SECRET}
|
|
||||||
APP_URL=http://${LOCAL_IP}:5443
|
|
||||||
SSL_DISABLED=true
|
|
||||||
COOKIE_SECURE=false
|
|
||||||
COOKIE_HTTP_ONLY=false
|
|
||||||
MAILER_TYPE=none
|
|
||||||
RUST_LOG=hoodik=info,error=info
|
|
||||||
EOF
|
|
||||||
msg_ok "Configured Hoodik"
|
|
||||||
|
|
||||||
msg_info "Creating Service"
|
|
||||||
cat <<EOF >/etc/systemd/system/hoodik.service
|
|
||||||
[Unit]
|
|
||||||
Description=Hoodik - Encrypted File Storage
|
|
||||||
After=network.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=simple
|
|
||||||
User=root
|
|
||||||
WorkingDirectory=/opt/hoodik_data
|
|
||||||
EnvironmentFile=/opt/hoodik/.env
|
|
||||||
ExecStart=/opt/hoodik/hoodik
|
|
||||||
Restart=always
|
|
||||||
RestartSec=5
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
EOF
|
|
||||||
systemctl enable -q --now hoodik
|
|
||||||
msg_ok "Created Service"
|
|
||||||
|
|
||||||
motd_ssh
|
|
||||||
customize
|
|
||||||
cleanup_lxc
|
|
||||||
@@ -47,7 +47,8 @@ msg_info "Setting up KitchenOwl"
|
|||||||
cd /opt/kitchenowl/backend
|
cd /opt/kitchenowl/backend
|
||||||
$STD uv sync --no-dev
|
$STD uv sync --no-dev
|
||||||
sed -i 's/default=True/default=False/' /opt/kitchenowl/backend/wsgi.py
|
sed -i 's/default=True/default=False/' /opt/kitchenowl/backend/wsgi.py
|
||||||
setup_nltk "averaged_perceptron_tagger_eng" "/nltk_data"
|
mkdir -p /nltk_data
|
||||||
|
$STD uv run python -m nltk.downloader -d /nltk_data averaged_perceptron_tagger_eng
|
||||||
JWT_SECRET=$(openssl rand -hex 32)
|
JWT_SECRET=$(openssl rand -hex 32)
|
||||||
mkdir -p /opt/kitchenowl/data
|
mkdir -p /opt/kitchenowl/data
|
||||||
cat <<EOF >/opt/kitchenowl/kitchenowl.env
|
cat <<EOF >/opt/kitchenowl/kitchenowl.env
|
||||||
|
|||||||
65
install/litellm-install.sh
Normal file
65
install/litellm-install.sh
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Copyright (c) 2021-2026 community-scripts ORG
|
||||||
|
# Author: stout01
|
||||||
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||||
|
# Source: https://github.com/BerriAI/litellm
|
||||||
|
|
||||||
|
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 \
|
||||||
|
build-essential \
|
||||||
|
python3-dev
|
||||||
|
msg_ok "Installed Dependencies"
|
||||||
|
|
||||||
|
PG_VERSION="17" setup_postgresql
|
||||||
|
PG_DB_NAME="litellm_db" PG_DB_USER="litellm" setup_postgresql_db
|
||||||
|
PYTHON_VERSION="3.13" USE_UVX="YES" setup_uv
|
||||||
|
|
||||||
|
msg_info "Setting up Virtual Environment"
|
||||||
|
mkdir -p /opt/litellm
|
||||||
|
cd /opt/litellm
|
||||||
|
$STD uv venv --clear /opt/litellm/.venv
|
||||||
|
$STD /opt/litellm/.venv/bin/python -m ensurepip --upgrade
|
||||||
|
$STD /opt/litellm/.venv/bin/python -m pip install --upgrade pip
|
||||||
|
$STD /opt/litellm/.venv/bin/python -m pip install litellm[proxy] prisma
|
||||||
|
$STD /opt/litellm/.venv/bin/prisma generate
|
||||||
|
msg_ok "Installed LiteLLM"
|
||||||
|
|
||||||
|
msg_info "Configuring LiteLLM"
|
||||||
|
mkdir -p /opt
|
||||||
|
cat <<EOF >/opt/litellm/litellm.yaml
|
||||||
|
general_settings:
|
||||||
|
master_key: sk-1234
|
||||||
|
database_url: postgresql://$PG_DB_USER:$PG_DB_PASS@127.0.0.1:5432/$PG_DB_NAME
|
||||||
|
store_model_in_db: true
|
||||||
|
EOF
|
||||||
|
$STD /opt/litellm/.venv/bin/litellm --config /opt/litellm/litellm.yaml --use_prisma_db_push --skip_server_startup
|
||||||
|
msg_ok "Configured LiteLLM"
|
||||||
|
|
||||||
|
msg_info "Creating Service"
|
||||||
|
cat <<EOF >/etc/systemd/system/litellm.service
|
||||||
|
[Unit]
|
||||||
|
Description=LiteLLM
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
ExecStart=/opt/litellm/.venv/bin/litellm --config /opt/litellm/litellm.yaml
|
||||||
|
Restart=always
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
systemctl enable -q --now litellm
|
||||||
|
msg_ok "Created Service"
|
||||||
|
|
||||||
|
motd_ssh
|
||||||
|
customize
|
||||||
|
cleanup_lxc
|
||||||
@@ -55,7 +55,11 @@ mkdir -p /opt/mealie/mealie/frontend
|
|||||||
cp -r /opt/mealie/frontend/dist/* /opt/mealie/mealie/frontend/
|
cp -r /opt/mealie/frontend/dist/* /opt/mealie/mealie/frontend/
|
||||||
msg_ok "Copied Frontend"
|
msg_ok "Copied Frontend"
|
||||||
|
|
||||||
setup_nltk "averaged_perceptron_tagger_eng" "/nltk_data"
|
msg_info "Downloading NLTK Data"
|
||||||
|
mkdir -p /nltk_data/
|
||||||
|
cd /opt/mealie
|
||||||
|
$STD uv run python -m nltk.downloader -d /nltk_data averaged_perceptron_tagger_eng
|
||||||
|
msg_ok "Downloaded NLTK Data"
|
||||||
|
|
||||||
msg_info "Writing Environment File"
|
msg_info "Writing Environment File"
|
||||||
SECRET=$(openssl rand -hex 32)
|
SECRET=$(openssl rand -hex 32)
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ $STD apt install -y \
|
|||||||
msg_ok "Installed Dependencies"
|
msg_ok "Installed Dependencies"
|
||||||
|
|
||||||
NODE_VERSION="24" setup_nodejs
|
NODE_VERSION="24" setup_nodejs
|
||||||
PANGOLIN_VERSION="${PANGOLIN_VERSION:-1.18.3}"
|
PANGOLIN_VERSION="${PANGOLIN_VERSION:-1.18.2}"
|
||||||
fetch_and_deploy_gh_release "pangolin" "fosrl/pangolin" "tarball" "$PANGOLIN_VERSION"
|
fetch_and_deploy_gh_release "pangolin" "fosrl/pangolin" "tarball" "$PANGOLIN_VERSION"
|
||||||
fetch_and_deploy_gh_release "gerbil" "fosrl/gerbil" "singlefile" "latest" "/usr/bin" "gerbil_linux_amd64"
|
fetch_and_deploy_gh_release "gerbil" "fosrl/gerbil" "singlefile" "latest" "/usr/bin" "gerbil_linux_amd64"
|
||||||
fetch_and_deploy_gh_release "traefik" "traefik/traefik" "prebuild" "latest" "/usr/bin" "traefik_v*_linux_amd64.tar.gz"
|
fetch_and_deploy_gh_release "traefik" "traefik/traefik" "prebuild" "latest" "/usr/bin" "traefik_v*_linux_amd64.tar.gz"
|
||||||
|
|||||||
@@ -94,12 +94,18 @@ user.save()
|
|||||||
EOF
|
EOF
|
||||||
msg_ok "Set up admin Paperless-ngx User & Password"
|
msg_ok "Set up admin Paperless-ngx User & Password"
|
||||||
|
|
||||||
setup_nltk "snowball_data stopwords punkt_tab" "/usr/share/nltk_data"
|
msg_info "Installing Natural Language Toolkit (Patience)"
|
||||||
|
cd /opt/paperless
|
||||||
|
$STD uv run python -m nltk.downloader -d /usr/share/nltk_data snowball_data
|
||||||
|
$STD uv run python -m nltk.downloader -d /usr/share/nltk_data stopwords
|
||||||
|
$STD uv run python -m nltk.downloader -d /usr/share/nltk_data punkt_tab ||
|
||||||
|
$STD uv run python -m nltk.downloader -d /usr/share/nltk_data punkt
|
||||||
for policy_file in /etc/ImageMagick-6/policy.xml /etc/ImageMagick-7/policy.xml; do
|
for policy_file in /etc/ImageMagick-6/policy.xml /etc/ImageMagick-7/policy.xml; do
|
||||||
if [[ -f "$policy_file" ]]; then
|
if [[ -f "$policy_file" ]]; then
|
||||||
sed -i -e 's/rights="none" pattern="PDF"/rights="read|write" pattern="PDF"/' "$policy_file"
|
sed -i -e 's/rights="none" pattern="PDF"/rights="read|write" pattern="PDF"/' "$policy_file"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
msg_ok "Installed Natural Language Toolkit"
|
||||||
|
|
||||||
msg_info "Creating Services"
|
msg_info "Creating Services"
|
||||||
cat <<EOF >/etc/systemd/system/paperless-scheduler.service
|
cat <<EOF >/etc/systemd/system/paperless-scheduler.service
|
||||||
|
|||||||
@@ -100,7 +100,6 @@ sed -i 's|/app/html|/opt/termix/html|g' /etc/nginx/nginx.conf
|
|||||||
sed -i 's|/app/nginx|/opt/termix/nginx|g' /etc/nginx/nginx.conf
|
sed -i 's|/app/nginx|/opt/termix/nginx|g' /etc/nginx/nginx.conf
|
||||||
sed -i 's|listen ${PORT};|listen 80;|g' /etc/nginx/nginx.conf
|
sed -i 's|listen ${PORT};|listen 80;|g' /etc/nginx/nginx.conf
|
||||||
|
|
||||||
mkdir -p /tmp/nginx
|
|
||||||
rm -f /etc/nginx/sites-enabled/default
|
rm -f /etc/nginx/sites-enabled/default
|
||||||
nginx -t
|
nginx -t
|
||||||
systemctl reload nginx
|
systemctl reload nginx
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ network_check
|
|||||||
update_os
|
update_os
|
||||||
|
|
||||||
fetch_and_deploy_gh_release "thelounge" "thelounge/thelounge-deb" "binary"
|
fetch_and_deploy_gh_release "thelounge" "thelounge/thelounge-deb" "binary"
|
||||||
systemctl enable -q --now thelounge
|
|
||||||
|
|
||||||
motd_ssh
|
motd_ssh
|
||||||
customize
|
customize
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ $STD apt install -y \
|
|||||||
msg_ok "Installed Dependencies"
|
msg_ok "Installed Dependencies"
|
||||||
|
|
||||||
fetch_and_deploy_gh_release "threadfin-app" "threadfin/threadfin" "singlefile" "latest" "/opt/threadfin" "Threadfin_linux_amd64"
|
fetch_and_deploy_gh_release "threadfin-app" "threadfin/threadfin" "singlefile" "latest" "/opt/threadfin" "Threadfin_linux_amd64"
|
||||||
mv /opt/threadfin/threadfin-app /opt/threadfin/threadfin
|
|
||||||
|
|
||||||
msg_info "Creating Service"
|
msg_info "Creating Service"
|
||||||
cat <<EOF >/etc/systemd/system/threadfin.service
|
cat <<EOF >/etc/systemd/system/threadfin.service
|
||||||
|
|||||||
@@ -3230,10 +3230,6 @@ check_container_resources() {
|
|||||||
if [[ "$current_ram" -lt "$var_ram" ]] || [[ "$current_cpu" -lt "$var_cpu" ]]; then
|
if [[ "$current_ram" -lt "$var_ram" ]] || [[ "$current_cpu" -lt "$var_cpu" ]]; then
|
||||||
msg_warn "Under-provisioned: Required ${var_cpu} CPU/${var_ram}MB RAM, Current ${current_cpu} CPU/${current_ram}MB RAM"
|
msg_warn "Under-provisioned: Required ${var_cpu} CPU/${var_ram}MB RAM, Current ${current_cpu} CPU/${current_ram}MB RAM"
|
||||||
echo -e "${YWB}Please ensure that the ${APP} LXC is configured with at least ${var_cpu} vCPU and ${var_ram} MB RAM for the build process.${CL}\n"
|
echo -e "${YWB}Please ensure that the ${APP} LXC is configured with at least ${var_cpu} vCPU and ${var_ram} MB RAM for the build process.${CL}\n"
|
||||||
if is_unattended; then
|
|
||||||
msg_error "Aborted: under-provisioned LXC in unattended mode (${current_cpu} CPU/${current_ram}MB RAM < ${var_cpu} CPU/${var_ram}MB RAM)"
|
|
||||||
exit 113
|
|
||||||
fi
|
|
||||||
echo -ne "${INFO}${HOLD} May cause data loss! ${INFO} Continue update with under-provisioned LXC? <yes/No> "
|
echo -ne "${INFO}${HOLD} May cause data loss! ${INFO} Continue update with under-provisioned LXC? <yes/No> "
|
||||||
read -r prompt </dev/tty
|
read -r prompt </dev/tty
|
||||||
if [[ ! ${prompt,,} =~ ^(yes)$ ]]; then
|
if [[ ! ${prompt,,} =~ ^(yes)$ ]]; then
|
||||||
@@ -3257,10 +3253,6 @@ check_container_storage() {
|
|||||||
usage=$((100 * used_size / total_size))
|
usage=$((100 * used_size / total_size))
|
||||||
if ((usage > 80)); then
|
if ((usage > 80)); then
|
||||||
msg_warn "Storage is dangerously low (${usage}% used on /boot)"
|
msg_warn "Storage is dangerously low (${usage}% used on /boot)"
|
||||||
if is_unattended; then
|
|
||||||
msg_error "Aborted: storage too low in unattended mode (${usage}% used on /boot)"
|
|
||||||
exit 114
|
|
||||||
fi
|
|
||||||
echo -ne "Continue anyway? <y/N> "
|
echo -ne "Continue anyway? <y/N> "
|
||||||
read -r prompt </dev/tty
|
read -r prompt </dev/tty
|
||||||
if [[ ! ${prompt,,} =~ ^(y|yes)$ ]]; then
|
if [[ ! ${prompt,,} =~ ^(y|yes)$ ]]; then
|
||||||
|
|||||||
@@ -868,12 +868,6 @@ get_header() {
|
|||||||
# - Returns silently if header not available
|
# - Returns silently if header not available
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
header_info() {
|
header_info() {
|
||||||
# Guard against printing the header twice in the same session (e.g. when
|
|
||||||
# the ct script calls header_info at global scope AND again inside
|
|
||||||
# update_script()).
|
|
||||||
[[ "${_HEADER_SHOWN:-0}" == "1" ]] && return 0
|
|
||||||
_HEADER_SHOWN=1
|
|
||||||
|
|
||||||
local app_name=$(echo "${APP,,}" | tr -d ' ')
|
local app_name=$(echo "${APP,,}" | tr -d ' ')
|
||||||
local header_content
|
local header_content
|
||||||
|
|
||||||
|
|||||||
@@ -2095,10 +2095,10 @@ get_latest_gh_tag() {
|
|||||||
local count
|
local count
|
||||||
count=$(jq 'length' "$temp_file" 2>/dev/null || echo 0)
|
count=$(jq 'length' "$temp_file" 2>/dev/null || echo 0)
|
||||||
if [[ "$count" -gt 0 ]]; then
|
if [[ "$count" -gt 0 ]]; then
|
||||||
tag=$(jq -r '.[].ref' "$temp_file" |
|
tag=$(jq -r '.[].ref' "$temp_file" \
|
||||||
sed 's|^refs/tags/||' |
|
| sed 's|^refs/tags/||' \
|
||||||
sort -V |
|
| sort -V \
|
||||||
tail -n1)
|
| tail -n1)
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
# No prefix: just take the first (newest) tag from /tags
|
# No prefix: just take the first (newest) tag from /tags
|
||||||
@@ -7588,7 +7588,7 @@ function setup_meilisearch() {
|
|||||||
|
|
||||||
# Start meilisearch with --import-dump flag
|
# Start meilisearch with --import-dump flag
|
||||||
# This is a one-time import that happens during startup
|
# This is a one-time import that happens during startup
|
||||||
/usr/bin/meilisearch --config-file-path /etc/meilisearch.toml --import-dump "$DUMP_FILE" >/dev/null 2>&1 &
|
/usr/bin/meilisearch --config-file-path /etc/meilisearch.toml --import-dump "$DUMP_FILE" &
|
||||||
local MEILI_PID=$!
|
local MEILI_PID=$!
|
||||||
|
|
||||||
# Wait for meilisearch to become healthy (import happens during startup)
|
# Wait for meilisearch to become healthy (import happens during startup)
|
||||||
@@ -7611,7 +7611,6 @@ function setup_meilisearch() {
|
|||||||
|
|
||||||
# Stop the manual process
|
# Stop the manual process
|
||||||
kill $MEILI_PID 2>/dev/null || true
|
kill $MEILI_PID 2>/dev/null || true
|
||||||
wait $MEILI_PID 2>/dev/null || true
|
|
||||||
sleep 2
|
sleep 2
|
||||||
|
|
||||||
# Start via systemd for proper management
|
# Start via systemd for proper management
|
||||||
@@ -9440,73 +9439,3 @@ function fetch_and_deploy_gl_release() {
|
|||||||
msg_ok "Deployed: $app ($version)"
|
msg_ok "Deployed: $app ($version)"
|
||||||
rm -rf "$tmpdir"
|
rm -rf "$tmpdir"
|
||||||
}
|
}
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# Download NLTK data packages directly from GitHub, bypassing Python.
|
|
||||||
# Avoids CPU-instruction failures (SIGILL) on older hardware lacking AVX.
|
|
||||||
#
|
|
||||||
# Usage:
|
|
||||||
# setup_nltk "averaged_perceptron_tagger_eng" "/nltk_data"
|
|
||||||
# setup_nltk "snowball_data stopwords punkt_tab" "/usr/share/nltk_data"
|
|
||||||
#
|
|
||||||
# Parameters:
|
|
||||||
# $1 - Space-separated list of NLTK package IDs
|
|
||||||
# $2 - Target directory (default: /usr/share/nltk_data)
|
|
||||||
#
|
|
||||||
# Returns: 0 on success, non-zero if any package failed
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
function setup_nltk() {
|
|
||||||
local packages="${1:?setup_nltk requires at least one package name}"
|
|
||||||
local target_dir="${2:-/usr/share/nltk_data}"
|
|
||||||
local NLTK_INDEX_URL="https://raw.githubusercontent.com/nltk/nltk_data/gh-pages/index.xml"
|
|
||||||
local index_xml rc=0
|
|
||||||
|
|
||||||
ensure_dependencies unzip
|
|
||||||
|
|
||||||
index_xml=$(curl_with_retry "$NLTK_INDEX_URL" "-") || {
|
|
||||||
msg_error "Failed to fetch NLTK package index"
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
local pkg
|
|
||||||
for pkg in $packages; do
|
|
||||||
msg_info "Downloading NLTK: $pkg"
|
|
||||||
local pkg_line subdir pkg_url do_unzip tmp_zip
|
|
||||||
|
|
||||||
pkg_line=$(echo "$index_xml" | grep "id=\"${pkg}\"" | head -1)
|
|
||||||
if [[ -z "$pkg_line" ]]; then
|
|
||||||
msg_error "NLTK package not found in index: $pkg"
|
|
||||||
rc=1
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
subdir=$(echo "$pkg_line" | grep -oP 'subdir="\K[^"]+')
|
|
||||||
pkg_url=$(echo "$pkg_line" | grep -oP 'url="\K[^"]+')
|
|
||||||
do_unzip=$(echo "$pkg_line" | grep -oP 'unzip="\K[^"]+')
|
|
||||||
|
|
||||||
if [[ -z "$subdir" || -z "$pkg_url" ]]; then
|
|
||||||
msg_error "Could not parse NLTK index entry for: $pkg"
|
|
||||||
rc=1
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
mkdir -p "${target_dir}/${subdir}"
|
|
||||||
tmp_zip=$(mktemp --suffix=.zip)
|
|
||||||
|
|
||||||
if CURL_TIMEOUT=120 curl_with_retry "$pkg_url" "$tmp_zip"; then
|
|
||||||
if [[ "$do_unzip" == "1" ]]; then
|
|
||||||
$STD unzip -q -o "$tmp_zip" -d "${target_dir}/${subdir}/"
|
|
||||||
rm -f "$tmp_zip"
|
|
||||||
else
|
|
||||||
mv "$tmp_zip" "${target_dir}/${subdir}/${pkg}.zip"
|
|
||||||
fi
|
|
||||||
msg_ok "Downloaded NLTK: $pkg"
|
|
||||||
else
|
|
||||||
msg_error "Failed to download NLTK package: $pkg"
|
|
||||||
rm -f "$tmp_zip"
|
|
||||||
rc=1
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
return $rc
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ EOF
|
|||||||
# HELPER FUNCTIONS
|
# HELPER FUNCTIONS
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
get_ip() {
|
get_ip() {
|
||||||
hostname -I 2>/dev/null | awk '{print $1}' || ip -4 addr show scope global 2>/dev/null | awk '/inet / {print $2}' | cut -d/ -f1 | head -n1 || echo "127.0.0.1"
|
ifconfig | grep -v '127.0.0.1' | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -m1 -Eo '([0-9]*\.){3}[0-9]*' || echo "127.0.0.1"
|
||||||
}
|
}
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
|
|||||||
@@ -42,17 +42,6 @@ var_skip_confirm="${var_skip_confirm:-no}"
|
|||||||
# Options: "yes" | "no" | "" (empty = interactive prompt)
|
# Options: "yes" | "no" | "" (empty = interactive prompt)
|
||||||
var_auto_reboot="${var_auto_reboot:-}"
|
var_auto_reboot="${var_auto_reboot:-}"
|
||||||
|
|
||||||
# var_continue_on_error: Continue updating remaining containers if one update fails
|
|
||||||
# Options: "yes" | "no" (default: no = stop on first error)
|
|
||||||
# Note: containers with backups always attempt restore on failure regardless of this setting
|
|
||||||
var_continue_on_error="${var_continue_on_error:-no}"
|
|
||||||
|
|
||||||
# var_dry_run: Check for available updates without applying them
|
|
||||||
# Options: "yes" | "no" (default: no)
|
|
||||||
# Output: lists each container with current vs. latest version
|
|
||||||
# Note: requires the container to be running; does not modify any container
|
|
||||||
var_dry_run="${var_dry_run:-no}"
|
|
||||||
|
|
||||||
# var_tags: Optionally override the tags used for auto-detection
|
# var_tags: Optionally override the tags used for auto-detection
|
||||||
# Options: "community-script|proxmox-helper-scripts" (default)
|
# Options: "community-script|proxmox-helper-scripts" (default)
|
||||||
var_tags="${var_tags:-community-script|proxmox-helper-scripts}"
|
var_tags="${var_tags:-community-script|proxmox-helper-scripts}"
|
||||||
@@ -70,8 +59,6 @@ function export_config_json() {
|
|||||||
"var_unattended": "${var_unattended}",
|
"var_unattended": "${var_unattended}",
|
||||||
"var_skip_confirm": "${var_skip_confirm}",
|
"var_skip_confirm": "${var_skip_confirm}",
|
||||||
"var_auto_reboot": "${var_auto_reboot}",
|
"var_auto_reboot": "${var_auto_reboot}",
|
||||||
"var_continue_on_error": "${var_continue_on_error}",
|
|
||||||
"var_dry_run": "${var_dry_run}",
|
|
||||||
"var_tags": "${var_tags}"
|
"var_tags": "${var_tags}"
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
@@ -91,12 +78,10 @@ Environment Variables:
|
|||||||
var_backup Enable backup before update (yes/no)
|
var_backup Enable backup before update (yes/no)
|
||||||
var_backup_storage Storage location for backups
|
var_backup_storage Storage location for backups
|
||||||
var_container Container selection (all/all_running/all_stopped/101,102,...)
|
var_container Container selection (all/all_running/all_stopped/101,102,...)
|
||||||
var_unattended Run updates unattended (yes/no)
|
var_unattended Run updates unattended (yes/no)
|
||||||
var_skip_confirm Skip initial confirmation (yes/no)
|
var_skip_confirm Skip initial confirmation (yes/no)
|
||||||
var_auto_reboot Auto-reboot containers if required (yes/no)
|
var_auto_reboot Auto-reboot containers if required (yes/no)
|
||||||
var_continue_on_error Continue to next container on update failure (yes/no)
|
var_tags Optionally override auto-detection tags ("prod|smb|community-script")
|
||||||
var_dry_run Check for updates without applying them (yes/no)
|
|
||||||
var_tags Optionally override auto-detection tags ("prod|smb|community-script")
|
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
# Run interactively
|
# Run interactively
|
||||||
@@ -108,12 +93,6 @@ Examples:
|
|||||||
# Update specific containers without backup
|
# Update specific containers without backup
|
||||||
var_backup=no var_container=101,102,105 var_unattended=yes var_skip_confirm=yes $(basename "$0")
|
var_backup=no var_container=101,102,105 var_unattended=yes var_skip_confirm=yes $(basename "$0")
|
||||||
|
|
||||||
# Unattended cron-style: skip confirm, continue on error, no backup
|
|
||||||
var_backup=no var_container=all_running var_unattended=yes var_skip_confirm=yes var_continue_on_error=yes $(basename "$0")
|
|
||||||
|
|
||||||
# Dry-run: show available updates for all running containers without applying
|
|
||||||
var_container=all_running var_skip_confirm=yes var_dry_run=yes $(basename "$0")
|
|
||||||
|
|
||||||
# Export current configuration
|
# Export current configuration
|
||||||
$(basename "$0") --export-config
|
$(basename "$0") --export-config
|
||||||
EOF
|
EOF
|
||||||
@@ -152,62 +131,6 @@ function detect_service() {
|
|||||||
popd >/dev/null
|
popd >/dev/null
|
||||||
}
|
}
|
||||||
|
|
||||||
function dry_run_container() {
|
|
||||||
local container="$1"
|
|
||||||
local service="$2"
|
|
||||||
|
|
||||||
# Extract app name and source repo directly from check_for_gh_release call in the ct script
|
|
||||||
# Pattern: check_for_gh_release "appname" "owner/repo"
|
|
||||||
local check_line app_name app_lc source_repo
|
|
||||||
check_line=$(echo "$script" | grep -m1 'check_for_gh_release')
|
|
||||||
|
|
||||||
if [[ -z "$check_line" ]]; then
|
|
||||||
echo -e "${YW}[DRY-RUN]${CL} Container $container ($service): no check_for_gh_release found — skipping"
|
|
||||||
DRY_RUN_RESULT="no check_for_gh_release found — skipping"
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
app_name=$(echo "$check_line" | cut -d'"' -f2)
|
|
||||||
source_repo=$(echo "$check_line" | cut -d'"' -f4)
|
|
||||||
app_lc=$(echo "${app_name,,}" | tr -d ' ')
|
|
||||||
|
|
||||||
if [[ -z "$source_repo" || "$source_repo" != *"/"* ]]; then
|
|
||||||
echo -e "${YW}[DRY-RUN]${CL} Container $container ($service): cannot parse source repo — skipping"
|
|
||||||
DRY_RUN_RESULT="cannot parse source repo — skipping"
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Read installed version from container (stored by check_for_gh_release as ~/.<appname>)
|
|
||||||
local current_version
|
|
||||||
current_version=$(pct exec "$container" -- bash -c "cat \$HOME/.${app_lc} 2>/dev/null" 2>/dev/null || true)
|
|
||||||
current_version="${current_version#v}"
|
|
||||||
|
|
||||||
# Query latest release from GitHub API
|
|
||||||
local latest_version
|
|
||||||
latest_version=$(curl -sSL --max-time 10 \
|
|
||||||
-H 'Accept: application/vnd.github+json' \
|
|
||||||
-H 'X-GitHub-Api-Version: 2022-11-28' \
|
|
||||||
"https://api.github.com/repos/${source_repo}/releases/latest" 2>/dev/null |
|
|
||||||
grep '"tag_name"' | head -1 | cut -d'"' -f4 | sed 's/^v//')
|
|
||||||
|
|
||||||
if [[ -z "$latest_version" ]]; then
|
|
||||||
echo -e "${YW}[DRY-RUN]${CL} Container $container ($service): cannot fetch latest version from $source_repo"
|
|
||||||
DRY_RUN_RESULT="cannot fetch latest version from $source_repo"
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -z "$current_version" ]]; then
|
|
||||||
echo -e "${BL}[DRY-RUN]${CL} Container $container ($service): installed version unknown, latest: ${latest_version} (${source_repo})"
|
|
||||||
DRY_RUN_RESULT="version unknown — latest: ${latest_version}"
|
|
||||||
elif [[ "$current_version" == "$latest_version" ]]; then
|
|
||||||
echo -e "${GN}[DRY-RUN]${CL} Container $container ($service): up to date (${current_version})"
|
|
||||||
DRY_RUN_RESULT="up to date (${current_version})"
|
|
||||||
else
|
|
||||||
echo -e "${YW}[DRY-RUN]${CL} Container $container ($service): update available ${current_version} → ${latest_version}"
|
|
||||||
DRY_RUN_RESULT="update available ${current_version} → ${latest_version}"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function backup_container() {
|
function backup_container() {
|
||||||
msg_info "Creating backup for container $1"
|
msg_info "Creating backup for container $1"
|
||||||
vzdump $1 --compress zstd --storage $STORAGE_CHOICE -notes-template "{{guestname}} - community-scripts backup updater" >/dev/null 2>&1
|
vzdump $1 --compress zstd --storage $STORAGE_CHOICE -notes-template "{{guestname}} - community-scripts backup updater" >/dev/null 2>&1
|
||||||
@@ -246,32 +169,8 @@ END {
|
|||||||
' /etc/pve/storage.cfg)
|
' /etc/pve/storage.cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
# Structured result tracking for the final summary report
|
|
||||||
# Each entry: "CTID|service|STATUS|details"
|
|
||||||
declare -a UPDATE_RESULTS=()
|
|
||||||
function log_result() {
|
|
||||||
# log_result <ctid> <service> <STATUS> <details>
|
|
||||||
UPDATE_RESULTS+=("${1}|${2}|${3}|${4}")
|
|
||||||
}
|
|
||||||
|
|
||||||
header_info
|
header_info
|
||||||
|
|
||||||
# =============================================================================
|
|
||||||
# LOGGING SETUP
|
|
||||||
# Key events are written directly to a timestamped log file under
|
|
||||||
# /usr/local/community-scripts/update_apps/ — this avoids any stdout
|
|
||||||
# redirection that would break interactive spinners or whiptail dialogs.
|
|
||||||
# The full summary table is appended at the end of the run.
|
|
||||||
# =============================================================================
|
|
||||||
LOG_DIR="/usr/local/community-scripts/update_apps"
|
|
||||||
mkdir -p "$LOG_DIR"
|
|
||||||
LOG_FILE="${LOG_DIR}/$(date '+%Y%m%d_%H%M%S').log"
|
|
||||||
echo "Update started: $(date '+%Y-%m-%d %H:%M:%S')" >"$LOG_FILE"
|
|
||||||
|
|
||||||
function log_write() {
|
|
||||||
echo "[$(date '+%H:%M:%S')] $*" >>"$LOG_FILE"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Skip confirmation if var_skip_confirm is set to yes
|
# Skip confirmation if var_skip_confirm is set to yes
|
||||||
if [[ "$var_skip_confirm" != "yes" ]]; then
|
if [[ "$var_skip_confirm" != "yes" ]]; then
|
||||||
whiptail --backtitle "Proxmox VE Helper Scripts" --title "LXC App Update" --yesno "This will update apps in LXCs installed by Helper-Scripts. Proceed?" 10 58 || exit
|
whiptail --backtitle "Proxmox VE Helper Scripts" --title "LXC App Update" --yesno "This will update apps in LXCs installed by Helper-Scripts. Proceed?" 10 58 || exit
|
||||||
@@ -361,10 +260,7 @@ fi
|
|||||||
header_info
|
header_info
|
||||||
|
|
||||||
# Determine backup choice based on var_backup
|
# Determine backup choice based on var_backup
|
||||||
# Dry-run never needs a backup — skip the prompt entirely
|
if [[ -n "$var_backup" ]]; then
|
||||||
if [[ "$var_dry_run" == "yes" ]]; then
|
|
||||||
BACKUP_CHOICE="no"
|
|
||||||
elif [[ -n "$var_backup" ]]; then
|
|
||||||
BACKUP_CHOICE="$var_backup"
|
BACKUP_CHOICE="$var_backup"
|
||||||
else
|
else
|
||||||
BACKUP_CHOICE="no"
|
BACKUP_CHOICE="no"
|
||||||
@@ -374,10 +270,7 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Determine unattended update based on var_unattended
|
# Determine unattended update based on var_unattended
|
||||||
# Dry-run never executes updates — skip the prompt entirely
|
if [[ -n "$var_unattended" ]]; then
|
||||||
if [[ "$var_dry_run" == "yes" ]]; then
|
|
||||||
UNATTENDED_UPDATE="no"
|
|
||||||
elif [[ -n "$var_unattended" ]]; then
|
|
||||||
UNATTENDED_UPDATE="$var_unattended"
|
UNATTENDED_UPDATE="$var_unattended"
|
||||||
else
|
else
|
||||||
UNATTENDED_UPDATE="no"
|
UNATTENDED_UPDATE="no"
|
||||||
@@ -428,7 +321,6 @@ fi
|
|||||||
containers_needing_reboot=()
|
containers_needing_reboot=()
|
||||||
for container in $CHOICE; do
|
for container in $CHOICE; do
|
||||||
echo -e "${BL}[INFO]${CL} Updating container $container"
|
echo -e "${BL}[INFO]${CL} Updating container $container"
|
||||||
log_write "Container $container: starting"
|
|
||||||
|
|
||||||
if [ "$BACKUP_CHOICE" == "yes" ]; then
|
if [ "$BACKUP_CHOICE" == "yes" ]; then
|
||||||
backup_container $container
|
backup_container $container
|
||||||
@@ -450,12 +342,9 @@ for container in $CHOICE; do
|
|||||||
#1.1) If update script not detected, return
|
#1.1) If update script not detected, return
|
||||||
if [ -z "${service}" ]; then
|
if [ -z "${service}" ]; then
|
||||||
echo -e "${YW}[WARN]${CL} Update script not found. Skipping to next container"
|
echo -e "${YW}[WARN]${CL} Update script not found. Skipping to next container"
|
||||||
log_result "$container" "(unknown)" "SKIPPED" "No update script found in container"
|
|
||||||
log_write "Container $container: SKIPPED — no update script found"
|
|
||||||
continue
|
continue
|
||||||
else
|
else
|
||||||
echo -e "${BL}[INFO]${CL} Detected service: ${GN}${service}${CL}"
|
echo -e "${BL}[INFO]${CL} Detected service: ${GN}${service}${CL}"
|
||||||
log_write "Container $container: detected service '$service'"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#2) Extract service build/update resource requirements from config/installation file
|
#2) Extract service build/update resource requirements from config/installation file
|
||||||
@@ -502,29 +391,17 @@ for container in $CHOICE; do
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
#3) if build resources are different than run resources, then:
|
#3) if build resources are different than run resources, then:
|
||||||
if [ "$UPDATE_BUILD_RESOURCES" -eq "1" ] && [[ "$var_dry_run" != "yes" ]]; then
|
if [ "$UPDATE_BUILD_RESOURCES" -eq "1" ]; then
|
||||||
pct set "$container" --cores "$build_cpu" --memory "$build_ram"
|
pct set "$container" --cores "$build_cpu" --memory "$build_ram"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#3.5) Dry-run: report update availability without applying
|
|
||||||
if [[ "$var_dry_run" == "yes" ]]; then
|
|
||||||
DRY_RUN_RESULT=""
|
|
||||||
dry_run_container "$container" "$service"
|
|
||||||
log_result "$container" "$service" "DRY-RUN" "${DRY_RUN_RESULT:-version check only}"
|
|
||||||
log_write "Container $container ($service): DRY-RUN — ${DRY_RUN_RESULT:-version check only}"
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
#4) Update service, using the update command
|
#4) Update service, using the update command
|
||||||
# Prepend a no-op 'clear' wrapper to PATH so update scripts calling clear
|
|
||||||
# don't fail without a TTY — works for all shells incl. ash (no export -f)
|
|
||||||
SETUP_CMD="mkdir -p /tmp/.nc; printf '#!/bin/sh\n:\n' > /tmp/.nc/clear; chmod +x /tmp/.nc/clear; export PATH=/tmp/.nc:\$PATH; export TERM=dumb; "
|
|
||||||
case "$os" in
|
case "$os" in
|
||||||
alpine) pct exec "$container" -- ash -c "${SETUP_CMD}${UPDATE_CMD}" ;;
|
alpine) pct exec "$container" -- ash -c "$UPDATE_CMD" ;;
|
||||||
archlinux) pct exec "$container" -- bash -c "${SETUP_CMD}${UPDATE_CMD}" ;;
|
archlinux) pct exec "$container" -- bash -c "$UPDATE_CMD" ;;
|
||||||
fedora | rocky | centos | alma) pct exec "$container" -- bash -c "${SETUP_CMD}${UPDATE_CMD}" ;;
|
fedora | rocky | centos | alma) pct exec "$container" -- bash -c "$UPDATE_CMD" ;;
|
||||||
ubuntu | debian | devuan) pct exec "$container" -- bash -c "${SETUP_CMD}${UPDATE_CMD}" ;;
|
ubuntu | debian | devuan) pct exec "$container" -- bash -c "$UPDATE_CMD" ;;
|
||||||
opensuse) pct exec "$container" -- bash -c "${SETUP_CMD}${UPDATE_CMD}" ;;
|
opensuse) pct exec "$container" -- bash -c "$UPDATE_CMD" ;;
|
||||||
esac
|
esac
|
||||||
exit_code=$?
|
exit_code=$?
|
||||||
|
|
||||||
@@ -546,31 +423,16 @@ for container in $CHOICE; do
|
|||||||
|
|
||||||
if [ $exit_code -eq 0 ]; then
|
if [ $exit_code -eq 0 ]; then
|
||||||
msg_ok "Updated container $container"
|
msg_ok "Updated container $container"
|
||||||
log_result "$container" "$service" "OK" "Updated successfully"
|
|
||||||
log_write "Container $container ($service): OK"
|
|
||||||
elif [ $exit_code -eq 75 ]; then
|
elif [ $exit_code -eq 75 ]; then
|
||||||
echo -e "${YW}[WARN]${CL} Container $container skipped (requires interactive mode)"
|
echo -e "${YW}[WARN]${CL} Container $container skipped (requires interactive mode)"
|
||||||
log_result "$container" "$service" "SKIPPED" "Requires interactive mode (exit 75)"
|
|
||||||
log_write "Container $container ($service): SKIPPED — requires interactive mode"
|
|
||||||
elif [ $exit_code -eq 113 ]; then
|
|
||||||
echo -e "${YW}[WARN]${CL} Container $container skipped (under-provisioned: increase CPU/RAM to match template)"
|
|
||||||
log_result "$container" "$service" "SKIPPED" "Under-provisioned — increase CPU/RAM to match template"
|
|
||||||
log_write "Container $container ($service): SKIPPED — under-provisioned"
|
|
||||||
elif [ $exit_code -eq 114 ]; then
|
|
||||||
echo -e "${YW}[WARN]${CL} Container $container skipped (storage critically low on /boot)"
|
|
||||||
log_result "$container" "$service" "SKIPPED" "Storage critically low on /boot (>80%)"
|
|
||||||
log_write "Container $container ($service): SKIPPED — storage critically low on /boot"
|
|
||||||
elif [ "$BACKUP_CHOICE" == "yes" ]; then
|
elif [ "$BACKUP_CHOICE" == "yes" ]; then
|
||||||
msg_error "Update failed for container $container (exit code: $exit_code) — attempting restore"
|
msg_error "Update failed for container $container (exit code: $exit_code) — attempting restore"
|
||||||
log_write "Container $container ($service): FAILED (exit $exit_code) — attempting restore"
|
|
||||||
msg_info "Restoring LXC $container from backup ($STORAGE_CHOICE)"
|
msg_info "Restoring LXC $container from backup ($STORAGE_CHOICE)"
|
||||||
pct stop $container
|
pct stop $container
|
||||||
LXC_STORAGE=$(pct config $container | awk -F '[:,]' '/rootfs/ {print $2}')
|
LXC_STORAGE=$(pct config $container | awk -F '[:,]' '/rootfs/ {print $2}')
|
||||||
BACKUP_ENTRY=$(pvesm list "$STORAGE_CHOICE" 2>/dev/null | awk -v ctid="$container" '$1 ~ "vzdump-lxc-"ctid"-" || $1 ~ "/ct/"ctid"/" {print $1}' | sort -r | head -n1)
|
BACKUP_ENTRY=$(pvesm list "$STORAGE_CHOICE" 2>/dev/null | awk -v ctid="$container" '$1 ~ "vzdump-lxc-"ctid"-" || $1 ~ "/ct/"ctid"/" {print $1}' | sort -r | head -n1)
|
||||||
if [ -z "$BACKUP_ENTRY" ]; then
|
if [ -z "$BACKUP_ENTRY" ]; then
|
||||||
msg_error "No backup found in storage $STORAGE_CHOICE for container $container"
|
msg_error "No backup found in storage $STORAGE_CHOICE for container $container"
|
||||||
log_result "$container" "$service" "FAILED" "Update failed (exit $exit_code) — no backup found for restore"
|
|
||||||
log_write "Container $container ($service): FAILED — no backup found for restore"
|
|
||||||
exit 235
|
exit 235
|
||||||
fi
|
fi
|
||||||
msg_info "Restoring from: $BACKUP_ENTRY"
|
msg_info "Restoring from: $BACKUP_ENTRY"
|
||||||
@@ -579,76 +441,19 @@ for container in $CHOICE; do
|
|||||||
if [ $restorestatus -eq 0 ]; then
|
if [ $restorestatus -eq 0 ]; then
|
||||||
pct start $container
|
pct start $container
|
||||||
msg_ok "Container $container successfully restored from backup"
|
msg_ok "Container $container successfully restored from backup"
|
||||||
log_result "$container" "$service" "RESTORED" "Update failed (exit $exit_code) — restored from backup"
|
|
||||||
log_write "Container $container ($service): RESTORED from $BACKUP_ENTRY"
|
|
||||||
else
|
else
|
||||||
msg_error "Restore failed for container $container"
|
msg_error "Restore failed for container $container"
|
||||||
log_result "$container" "$service" "FAILED" "Update failed (exit $exit_code) — restore also failed"
|
|
||||||
log_write "Container $container ($service): FAILED — restore also failed"
|
|
||||||
exit 235
|
exit 235
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
msg_error "Update failed for container $container (exit code: $exit_code)"
|
msg_error "Update failed for container $container. Exiting"
|
||||||
log_result "$container" "$service" "FAILED" "Exit code $exit_code"
|
exit "$exit_code"
|
||||||
log_write "Container $container ($service): FAILED (exit $exit_code)"
|
|
||||||
if [[ "$var_continue_on_error" == "yes" ]]; then
|
|
||||||
echo -e "${YW}[WARN]${CL} Continuing to next container (var_continue_on_error=yes)"
|
|
||||||
continue
|
|
||||||
else
|
|
||||||
exit "$exit_code"
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
wait
|
wait
|
||||||
header_info
|
header_info
|
||||||
if [[ "$var_dry_run" == "yes" ]]; then
|
echo -e "${GN}The process is complete, and the containers have been successfully updated.${CL}\n"
|
||||||
echo -e "${GN}Dry-run complete. No containers were modified.${CL}\n"
|
|
||||||
else
|
|
||||||
echo -e "${GN}The process is complete, and the containers have been successfully updated.${CL}\n"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# =============================================================================
|
|
||||||
# SUMMARY REPORT
|
|
||||||
# =============================================================================
|
|
||||||
if [ "${#UPDATE_RESULTS[@]}" -gt 0 ]; then
|
|
||||||
SEPARATOR="━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
||||||
HEADER=$(printf " %-8s %-22s %-10s %s" "CTID" "Service" "Status" "Details")
|
|
||||||
|
|
||||||
# terminal output (with colours)
|
|
||||||
echo ""
|
|
||||||
echo "$SEPARATOR"
|
|
||||||
echo "$HEADER"
|
|
||||||
echo "$SEPARATOR"
|
|
||||||
for entry in "${UPDATE_RESULTS[@]}"; do
|
|
||||||
IFS='|' read -r _ctid _svc _status _details <<<"$entry"
|
|
||||||
case "$_status" in
|
|
||||||
OK) _color="${GN}" ;;
|
|
||||||
FAILED) _color="${RD}" ;;
|
|
||||||
RESTORED) _color="${YW}" ;;
|
|
||||||
*) _color="${YW}" ;;
|
|
||||||
esac
|
|
||||||
printf " %-8s %-22s ${_color}%-10s${CL} %s\n" "$_ctid" "$_svc" "$_status" "$_details"
|
|
||||||
done
|
|
||||||
echo "$SEPARATOR"
|
|
||||||
echo ""
|
|
||||||
echo "Full log: $LOG_FILE"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# append plain-text summary to log file
|
|
||||||
{
|
|
||||||
echo ""
|
|
||||||
echo "Update finished: $(date '+%Y-%m-%d %H:%M:%S')"
|
|
||||||
echo "$SEPARATOR"
|
|
||||||
echo "$HEADER"
|
|
||||||
echo "$SEPARATOR"
|
|
||||||
for entry in "${UPDATE_RESULTS[@]}"; do
|
|
||||||
IFS='|' read -r _ctid _svc _status _details <<<"$entry"
|
|
||||||
printf " %-8s %-22s %-10s %s\n" "$_ctid" "$_svc" "$_status" "$_details"
|
|
||||||
done
|
|
||||||
echo "$SEPARATOR"
|
|
||||||
} >>"$LOG_FILE"
|
|
||||||
fi
|
|
||||||
if [ "${#containers_needing_reboot[@]}" -gt 0 ]; then
|
if [ "${#containers_needing_reboot[@]}" -gt 0 ]; then
|
||||||
echo -e "${RD}The following containers require a reboot:${CL}"
|
echo -e "${RD}The following containers require a reboot:${CL}"
|
||||||
for container_name in "${containers_needing_reboot[@]}"; do
|
for container_name in "${containers_needing_reboot[@]}"; do
|
||||||
|
|||||||
@@ -494,7 +494,7 @@ fi
|
|||||||
msg_ok "Using ${CL}${BL}$STORAGE${CL} ${GN}for Storage Location."
|
msg_ok "Using ${CL}${BL}$STORAGE${CL} ${GN}for Storage Location."
|
||||||
msg_ok "Virtual Machine ID is ${CL}${BL}$VMID${CL}."
|
msg_ok "Virtual Machine ID is ${CL}${BL}$VMID${CL}."
|
||||||
msg_info "Retrieving the URL for the Ubuntu 25.04 Disk Image"
|
msg_info "Retrieving the URL for the Ubuntu 25.04 Disk Image"
|
||||||
URL=https://cloud-images.ubuntu.com/releases/server/plucky/release/ubuntu-25.04-server-cloudimg-amd64.img
|
URL=https://cloud-images.ubuntu.com/plucky/current/plucky-server-cloudimg-amd64.img
|
||||||
sleep 2
|
sleep 2
|
||||||
msg_ok "${CL}${BL}${URL}${CL}"
|
msg_ok "${CL}${BL}${URL}${CL}"
|
||||||
curl -f#SL -o "$(basename "$URL")" "$URL"
|
curl -f#SL -o "$(basename "$URL")" "$URL"
|
||||||
|
|||||||
Reference in New Issue
Block a user