mirror of
https://github.com/community-scripts/ProxmoxVE.git
synced 2026-05-19 15:04:56 +02:00
Compare commits
4 Commits
feat/setup
...
copilot/fi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dc70bc1327 | ||
|
|
32bee2c7a7 | ||
|
|
5039e0fd17 | ||
|
|
980dd572ab |
55
CHANGELOG.md
55
CHANGELOG.md
@@ -458,73 +458,18 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
|
|||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## 2026-05-07
|
|
||||||
|
|
||||||
### 🚀 Updated Scripts
|
|
||||||
|
|
||||||
- #### 🐞 Bug Fixes
|
|
||||||
|
|
||||||
- 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
|
|
||||||
|
|
||||||
### 🆕 New Scripts
|
|
||||||
|
|
||||||
- LibreChat ([#14247](https://github.com/community-scripts/ProxmoxVE/pull/14247))
|
|
||||||
- Matomo ([#14248](https://github.com/community-scripts/ProxmoxVE/pull/14248))
|
|
||||||
- Storyteller ([#14122](https://github.com/community-scripts/ProxmoxVE/pull/14122))
|
|
||||||
|
|
||||||
### 🧰 Tools
|
|
||||||
|
|
||||||
- Fix container count message in update-apps.sh [@Quotacious](https://github.com/Quotacious) ([#14265](https://github.com/community-scripts/ProxmoxVE/pull/14265))
|
|
||||||
|
|
||||||
## 2026-05-04
|
## 2026-05-04
|
||||||
|
|
||||||
### 🚀 Updated Scripts
|
### 🚀 Updated Scripts
|
||||||
|
|
||||||
- #### 🐞 Bug Fixes
|
- #### 🐞 Bug Fixes
|
||||||
|
|
||||||
- Databasus: move .env to filesystem root so service starts correctly [@Copilot](https://github.com/Copilot) ([#14252](https://github.com/community-scripts/ProxmoxVE/pull/14252))
|
|
||||||
- Databasus: update mongo-tools fallback to 100.16.1 and use now pnpm instead of npm ci [@MickLesk](https://github.com/MickLesk) ([#14240](https://github.com/community-scripts/ProxmoxVE/pull/14240))
|
- Databasus: update mongo-tools fallback to 100.16.1 and use now pnpm instead of npm ci [@MickLesk](https://github.com/MickLesk) ([#14240](https://github.com/community-scripts/ProxmoxVE/pull/14240))
|
||||||
|
|
||||||
### 💾 Core
|
### 💾 Core
|
||||||
|
|
||||||
- #### ✨ New Features
|
- #### ✨ New Features
|
||||||
|
|
||||||
- tools.func get_latest_gh_tag - add pagination to find prefixed tags beyond first 50 [@MickLesk](https://github.com/MickLesk) ([#14241](https://github.com/community-scripts/ProxmoxVE/pull/14241))
|
|
||||||
- tools.func: add GitLab release check/fetch/deploy helpers [@MickLesk](https://github.com/MickLesk) ([#14242](https://github.com/community-scripts/ProxmoxVE/pull/14242))
|
- tools.func: add GitLab release check/fetch/deploy helpers [@MickLesk](https://github.com/MickLesk) ([#14242](https://github.com/community-scripts/ProxmoxVE/pull/14242))
|
||||||
|
|
||||||
## 2026-05-03
|
## 2026-05-03
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
__ __ ___ __
|
|
||||||
/ / / /___ ____ ____/ (_) /__
|
|
||||||
/ /_/ / __ \/ __ \/ __ / / //_/
|
|
||||||
/ __ / /_/ / /_/ / /_/ / / ,<
|
|
||||||
/_/ /_/\____/\____/\__,_/_/_/|_|
|
|
||||||
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
__ _ __ ________ __
|
|
||||||
/ / (_) /_ ________ / ____/ /_ ____ _/ /_
|
|
||||||
/ / / / __ \/ ___/ _ \/ / / __ \/ __ `/ __/
|
|
||||||
/ /___/ / /_/ / / / __/ /___/ / / / /_/ / /_
|
|
||||||
/_____/_/_.___/_/ \___/\____/_/ /_/\__,_/\__/
|
|
||||||
|
|
||||||
6
ct/headers/litellm
Normal file
6
ct/headers/litellm
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
__ _ __ __ __ __ ___
|
||||||
|
/ / (_) /____ / / / / / |/ /
|
||||||
|
/ / / / __/ _ \/ / / / / /|_/ /
|
||||||
|
/ /___/ / /_/ __/ /___/ /___/ / / /
|
||||||
|
/_____/_/\__/\___/_____/_____/_/ /_/
|
||||||
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
__ ___ __
|
|
||||||
/ |/ /___ _/ /_____ ____ ___ ____
|
|
||||||
/ /|_/ / __ `/ __/ __ \/ __ `__ \/ __ \
|
|
||||||
/ / / / /_/ / /_/ /_/ / / / / / / /_/ /
|
|
||||||
/_/ /_/\__,_/\__/\____/_/ /_/ /_/\____/
|
|
||||||
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
_____ __ __ ____
|
|
||||||
/ ___// /_____ _______ __/ /____ / / /__ _____
|
|
||||||
\__ \/ __/ __ \/ ___/ / / / __/ _ \/ / / _ \/ ___/
|
|
||||||
___/ / /_/ /_/ / / / /_/ / /_/ __/ / / __/ /
|
|
||||||
/____/\__/\____/_/ \__, /\__/\___/_/_/\___/_/
|
|
||||||
/____/
|
|
||||||
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}"
|
|
||||||
101
ct/librechat.sh
101
ct/librechat.sh
@@ -1,101 +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/danny-avila/LibreChat
|
|
||||||
|
|
||||||
APP="LibreChat"
|
|
||||||
var_tags="${var_tags:-ai;chat}"
|
|
||||||
var_cpu="${var_cpu:-4}"
|
|
||||||
var_ram="${var_ram:-6144}"
|
|
||||||
var_disk="${var_disk:-20}"
|
|
||||||
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 [[ ! -d /opt/librechat ]]; then
|
|
||||||
msg_error "No ${APP} Installation Found!"
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
|
|
||||||
if check_for_gh_tag "librechat" "danny-avila/LibreChat" "v"; then
|
|
||||||
msg_info "Stopping Services"
|
|
||||||
systemctl stop librechat rag-api
|
|
||||||
msg_ok "Stopped Services"
|
|
||||||
|
|
||||||
msg_info "Backing up Configuration"
|
|
||||||
cp /opt/librechat/.env /opt/librechat.env.bak
|
|
||||||
msg_ok "Backed up Configuration"
|
|
||||||
|
|
||||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_tag "librechat" "danny-avila/LibreChat"
|
|
||||||
|
|
||||||
msg_info "Installing Dependencies"
|
|
||||||
cd /opt/librechat
|
|
||||||
$STD npm ci
|
|
||||||
msg_ok "Installed Dependencies"
|
|
||||||
|
|
||||||
msg_info "Building Frontend"
|
|
||||||
$STD npm run frontend
|
|
||||||
$STD npm prune --production
|
|
||||||
$STD npm cache clean --force
|
|
||||||
msg_ok "Built Frontend"
|
|
||||||
|
|
||||||
msg_info "Restoring Configuration"
|
|
||||||
cp /opt/librechat.env.bak /opt/librechat/.env
|
|
||||||
rm -f /opt/librechat.env.bak
|
|
||||||
msg_ok "Restored Configuration"
|
|
||||||
|
|
||||||
msg_info "Starting Services"
|
|
||||||
systemctl start rag-api librechat
|
|
||||||
msg_ok "Started Services"
|
|
||||||
msg_ok "Updated LibreChat Successfully!"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if check_for_gh_release "rag-api" "danny-avila/rag_api"; then
|
|
||||||
msg_info "Stopping RAG API"
|
|
||||||
systemctl stop rag-api
|
|
||||||
msg_ok "Stopped RAG API"
|
|
||||||
|
|
||||||
msg_info "Backing up RAG API Configuration"
|
|
||||||
cp /opt/rag-api/.env /opt/rag-api.env.bak
|
|
||||||
msg_ok "Backed up RAG API Configuration"
|
|
||||||
|
|
||||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "rag-api" "danny-avila/rag_api" "tarball"
|
|
||||||
|
|
||||||
msg_info "Updating RAG API Dependencies"
|
|
||||||
cd /opt/rag-api
|
|
||||||
$STD .venv/bin/pip install -r requirements.lite.txt
|
|
||||||
msg_ok "Updated RAG API Dependencies"
|
|
||||||
|
|
||||||
msg_info "Restoring RAG API Configuration"
|
|
||||||
cp /opt/rag-api.env.bak /opt/rag-api/.env
|
|
||||||
rm -f /opt/rag-api.env.bak
|
|
||||||
msg_ok "Restored RAG API Configuration"
|
|
||||||
|
|
||||||
msg_info "Starting RAG API"
|
|
||||||
systemctl start rag-api
|
|
||||||
msg_ok "Started RAG API"
|
|
||||||
msg_ok "Updated RAG API 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}:3080${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}"
|
||||||
75
ct/matomo.sh
75
ct/matomo.sh
@@ -1,75 +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://matomo.org/
|
|
||||||
|
|
||||||
APP="Matomo"
|
|
||||||
var_tags="${var_tags:-analytics;tracking;privacy}"
|
|
||||||
var_cpu="${var_cpu:-2}"
|
|
||||||
var_ram="${var_ram:-2048}"
|
|
||||||
var_disk="${var_disk:-16}"
|
|
||||||
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 [[ ! -d /opt/matomo ]]; then
|
|
||||||
msg_error "No ${APP} Installation Found!"
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
|
|
||||||
if check_for_gh_release "matomo" "matomo-org/matomo"; then
|
|
||||||
msg_info "Stopping Services"
|
|
||||||
systemctl stop caddy
|
|
||||||
msg_ok "Stopped Services"
|
|
||||||
|
|
||||||
msg_info "Backing up Data"
|
|
||||||
[[ -f /opt/matomo/config/config.ini.php ]] && cp /opt/matomo/config/config.ini.php /opt/matomo_config.bak
|
|
||||||
[[ -d /opt/matomo/misc/user ]] && cp -r /opt/matomo/misc/user /opt/matomo_user_backup
|
|
||||||
[[ -f /root/matomo.creds ]] && cp /root/matomo.creds /opt/matomo_db_creds.bak
|
|
||||||
msg_ok "Backed up Data"
|
|
||||||
|
|
||||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "matomo" "matomo-org/matomo" "prebuild" "latest" "/opt/matomo" "matomo-*.zip"
|
|
||||||
|
|
||||||
msg_info "Restoring Data"
|
|
||||||
if [[ -f /opt/matomo_config.bak ]]; then
|
|
||||||
mkdir -p /opt/matomo/config
|
|
||||||
cp /opt/matomo_config.bak /opt/matomo/config/config.ini.php
|
|
||||||
fi
|
|
||||||
if [[ -d /opt/matomo_user_backup ]]; then
|
|
||||||
mkdir -p /opt/matomo/misc/user
|
|
||||||
cp -r /opt/matomo_user_backup/. /opt/matomo/misc/user
|
|
||||||
fi
|
|
||||||
[[ -f /opt/matomo_db_creds.bak ]] && cp /opt/matomo_db_creds.bak /root/matomo.creds
|
|
||||||
rm -f /opt/matomo_config.bak /opt/matomo_db_creds.bak
|
|
||||||
rm -rf /opt/matomo_user_backup
|
|
||||||
chown -R www-data:www-data /opt/matomo
|
|
||||||
msg_ok "Restored Data"
|
|
||||||
|
|
||||||
msg_info "Starting Services"
|
|
||||||
systemctl start caddy
|
|
||||||
msg_ok "Started Services"
|
|
||||||
msg_ok "Updated successfully!"
|
|
||||||
fi
|
|
||||||
exit
|
|
||||||
}
|
|
||||||
|
|
||||||
start
|
|
||||||
build_container
|
|
||||||
description
|
|
||||||
|
|
||||||
msg_ok "Completed Successfully!\n"
|
|
||||||
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
|
|
||||||
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
|
|
||||||
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${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
|
||||||
|
|||||||
@@ -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")
|
||||||
|
|||||||
@@ -48,6 +48,8 @@ function update_script() {
|
|||||||
msg_ok "Services started"
|
msg_ok "Services started"
|
||||||
|
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
|
else
|
||||||
|
msg_ok "No update required. ${APP} is already at v${RELEASE}"
|
||||||
fi
|
fi
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,85 +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://gitlab.com/storyteller-platform/storyteller
|
|
||||||
|
|
||||||
APP="Storyteller"
|
|
||||||
var_tags="${var_tags:-media;ebook;audiobook}"
|
|
||||||
var_cpu="${var_cpu:-4}"
|
|
||||||
var_ram="${var_ram:-10240}"
|
|
||||||
var_disk="${var_disk:-20}"
|
|
||||||
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 [[ ! -d /opt/storyteller ]]; then
|
|
||||||
msg_error "No ${APP} Installation Found!"
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
|
|
||||||
if check_for_gl_release "storyteller" "storyteller-platform/storyteller"; then
|
|
||||||
msg_info "Stopping Service"
|
|
||||||
systemctl stop storyteller
|
|
||||||
msg_ok "Stopped Service"
|
|
||||||
|
|
||||||
msg_info "Backing up Data"
|
|
||||||
cp /opt/storyteller/.env /opt/storyteller_env.bak
|
|
||||||
msg_ok "Backed up Data"
|
|
||||||
|
|
||||||
CLEAN_INSTALL=1 fetch_and_deploy_gl_release "storyteller" "storyteller-platform/storyteller" "tarball" "latest" "/opt/storyteller"
|
|
||||||
|
|
||||||
msg_info "Restoring Configuration"
|
|
||||||
mv /opt/storyteller_env.bak /opt/storyteller/.env
|
|
||||||
msg_ok "Restored Configuration"
|
|
||||||
|
|
||||||
msg_info "Rebuilding Storyteller"
|
|
||||||
cd /opt/storyteller
|
|
||||||
export NODE_OPTIONS="--max-old-space-size=4096"
|
|
||||||
$STD yarn install --network-timeout 600000
|
|
||||||
$STD gcc -g -fPIC -rdynamic -shared web/sqlite/uuid.c -o web/sqlite/uuid.c.so
|
|
||||||
export CI=1
|
|
||||||
export NODE_ENV=production
|
|
||||||
export NEXT_TELEMETRY_DISABLED=1
|
|
||||||
export SQLITE_NATIVE_BINDING=/opt/storyteller/node_modules/better-sqlite3/build/Release/better_sqlite3.node
|
|
||||||
$STD yarn workspaces foreach -Rpt --from @storyteller-platform/web --exclude @storyteller-platform/eslint run build
|
|
||||||
mkdir -p /opt/storyteller/web/.next/standalone/web/.next/static
|
|
||||||
cp -rT /opt/storyteller/web/.next/static /opt/storyteller/web/.next/standalone/web/.next/static
|
|
||||||
if [[ -d /opt/storyteller/web/public ]]; then
|
|
||||||
mkdir -p /opt/storyteller/web/.next/standalone/web/public
|
|
||||||
cp -rT /opt/storyteller/web/public /opt/storyteller/web/.next/standalone/web/public
|
|
||||||
fi
|
|
||||||
mkdir -p /opt/storyteller/web/.next/standalone/web/migrations
|
|
||||||
cp -rT /opt/storyteller/web/migrations /opt/storyteller/web/.next/standalone/web/migrations
|
|
||||||
mkdir -p /opt/storyteller/web/.next/standalone/web/sqlite
|
|
||||||
cp -rT /opt/storyteller/web/sqlite /opt/storyteller/web/.next/standalone/web/sqlite
|
|
||||||
ln -sf /opt/storyteller/.env /opt/storyteller/web/.next/standalone/web/.env
|
|
||||||
msg_ok "Rebuilt Storyteller"
|
|
||||||
|
|
||||||
msg_info "Starting Service"
|
|
||||||
systemctl start storyteller
|
|
||||||
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}:8001${CL}"
|
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -1,139 +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/danny-avila/LibreChat
|
|
||||||
|
|
||||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
|
||||||
color
|
|
||||||
verb_ip6
|
|
||||||
catch_errors
|
|
||||||
setting_up_container
|
|
||||||
network_check
|
|
||||||
update_os
|
|
||||||
|
|
||||||
MONGO_VERSION="8.0" setup_mongodb
|
|
||||||
setup_meilisearch
|
|
||||||
PG_VERSION="17" PG_MODULES="pgvector" setup_postgresql
|
|
||||||
PG_DB_NAME="ragapi" PG_DB_USER="ragapi" PG_DB_EXTENSIONS="vector" setup_postgresql_db
|
|
||||||
NODE_VERSION="24" setup_nodejs
|
|
||||||
UV_PYTHON="3.12" setup_uv
|
|
||||||
|
|
||||||
fetch_and_deploy_gh_tag "librechat" "danny-avila/LibreChat"
|
|
||||||
fetch_and_deploy_gh_release "rag-api" "danny-avila/rag_api" "tarball"
|
|
||||||
|
|
||||||
msg_info "Installing LibreChat Dependencies"
|
|
||||||
cd /opt/librechat
|
|
||||||
$STD npm ci
|
|
||||||
msg_ok "Installed LibreChat Dependencies"
|
|
||||||
|
|
||||||
msg_info "Building Frontend"
|
|
||||||
$STD npm run frontend
|
|
||||||
$STD npm prune --production
|
|
||||||
$STD npm cache clean --force
|
|
||||||
msg_ok "Built Frontend"
|
|
||||||
|
|
||||||
msg_info "Installing RAG API Dependencies"
|
|
||||||
cd /opt/rag-api
|
|
||||||
$STD uv venv --python 3.12 --seed .venv
|
|
||||||
$STD .venv/bin/pip install -r requirements.lite.txt
|
|
||||||
mkdir -p /opt/rag-api/uploads
|
|
||||||
msg_ok "Installed RAG API Dependencies"
|
|
||||||
|
|
||||||
msg_info "Configuring LibreChat"
|
|
||||||
JWT_SECRET=$(openssl rand -hex 32)
|
|
||||||
JWT_REFRESH_SECRET=$(openssl rand -hex 32)
|
|
||||||
CREDS_KEY=$(openssl rand -hex 32)
|
|
||||||
CREDS_IV=$(openssl rand -hex 16)
|
|
||||||
cat <<EOF >/opt/librechat/.env
|
|
||||||
HOST=0.0.0.0
|
|
||||||
PORT=3080
|
|
||||||
MONGO_URI=mongodb://127.0.0.1:27017/LibreChat
|
|
||||||
DOMAIN_CLIENT=http://${LOCAL_IP}:3080
|
|
||||||
DOMAIN_SERVER=http://${LOCAL_IP}:3080
|
|
||||||
NO_INDEX=true
|
|
||||||
TRUST_PROXY=1
|
|
||||||
JWT_SECRET=${JWT_SECRET}
|
|
||||||
JWT_REFRESH_SECRET=${JWT_REFRESH_SECRET}
|
|
||||||
SESSION_EXPIRY=1000 * 60 * 15
|
|
||||||
REFRESH_TOKEN_EXPIRY=(1000 * 60 * 60 * 24) * 7
|
|
||||||
CREDS_KEY=${CREDS_KEY}
|
|
||||||
CREDS_IV=${CREDS_IV}
|
|
||||||
ALLOW_EMAIL_LOGIN=true
|
|
||||||
ALLOW_REGISTRATION=true
|
|
||||||
ALLOW_SOCIAL_LOGIN=false
|
|
||||||
ALLOW_SOCIAL_REGISTRATION=false
|
|
||||||
ALLOW_PASSWORD_RESET=false
|
|
||||||
ALLOW_UNVERIFIED_EMAIL_LOGIN=true
|
|
||||||
SEARCH=true
|
|
||||||
MEILI_NO_ANALYTICS=true
|
|
||||||
MEILI_HOST=http://127.0.0.1:7700
|
|
||||||
MEILI_MASTER_KEY=${MEILISEARCH_MASTER_KEY}
|
|
||||||
RAG_PORT=8000
|
|
||||||
RAG_API_URL=http://127.0.0.1:8000
|
|
||||||
APP_TITLE=LibreChat
|
|
||||||
ENDPOINTS=openAI,agents,assistants,anthropic,google
|
|
||||||
# OPENAI_API_KEY=your-key-here
|
|
||||||
# OPENAI_MODELS=
|
|
||||||
# ANTHROPIC_API_KEY=your-key-here
|
|
||||||
# GOOGLE_KEY=your-key-here
|
|
||||||
EOF
|
|
||||||
msg_ok "Configured LibreChat"
|
|
||||||
|
|
||||||
msg_info "Configuring RAG API"
|
|
||||||
cat <<EOF >/opt/rag-api/.env
|
|
||||||
VECTOR_DB_TYPE=pgvector
|
|
||||||
DB_HOST=127.0.0.1
|
|
||||||
DB_PORT=5432
|
|
||||||
POSTGRES_DB=${PG_DB_NAME}
|
|
||||||
POSTGRES_USER=${PG_DB_USER}
|
|
||||||
POSTGRES_PASSWORD=${PG_DB_PASS}
|
|
||||||
RAG_HOST=0.0.0.0
|
|
||||||
RAG_PORT=8000
|
|
||||||
JWT_SECRET=${JWT_SECRET}
|
|
||||||
RAG_UPLOAD_DIR=/opt/rag-api/uploads/
|
|
||||||
EOF
|
|
||||||
msg_ok "Configured RAG API"
|
|
||||||
|
|
||||||
msg_info "Creating Services"
|
|
||||||
cat <<EOF >/etc/systemd/system/librechat.service
|
|
||||||
[Unit]
|
|
||||||
Description=LibreChat
|
|
||||||
After=network.target mongod.service meilisearch.service rag-api.service
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=simple
|
|
||||||
User=root
|
|
||||||
WorkingDirectory=/opt/librechat
|
|
||||||
EnvironmentFile=/opt/librechat/.env
|
|
||||||
ExecStart=/usr/bin/npm run backend
|
|
||||||
Restart=on-failure
|
|
||||||
RestartSec=5
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
EOF
|
|
||||||
cat <<EOF >/etc/systemd/system/rag-api.service
|
|
||||||
[Unit]
|
|
||||||
Description=LibreChat RAG API
|
|
||||||
After=network.target postgresql.service
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=simple
|
|
||||||
User=root
|
|
||||||
WorkingDirectory=/opt/rag-api
|
|
||||||
EnvironmentFile=/opt/rag-api/.env
|
|
||||||
ExecStart=/opt/rag-api/.venv/bin/uvicorn main:app --host 0.0.0.0 --port 8000
|
|
||||||
Restart=on-failure
|
|
||||||
RestartSec=5
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
EOF
|
|
||||||
systemctl enable -q --now rag-api librechat
|
|
||||||
msg_ok "Created Services"
|
|
||||||
|
|
||||||
motd_ssh
|
|
||||||
customize
|
|
||||||
cleanup_lxc
|
|
||||||
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
|
||||||
@@ -1,66 +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://matomo.org/
|
|
||||||
|
|
||||||
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 caddy
|
|
||||||
msg_ok "Installed Dependencies"
|
|
||||||
|
|
||||||
mkdir -p /opt/matomo
|
|
||||||
|
|
||||||
PHP_VERSION="8.3" PHP_FPM="YES" PHP_MODULES="pdo_mysql,gd,mbstring,xml,curl,intl,zip,ldap" setup_php
|
|
||||||
setup_mariadb
|
|
||||||
MARIADB_DB_NAME="matomo" MARIADB_DB_USER="matomo" setup_mariadb_db
|
|
||||||
|
|
||||||
msg_info "Allowing Local TCP Database Access"
|
|
||||||
$STD mariadb -u root -e "CREATE USER IF NOT EXISTS '$MARIADB_DB_USER'@'127.0.0.1' IDENTIFIED BY '$MARIADB_DB_PASS';"
|
|
||||||
$STD mariadb -u root -e "ALTER USER '$MARIADB_DB_USER'@'127.0.0.1' IDENTIFIED BY '$MARIADB_DB_PASS';"
|
|
||||||
$STD mariadb -u root -e "GRANT ALL ON \`$MARIADB_DB_NAME\`.* TO '$MARIADB_DB_USER'@'127.0.0.1';"
|
|
||||||
$STD mariadb -u root -e "FLUSH PRIVILEGES;"
|
|
||||||
msg_ok "Allowed Local TCP Database Access"
|
|
||||||
|
|
||||||
fetch_and_deploy_gh_release "matomo" "matomo-org/matomo" "prebuild" "latest" "/opt/matomo" "matomo-*.zip"
|
|
||||||
|
|
||||||
msg_info "Setting up Matomo"
|
|
||||||
if [[ -d /opt/matomo/matomo ]]; then
|
|
||||||
rm -rf /opt/matomo/tmp "/opt/matomo/How to install Matomo.html"
|
|
||||||
find /opt/matomo/matomo -mindepth 1 -maxdepth 1 -exec mv -t /opt/matomo {} +
|
|
||||||
rm -rf /opt/matomo/matomo
|
|
||||||
fi
|
|
||||||
mkdir -p /opt/matomo/tmp
|
|
||||||
chown -R www-data:www-data /opt/matomo
|
|
||||||
chmod -R 755 /opt/matomo/tmp
|
|
||||||
msg_ok "Set up Matomo"
|
|
||||||
|
|
||||||
msg_info "Configuring Caddy"
|
|
||||||
PHP_VER=$(php -r 'echo PHP_MAJOR_VERSION . "." . PHP_MINOR_VERSION;')
|
|
||||||
cat <<EOF >/etc/caddy/Caddyfile
|
|
||||||
:80 {
|
|
||||||
root * /opt/matomo
|
|
||||||
@blocked path /config /config/* /tmp /tmp/* /.* /.*/*
|
|
||||||
respond @blocked 403
|
|
||||||
php_fastcgi unix//run/php/php${PHP_VER}-fpm.sock
|
|
||||||
file_server
|
|
||||||
encode gzip
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
usermod -aG www-data caddy
|
|
||||||
msg_ok "Configured Caddy"
|
|
||||||
|
|
||||||
systemctl enable -q --now php${PHP_VER}-fpm
|
|
||||||
systemctl restart caddy
|
|
||||||
|
|
||||||
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
|
||||||
|
|||||||
@@ -1,98 +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://gitlab.com/storyteller-platform/storyteller
|
|
||||||
|
|
||||||
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 \
|
|
||||||
git \
|
|
||||||
pkg-config \
|
|
||||||
libsqlite3-dev \
|
|
||||||
sqlite3 \
|
|
||||||
python3-setuptools \
|
|
||||||
ffmpeg
|
|
||||||
msg_ok "Installed Dependencies"
|
|
||||||
|
|
||||||
NODE_VERSION="22" NODE_MODULE="yarn" setup_nodejs
|
|
||||||
|
|
||||||
fetch_and_deploy_gh_release "readium" "readium/cli" "prebuild" "latest" "/opt/readium" "readium_linux_x86_64.tar.gz"
|
|
||||||
ln -sf /opt/readium/readium /usr/local/bin/readium
|
|
||||||
fetch_and_deploy_gl_release "storyteller" "storyteller-platform/storyteller" "tarball" "latest" "/opt/storyteller"
|
|
||||||
|
|
||||||
msg_info "Setting up Storyteller"
|
|
||||||
cd /opt/storyteller
|
|
||||||
$STD yarn install --network-timeout 600000
|
|
||||||
$STD gcc -g -fPIC -rdynamic -shared web/sqlite/uuid.c -o web/sqlite/uuid.c.so
|
|
||||||
STORYTELLER_SECRET_KEY=$(openssl rand -base64 32)
|
|
||||||
cat <<EOF >/opt/storyteller/.env
|
|
||||||
STORYTELLER_SECRET_KEY=${STORYTELLER_SECRET_KEY}
|
|
||||||
STORYTELLER_DATA_DIR=/opt/storyteller/data
|
|
||||||
PORT=8001
|
|
||||||
HOSTNAME=0.0.0.0
|
|
||||||
READIUM_PORT=9000
|
|
||||||
NODE_ENV=production
|
|
||||||
NEXT_TELEMETRY_DISABLED=1
|
|
||||||
EOF
|
|
||||||
mkdir -p /opt/storyteller/data
|
|
||||||
{
|
|
||||||
echo "Storyteller Credentials"
|
|
||||||
echo "======================="
|
|
||||||
echo "Secret Key: ${STORYTELLER_SECRET_KEY}"
|
|
||||||
} >~/storyteller.creds
|
|
||||||
msg_ok "Set up Storyteller"
|
|
||||||
|
|
||||||
msg_info "Building Storyteller"
|
|
||||||
cd /opt/storyteller
|
|
||||||
export CI=1
|
|
||||||
export NODE_ENV=production
|
|
||||||
export NEXT_TELEMETRY_DISABLED=1
|
|
||||||
export SQLITE_NATIVE_BINDING=/opt/storyteller/node_modules/better-sqlite3/build/Release/better_sqlite3.node
|
|
||||||
$STD yarn workspaces foreach -Rpt --from @storyteller-platform/web --exclude @storyteller-platform/eslint run build
|
|
||||||
mkdir -p /opt/storyteller/web/.next/standalone/web/.next/static
|
|
||||||
cp -rT /opt/storyteller/web/.next/static /opt/storyteller/web/.next/standalone/web/.next/static
|
|
||||||
if [[ -d /opt/storyteller/web/public ]]; then
|
|
||||||
mkdir -p /opt/storyteller/web/.next/standalone/web/public
|
|
||||||
cp -rT /opt/storyteller/web/public /opt/storyteller/web/.next/standalone/web/public
|
|
||||||
fi
|
|
||||||
mkdir -p /opt/storyteller/web/.next/standalone/web/migrations
|
|
||||||
cp -rT /opt/storyteller/web/migrations /opt/storyteller/web/.next/standalone/web/migrations
|
|
||||||
mkdir -p /opt/storyteller/web/.next/standalone/web/sqlite
|
|
||||||
cp -rT /opt/storyteller/web/sqlite /opt/storyteller/web/.next/standalone/web/sqlite
|
|
||||||
ln -sf /opt/storyteller/.env /opt/storyteller/web/.next/standalone/web/.env
|
|
||||||
msg_ok "Built Storyteller"
|
|
||||||
|
|
||||||
msg_info "Creating Service"
|
|
||||||
cat <<EOF >/etc/systemd/system/storyteller.service
|
|
||||||
[Unit]
|
|
||||||
Description=Storyteller
|
|
||||||
After=network.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=simple
|
|
||||||
User=root
|
|
||||||
WorkingDirectory=/opt/storyteller/web/.next/standalone/web
|
|
||||||
EnvironmentFile=/opt/storyteller/.env
|
|
||||||
ExecStart=/usr/bin/node --enable-source-maps server.js
|
|
||||||
Restart=on-failure
|
|
||||||
RestartSec=5
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
EOF
|
|
||||||
systemctl enable -q --now storyteller
|
|
||||||
msg_ok "Created Service"
|
|
||||||
|
|
||||||
motd_ssh
|
|
||||||
customize
|
|
||||||
cleanup_lxc
|
|
||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
100
misc/tools.func
100
misc/tools.func
@@ -2079,33 +2079,15 @@ get_latest_gh_tag() {
|
|||||||
local temp_file
|
local temp_file
|
||||||
temp_file=$(mktemp)
|
temp_file=$(mktemp)
|
||||||
|
|
||||||
|
if ! github_api_call "https://api.github.com/repos/${repo}/tags?per_page=50" "$temp_file"; then
|
||||||
|
rm -f "$temp_file"
|
||||||
|
return 22
|
||||||
|
fi
|
||||||
|
|
||||||
local tag=""
|
local tag=""
|
||||||
|
|
||||||
if [[ -n "$prefix" ]]; then
|
if [[ -n "$prefix" ]]; then
|
||||||
# Use git/matching-refs API for server-side prefix filtering. This avoids
|
tag=$(jq -r --arg p "$prefix" '[.[] | select(.name | startswith($p))][0].name // empty' "$temp_file")
|
||||||
# paging through unrelated tags (e.g. mongodb/mongo-tools where 100.x tags
|
|
||||||
# only appear after page 4 of /tags). Returns ALL tags matching the prefix
|
|
||||||
# in a single call, sorted lexicographically ascending; we pick the
|
|
||||||
# highest version using `sort -V`.
|
|
||||||
if ! github_api_call "https://api.github.com/repos/${repo}/git/matching-refs/tags/${prefix}" "$temp_file"; then
|
|
||||||
rm -f "$temp_file"
|
|
||||||
return 22
|
|
||||||
fi
|
|
||||||
|
|
||||||
local count
|
|
||||||
count=$(jq 'length' "$temp_file" 2>/dev/null || echo 0)
|
|
||||||
if [[ "$count" -gt 0 ]]; then
|
|
||||||
tag=$(jq -r '.[].ref' "$temp_file" |
|
|
||||||
sed 's|^refs/tags/||' |
|
|
||||||
sort -V |
|
|
||||||
tail -n1)
|
|
||||||
fi
|
|
||||||
else
|
else
|
||||||
# No prefix: just take the first (newest) tag from /tags
|
|
||||||
if ! github_api_call "https://api.github.com/repos/${repo}/tags?per_page=1" "$temp_file"; then
|
|
||||||
rm -f "$temp_file"
|
|
||||||
return 22
|
|
||||||
fi
|
|
||||||
tag=$(jq -r '.[0].name // empty' "$temp_file")
|
tag=$(jq -r '.[0].name // empty' "$temp_file")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -9439,73 +9421,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
|
||||||
@@ -94,8 +81,6 @@ Environment Variables:
|
|||||||
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_dry_run Check for updates without applying them (yes/no)
|
|
||||||
var_tags Optionally override auto-detection tags ("prod|smb|community-script")
|
var_tags Optionally override auto-detection tags ("prod|smb|community-script")
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
@@ -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
|
||||||
@@ -300,7 +199,7 @@ while read -r container; do
|
|||||||
menu_items+=("$container_id" "$formatted_line" "OFF")
|
menu_items+=("$container_id" "$formatted_line" "OFF")
|
||||||
fi
|
fi
|
||||||
done <<<"$containers"
|
done <<<"$containers"
|
||||||
msg_ok "Loaded $((${#menu_items[@]} / 3)) containers"
|
msg_ok "Loaded ${#menu_items[@]} containers"
|
||||||
|
|
||||||
# Determine container selection based on var_container
|
# Determine container selection based on var_container
|
||||||
if [[ -n "$var_container" ]]; then
|
if [[ -n "$var_container" ]]; then
|
||||||
@@ -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"
|
|
||||||
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"
|
exit "$exit_code"
|
||||||
fi
|
fi
|
||||||
fi
|
|
||||||
done
|
done
|
||||||
|
|
||||||
wait
|
wait
|
||||||
header_info
|
header_info
|
||||||
if [[ "$var_dry_run" == "yes" ]]; then
|
|
||||||
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"
|
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