Merge branch 'community-scripts:main' into pr-update-lxcs-services
This commit is contained in:
commit
507057693a
@ -1,45 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
source <(curl -s https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/build.func)
|
|
||||||
# Copyright (c) 2021-2025 community-scripts ORG
|
|
||||||
# Author: MickLesk (CanbiZ)
|
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
|
||||||
# Source: https://syncthing.net/
|
|
||||||
|
|
||||||
APP="Alpine-Syncthing"
|
|
||||||
var_tags="${var_tags:-alpine;networking}"
|
|
||||||
var_cpu="${var_cpu:-1}"
|
|
||||||
var_ram="${var_ram:-256}"
|
|
||||||
var_disk="${var_disk:-1}"
|
|
||||||
var_os="${var_os:-alpine}"
|
|
||||||
var_version="${var_version:-3.21}"
|
|
||||||
var_unprivileged="${var_unprivileged:-1}"
|
|
||||||
|
|
||||||
header_info "$APP"
|
|
||||||
variables
|
|
||||||
color
|
|
||||||
catch_errors
|
|
||||||
|
|
||||||
function update_script() {
|
|
||||||
msg_info "Updating Alpine Packages"
|
|
||||||
$STD apk -U upgrade
|
|
||||||
msg_ok "Updated Alpine Packages"
|
|
||||||
|
|
||||||
msg_info "Updating Syncthing"
|
|
||||||
$STD apk upgrade syncthing
|
|
||||||
msg_ok "Updated Syncthing"
|
|
||||||
|
|
||||||
msg_info "Restarting Syncthing"
|
|
||||||
$STD rc-service syncthing restart
|
|
||||||
msg_ok "Restarted Syncthing"
|
|
||||||
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
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}:8384${CL}"
|
|
@ -11,7 +11,7 @@ var_cpu="${var_cpu:-1}"
|
|||||||
var_ram="${var_ram:-512}"
|
var_ram="${var_ram:-512}"
|
||||||
var_disk="${var_disk:-1}"
|
var_disk="${var_disk:-1}"
|
||||||
var_os="${var_os:-alpine}"
|
var_os="${var_os:-alpine}"
|
||||||
var_version="${var_version:-3.21}"
|
var_version="${var_version:-3.22}"
|
||||||
var_unprivileged="${var_unprivileged:-1}"
|
var_unprivileged="${var_unprivileged:-1}"
|
||||||
|
|
||||||
header_info "$APP"
|
header_info "$APP"
|
||||||
|
@ -40,5 +40,5 @@ start
|
|||||||
build_container
|
build_container
|
||||||
description
|
description
|
||||||
|
|
||||||
msg_ok "Completed Successfully!\n"
|
msg_ok "Completed Successfully!"
|
||||||
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
|
msg_custom "🚀" "${GN}" "${APP} setup has been successfully initialized!"
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
___ __ _ _____ __ __ _
|
|
||||||
/ | / /___ (_)___ ___ / ___/__ ______ _____/ /_/ /_ (_)___ ____ _
|
|
||||||
/ /| | / / __ \/ / __ \/ _ \______\__ \/ / / / __ \/ ___/ __/ __ \/ / __ \/ __ `/
|
|
||||||
/ ___ |/ / /_/ / / / / / __/_____/__/ / /_/ / / / / /__/ /_/ / / / / / / / /_/ /
|
|
||||||
/_/ |_/_/ .___/_/_/ /_/\___/ /____/\__, /_/ /_/\___/\__/_/ /_/_/_/ /_/\__, /
|
|
||||||
/_/ /____/ /____/
|
|
@ -1,6 +0,0 @@
|
|||||||
_ __
|
|
||||||
(_) /__________ ___ ____ ____ _
|
|
||||||
/ / __/ ___/ __ `__ \/ __ \/ __ `/
|
|
||||||
/ / /_(__ ) / / / / / / / / /_/ /
|
|
||||||
/_/\__/____/_/ /_/ /_/_/ /_/\__, /
|
|
||||||
/____/
|
|
@ -1,6 +0,0 @@
|
|||||||
__ ____ _____
|
|
||||||
/ /__ / / /_ __/ __(_)___
|
|
||||||
__ / / _ \/ / / / / / /_/ / __ \
|
|
||||||
/ /_/ / __/ / / /_/ / __/ / / / /
|
|
||||||
\____/\___/_/_/\__, /_/ /_/_/ /_/
|
|
||||||
/____/
|
|
@ -1,6 +0,0 @@
|
|||||||
__ __
|
|
||||||
/ //_/___ _____ ____ _ ______ ___________
|
|
||||||
/ ,< / __ `/ __ \/ __ \ | /| / / __ `/ ___/ ___/
|
|
||||||
/ /| / /_/ / /_/ / /_/ / |/ |/ / /_/ / / / /
|
|
||||||
/_/ |_\__,_/ .___/\____/|__/|__/\__,_/_/ /_/
|
|
||||||
/_/
|
|
@ -1,6 +0,0 @@
|
|||||||
_ ______ __ ___ __
|
|
||||||
/ | / / __ \/ |/ /___ / /_ _______
|
|
||||||
/ |/ / /_/ / /|_/ / __ \/ / / / / ___/
|
|
||||||
/ /| / ____/ / / / /_/ / / /_/ (__ )
|
|
||||||
/_/ |_/_/ /_/ /_/ .___/_/\__,_/____/
|
|
||||||
/_/
|
|
6
ct/headers/scraparr
Normal file
6
ct/headers/scraparr
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
_____
|
||||||
|
/ ___/______________ _____ ____ ___________
|
||||||
|
\__ \/ ___/ ___/ __ `/ __ \/ __ `/ ___/ ___/
|
||||||
|
___/ / /__/ / / /_/ / /_/ / /_/ / / / /
|
||||||
|
/____/\___/_/ \__,_/ .___/\__,_/_/ /_/
|
||||||
|
/_/
|
6
ct/headers/zigbee2mqtt
Normal file
6
ct/headers/zigbee2mqtt
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
_____ _ __ ___ __ _______ ____________
|
||||||
|
/__ / (_)___ _/ /_ ___ ___ |__ \ / |/ / __ \/_ __/_ __/
|
||||||
|
/ / / / __ `/ __ \/ _ \/ _ \__/ // /|_/ / / / / / / / /
|
||||||
|
/ /__/ / /_/ / /_/ / __/ __/ __// / / / /_/ / / / / /
|
||||||
|
/____/_/\__, /_.___/\___/\___/____/_/ /_/\___\_\/_/ /_/
|
||||||
|
/____/
|
47
ct/itsmng.sh
47
ct/itsmng.sh
@ -1,47 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
|
|
||||||
# Copyright (c) 2021-2025 community-scripts ORG
|
|
||||||
# Author: Florianb63
|
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
|
||||||
# Source: https://itsm-ng.com/
|
|
||||||
|
|
||||||
APP="itsmng"
|
|
||||||
var_tags="${var_tags:-asset-management;foss}"
|
|
||||||
var_cpu="${var_cpu:-2}"
|
|
||||||
var_ram="${var_ram:-2048}"
|
|
||||||
var_disk="${var_disk:-10}"
|
|
||||||
var_os="${var_os:-debian}"
|
|
||||||
var_version="${var_version:-12}"
|
|
||||||
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/itsm-ng/config_db.php ]]; then
|
|
||||||
msg_error "No ${APP} Installation Found!"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
msg_info "Updating ${APP} LXC"
|
|
||||||
$STD apt-get update
|
|
||||||
$STD apt-get -y upgrade
|
|
||||||
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}${CL}"
|
|
@ -1,45 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
|
|
||||||
# Copyright (c) 2021-2025 tteck
|
|
||||||
# Author: tteck (tteckster)
|
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
|
||||||
# Source: https://jellyfin.org/
|
|
||||||
|
|
||||||
APP="Jellyfin"
|
|
||||||
var_tags="${var_tags:-media}"
|
|
||||||
var_cpu="${var_cpu:-2}"
|
|
||||||
var_ram="${var_ram:-2048}"
|
|
||||||
var_disk="${var_disk:-8}"
|
|
||||||
var_os="${var_os:-ubuntu}"
|
|
||||||
var_version="${var_version:-24.04}"
|
|
||||||
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 /usr/lib/jellyfin ]]; then
|
|
||||||
msg_error "No ${APP} Installation Found!"
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
msg_info "Updating ${APP} LXC"
|
|
||||||
$STD apt-get update
|
|
||||||
$STD apt-get -y upgrade
|
|
||||||
$STD apt-get -y --with-new-pkgs upgrade jellyfin jellyfin-server
|
|
||||||
msg_ok "Updated ${APP} LXC"
|
|
||||||
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}:8096${CL}"
|
|
@ -1,64 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
source <(curl -s https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/build.func)
|
|
||||||
# Copyright (c) 2021-2025 community-scripts ORG
|
|
||||||
# Author: Slaviša Arežina (tremor021)
|
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
|
||||||
# Source: https://github.com/Casvt/Kapowarr
|
|
||||||
|
|
||||||
APP="Kapowarr"
|
|
||||||
var_tags="${var_tags:-Arr}"
|
|
||||||
var_cpu="${var_cpu:-1}"
|
|
||||||
var_ram="${var_ram:-256}"
|
|
||||||
var_disk="${var_disk:-2}"
|
|
||||||
var_os="${var_os:-debian}"
|
|
||||||
var_version="${var_version:-12}"
|
|
||||||
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/kapowarr.service ]]; then
|
|
||||||
msg_error "No ${APP} Installation Found!"
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
RELEASE=$(curl -s https://api.github.com/repos/Casvt/Kapowarr/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }')
|
|
||||||
if [[ "${RELEASE}" != "$(cat $HOME/.kapowarr)" ]] || [[ ! -f $HOME/.kapowarr ]]; then
|
|
||||||
msg_info "Stopping $APP"
|
|
||||||
systemctl stop kapowarr
|
|
||||||
msg_ok "Stopped $APP"
|
|
||||||
|
|
||||||
msg_info "Creating Backup"
|
|
||||||
mv /opt/kapowarr/db /opt/
|
|
||||||
msg_ok "Backup Created"
|
|
||||||
|
|
||||||
msg_info "Updating $APP to ${RELEASE}"
|
|
||||||
fetch_and_deploy_gh_release "kapowarr" "Casvt/Kapowarr"
|
|
||||||
mv /opt/db /opt/kapowarr
|
|
||||||
msg_ok "Updated $APP to ${RELEASE}"
|
|
||||||
|
|
||||||
msg_info "Starting $APP"
|
|
||||||
systemctl start kapowarr
|
|
||||||
msg_ok "Started $APP"
|
|
||||||
|
|
||||||
msg_ok "Update Successful"
|
|
||||||
else
|
|
||||||
msg_ok "No update required. ${APP} is already at ${RELEASE}"
|
|
||||||
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}:5656${CL}"
|
|
@ -1,58 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
|
|
||||||
# Copyright (c) 2021-2025 community-scripts ORG
|
|
||||||
# Author: MickLesk (CanbiZ)
|
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
|
||||||
# Source: https://github.com/ZoeyVid/NPMplus
|
|
||||||
|
|
||||||
APP="NPMplus"
|
|
||||||
var_tags="${var_tags:-proxy;nginx}"
|
|
||||||
var_cpu="${var_cpu:-1}"
|
|
||||||
var_ram="${var_ram:-512}"
|
|
||||||
var_disk="${var_disk:-3}"
|
|
||||||
var_os="${var_os:-alpine}"
|
|
||||||
var_version="${var_version:-3.21}"
|
|
||||||
var_unprivileged="${var_unprivileged:-1}"
|
|
||||||
|
|
||||||
header_info "$APP"
|
|
||||||
variables
|
|
||||||
color
|
|
||||||
catch_errors
|
|
||||||
|
|
||||||
function update_script() {
|
|
||||||
UPD=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "UPDATE MODE" --radiolist --cancel-button Exit-Script "Spacebar = Select" 14 60 2 \
|
|
||||||
"1" "Check for Alpine Updates" OFF \
|
|
||||||
"2" "Update NPMplus Docker Container" ON \
|
|
||||||
3>&1 1>&2 2>&3)
|
|
||||||
|
|
||||||
header_info "$APP"
|
|
||||||
|
|
||||||
case "$UPD" in
|
|
||||||
"1")
|
|
||||||
msg_info "Updating Alpine OS"
|
|
||||||
$STD apk -U upgrade
|
|
||||||
msg_ok "System updated"
|
|
||||||
exit
|
|
||||||
;;
|
|
||||||
"2")
|
|
||||||
msg_info "Updating NPMplus Container"
|
|
||||||
cd /opt
|
|
||||||
msg_info "Pulling latest container image"
|
|
||||||
$STD docker compose pull
|
|
||||||
msg_info "Recreating container"
|
|
||||||
$STD docker compose up -d
|
|
||||||
msg_ok "NPMplus container updated"
|
|
||||||
exit
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
exit 0
|
|
||||||
}
|
|
||||||
|
|
||||||
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}https://${IP}:81${CL}"
|
|
66
ct/scraparr.sh
Normal file
66
ct/scraparr.sh
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
|
||||||
|
# Copyright (c) 2021-2025 community-scripts ORG
|
||||||
|
# Author: JasonGreenC
|
||||||
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||||
|
# Source: https://github.com/thecfu/scraparr
|
||||||
|
|
||||||
|
APP="Scraparr"
|
||||||
|
var_tags="${var_tags:-arr;monitoring}"
|
||||||
|
var_cpu="${var_cpu:-2}"
|
||||||
|
var_ram="${var_ram:-1024}"
|
||||||
|
var_disk="${var_disk:-4}"
|
||||||
|
var_os="${var_os:-debian}"
|
||||||
|
var_version="${var_version:-12}"
|
||||||
|
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/scraparr/ ]]; then
|
||||||
|
msg_error "No ${APP} Installation Found!"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
RELEASE=$(curl -fsSL https://api.github.com/repos/thecfu/scraparr/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
|
||||||
|
if [[ ! -f "${HOME}/.scrappar" ]] || [[ "${RELEASE}" != "$(cat "${HOME}"/.scrappar)" ]]; then
|
||||||
|
msg_info "Stopping Services"
|
||||||
|
systemctl stop scraparr
|
||||||
|
msg_ok "Services Stopped"
|
||||||
|
|
||||||
|
PYTHON_VERSION="3.12" setup_uv
|
||||||
|
fetch_and_deploy_gh_release "scrappar" "thecfu/scraparr" "tarball" "latest" "/opt/scraparr"
|
||||||
|
|
||||||
|
msg_info "Updating ${APP} to ${RELEASE}"
|
||||||
|
cd /opt/scraparr || exit
|
||||||
|
$STD uv venv /opt/scraparr/.venv
|
||||||
|
$STD /opt/scraparr/.venv/bin/python -m ensurepip --upgrade
|
||||||
|
$STD /opt/scraparr/.venv/bin/python -m pip install --upgrade pip
|
||||||
|
$STD /opt/scraparr/.venv/bin/python -m pip install -r /opt/scraparr/src/scraparr/requirements.txt
|
||||||
|
chmod -R 755 /opt/scraparr
|
||||||
|
msg_ok "Updated ${APP} to v${RELEASE}"
|
||||||
|
|
||||||
|
msg_info "Starting Services"
|
||||||
|
systemctl start scraparr
|
||||||
|
msg_ok "Services Started"
|
||||||
|
else
|
||||||
|
msg_ok "No update required. ${APP} is already at v${RELEASE}"
|
||||||
|
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}:7100${CL}"
|
90
ct/zigbee2mqtt.sh
Normal file
90
ct/zigbee2mqtt.sh
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
|
||||||
|
# Copyright (c) 2021-2025 tteck
|
||||||
|
# Author: tteck (tteckster)
|
||||||
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||||
|
# Source: https://www.zigbee2mqtt.io/
|
||||||
|
|
||||||
|
APP="Zigbee2MQTT"
|
||||||
|
var_tags="${var_tags:-smarthome;zigbee;mqtt}"
|
||||||
|
var_cpu="${var_cpu:-2}"
|
||||||
|
var_ram="${var_ram:-1024}"
|
||||||
|
var_disk="${var_disk:-4}"
|
||||||
|
var_os="${var_os:-debian}"
|
||||||
|
var_version="${var_version:-12}"
|
||||||
|
var_unprivileged="${var_unprivileged:-0}"
|
||||||
|
|
||||||
|
header_info "$APP"
|
||||||
|
variables
|
||||||
|
color
|
||||||
|
catch_errors
|
||||||
|
|
||||||
|
function update_script() {
|
||||||
|
header_info
|
||||||
|
check_container_storage
|
||||||
|
check_container_resources
|
||||||
|
if [[ ! -d /opt/zigbee2mqtt ]]; then
|
||||||
|
msg_error "No ${APP} Installation Found!"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -f ~/.zigbee2mqtt ]]; then
|
||||||
|
CURRENT="$(cat ~/.zigbee2mqtt)"
|
||||||
|
elif [[ -f /opt/${APP}_version.txt ]]; then
|
||||||
|
CURRENT="$(cat /opt/${APP}_version.txt)"
|
||||||
|
rm -f /opt/${APP}_version.txt
|
||||||
|
else
|
||||||
|
CURRENT=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
RELEASE=$(curl -fsSL https://api.github.com/repos/Koenkk/zigbee2mqtt/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }')
|
||||||
|
if [[ "$RELEASE" != "$CURRENT" ]]; then
|
||||||
|
if ! command -v jq &>/dev/null; then
|
||||||
|
$STD apt-get update
|
||||||
|
$STD apt-get install -y jq
|
||||||
|
fi
|
||||||
|
NODE_VERSION=24 NODE_MODULE="pnpm@$(curl -fsSL https://raw.githubusercontent.com/Koenkk/zigbee2mqtt/master/package.json | jq -r '.packageManager | split("@")[1]')" setup_nodejs
|
||||||
|
|
||||||
|
msg_info "Stopping Service"
|
||||||
|
systemctl stop zigbee2mqtt
|
||||||
|
msg_ok "Stopped Service"
|
||||||
|
|
||||||
|
msg_info "Creating Backup"
|
||||||
|
rm -rf /opt/${APP}_backup*.tar.gz
|
||||||
|
mkdir -p /opt/z2m_backup
|
||||||
|
$STD tar -czf /opt/z2m_backup/${APP}_backup_$(date +%Y%m%d%H%M%S).tar.gz -C /opt zigbee2mqtt
|
||||||
|
mv /opt/zigbee2mqtt/data /opt/z2m_backup
|
||||||
|
msg_ok "Backup Created"
|
||||||
|
|
||||||
|
fetch_and_deploy_gh_release "Zigbee2MQTT" "Koenkk/zigbee2mqtt" "tarball" "latest" "/opt/zigbee2mqtt"
|
||||||
|
|
||||||
|
msg_info "Updating ${APP} to v${RELEASE}"
|
||||||
|
rm -rf /opt/zigbee2mqtt/data
|
||||||
|
mv /opt/z2m_backup/data /opt/zigbee2mqtt
|
||||||
|
cd /opt/zigbee2mqtt
|
||||||
|
$STD pnpm install --frozen-lockfile
|
||||||
|
$STD pnpm build
|
||||||
|
msg_ok "Updated Zigbee2MQTT"
|
||||||
|
|
||||||
|
msg_info "Starting Service"
|
||||||
|
systemctl start zigbee2mqtt
|
||||||
|
msg_ok "Started Service"
|
||||||
|
|
||||||
|
msg_info "Cleaning up"
|
||||||
|
rm -rf /opt/z2m_backup
|
||||||
|
msg_ok "Cleaned up"
|
||||||
|
echo "${RELEASE}" >/opt/${APP}_version.txt
|
||||||
|
else
|
||||||
|
msg_ok "No update required. ${APP} is already at v${RELEASE}."
|
||||||
|
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}:9442${CL}"
|
35
frontend/public/json/docspell.json
Normal file
35
frontend/public/json/docspell.json
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"name": "Docspell",
|
||||||
|
"slug": "docspell",
|
||||||
|
"categories": [
|
||||||
|
12
|
||||||
|
],
|
||||||
|
"date_created": "2025-07-02",
|
||||||
|
"type": "ct",
|
||||||
|
"updateable": true,
|
||||||
|
"privileged": false,
|
||||||
|
"config_path": "/opt/docspell/.env",
|
||||||
|
"interface_port": 3000,
|
||||||
|
"documentation": "https://docspell.io/",
|
||||||
|
"website": "https://docspell.io/",
|
||||||
|
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/svg/docspell.svg",
|
||||||
|
"description": "Docspell is an open-source self-hosted application.",
|
||||||
|
"install_methods": [
|
||||||
|
{
|
||||||
|
"type": "default",
|
||||||
|
"script": "ct/docspell.sh",
|
||||||
|
"resources": {
|
||||||
|
"cpu": 1,
|
||||||
|
"ram": 1024,
|
||||||
|
"hdd": 2,
|
||||||
|
"os": "Debian",
|
||||||
|
"version": "12"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default_credentials": {
|
||||||
|
"username": null,
|
||||||
|
"password": null
|
||||||
|
},
|
||||||
|
"notes": []
|
||||||
|
}
|
35
frontend/public/json/frigate.json
Normal file
35
frontend/public/json/frigate.json
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"name": "Frigate",
|
||||||
|
"slug": "frigate",
|
||||||
|
"categories": [
|
||||||
|
15
|
||||||
|
],
|
||||||
|
"date_created": "2025-07-02",
|
||||||
|
"type": "ct",
|
||||||
|
"updateable": true,
|
||||||
|
"privileged": false,
|
||||||
|
"config_path": "/opt/frigate/.env",
|
||||||
|
"interface_port": 3000,
|
||||||
|
"documentation": "https://frigate.io/",
|
||||||
|
"website": "https://frigate.io/",
|
||||||
|
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/svg/frigate.svg",
|
||||||
|
"description": "Frigate is an open-source self-hosted application.",
|
||||||
|
"install_methods": [
|
||||||
|
{
|
||||||
|
"type": "default",
|
||||||
|
"script": "ct/frigate.sh",
|
||||||
|
"resources": {
|
||||||
|
"cpu": 1,
|
||||||
|
"ram": 1024,
|
||||||
|
"hdd": 2,
|
||||||
|
"os": "Debian",
|
||||||
|
"version": "12"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default_credentials": {
|
||||||
|
"username": null,
|
||||||
|
"password": null
|
||||||
|
},
|
||||||
|
"notes": []
|
||||||
|
}
|
35
frontend/public/json/hanko.json
Normal file
35
frontend/public/json/hanko.json
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"name": "Hanko",
|
||||||
|
"slug": "hanko",
|
||||||
|
"categories": [
|
||||||
|
21
|
||||||
|
],
|
||||||
|
"date_created": "2025-07-02",
|
||||||
|
"type": "ct",
|
||||||
|
"updateable": true,
|
||||||
|
"privileged": false,
|
||||||
|
"config_path": "/opt/hanko/.env",
|
||||||
|
"interface_port": 3000,
|
||||||
|
"documentation": "https://docs.hanko.io/",
|
||||||
|
"website": "https://hanko.io/",
|
||||||
|
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/svg/hanko.svg",
|
||||||
|
"description": "Hanko is an open-source authentication solution providing passkey-first login with support for WebAuthn/FIDO2, biometrics and modern identity flows. Easy to self-host and integrate via API or widget.",
|
||||||
|
"install_methods": [
|
||||||
|
{
|
||||||
|
"type": "default",
|
||||||
|
"script": "ct/hanko.sh",
|
||||||
|
"resources": {
|
||||||
|
"cpu": 1,
|
||||||
|
"ram": 1024,
|
||||||
|
"hdd": 2,
|
||||||
|
"os": "Debian",
|
||||||
|
"version": "12"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default_credentials": {
|
||||||
|
"username": null,
|
||||||
|
"password": null
|
||||||
|
},
|
||||||
|
"notes": []
|
||||||
|
}
|
35
frontend/public/json/healthchecks.json
Normal file
35
frontend/public/json/healthchecks.json
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"name": "Healthchecks",
|
||||||
|
"slug": "healthchecks",
|
||||||
|
"categories": [
|
||||||
|
9
|
||||||
|
],
|
||||||
|
"date_created": "2025-07-02",
|
||||||
|
"type": "ct",
|
||||||
|
"updateable": true,
|
||||||
|
"privileged": false,
|
||||||
|
"config_path": "/opt/healthchecks/.env",
|
||||||
|
"interface_port": 3000,
|
||||||
|
"documentation": "https://healthchecks.io/",
|
||||||
|
"website": "https://healthchecks.io/",
|
||||||
|
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/svg/healthchecks.svg",
|
||||||
|
"description": "Healthchecks is an open-source self-hosted application.",
|
||||||
|
"install_methods": [
|
||||||
|
{
|
||||||
|
"type": "default",
|
||||||
|
"script": "ct/healthchecks.sh",
|
||||||
|
"resources": {
|
||||||
|
"cpu": 1,
|
||||||
|
"ram": 1024,
|
||||||
|
"hdd": 2,
|
||||||
|
"os": "Debian",
|
||||||
|
"version": "12"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default_credentials": {
|
||||||
|
"username": null,
|
||||||
|
"password": null
|
||||||
|
},
|
||||||
|
"notes": []
|
||||||
|
}
|
@ -1,35 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "ITSMNG",
|
|
||||||
"slug": "itsmng",
|
|
||||||
"categories": [
|
|
||||||
25
|
|
||||||
],
|
|
||||||
"date_created": "2025-06-20",
|
|
||||||
"type": "ct",
|
|
||||||
"updateable": true,
|
|
||||||
"privileged": false,
|
|
||||||
"interface_port": 80,
|
|
||||||
"documentation": "https://wiki.itsm-ng.org/en/home",
|
|
||||||
"website": "https://itsm-ng.com",
|
|
||||||
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/svg/itsm-ng.svg",
|
|
||||||
"config_path": "/etc/itsm-ng",
|
|
||||||
"description": "ITSM-NG is a Free Asset and IT Management Software package, Data center management, ITIL Service Desk, licenses tracking and software auditing.",
|
|
||||||
"install_methods": [
|
|
||||||
{
|
|
||||||
"type": "default",
|
|
||||||
"script": "ct/itsmng.sh",
|
|
||||||
"resources": {
|
|
||||||
"cpu": 2,
|
|
||||||
"ram": 2048,
|
|
||||||
"hdd": 10,
|
|
||||||
"os": "debian",
|
|
||||||
"version": "12"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"default_credentials": {
|
|
||||||
"username": "itsm",
|
|
||||||
"password": "itsm"
|
|
||||||
},
|
|
||||||
"notes": []
|
|
||||||
}
|
|
@ -1,35 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "Kapowarr",
|
|
||||||
"slug": "kapowarr",
|
|
||||||
"categories": [
|
|
||||||
14
|
|
||||||
],
|
|
||||||
"date_created": "2025-06-09",
|
|
||||||
"type": "ct",
|
|
||||||
"updateable": true,
|
|
||||||
"privileged": false,
|
|
||||||
"interface_port": 5656,
|
|
||||||
"documentation": "https://casvt.github.io/Kapowarr/general_info/workings/",
|
|
||||||
"website": "https://casvt.github.io/Kapowarr/",
|
|
||||||
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/kapowarr.webp",
|
|
||||||
"config_path": "",
|
|
||||||
"description": "Kapowarr allows you to build a digital library of comics. You can add volumes, map them to a folder and start managing! Download, rename, move and convert issues of the volume (including TPB's, One Shots, Hard Covers, and more). The whole process is automated and can be customised in the settings.",
|
|
||||||
"install_methods": [
|
|
||||||
{
|
|
||||||
"type": "default",
|
|
||||||
"script": "ct/kapowarr.sh",
|
|
||||||
"resources": {
|
|
||||||
"cpu": 1,
|
|
||||||
"ram": 256,
|
|
||||||
"hdd": 2,
|
|
||||||
"os": "debian",
|
|
||||||
"version": "12"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"default_credentials": {
|
|
||||||
"username": null,
|
|
||||||
"password": null
|
|
||||||
},
|
|
||||||
"notes": []
|
|
||||||
}
|
|
35
frontend/public/json/maxun.json
Normal file
35
frontend/public/json/maxun.json
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"name": "Maxun",
|
||||||
|
"slug": "maxun",
|
||||||
|
"categories": [
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"date_created": "2025-07-02",
|
||||||
|
"type": "ct",
|
||||||
|
"updateable": true,
|
||||||
|
"privileged": false,
|
||||||
|
"config_path": "/opt/maxun/.env",
|
||||||
|
"interface_port": 3000,
|
||||||
|
"documentation": "https://maxun.io/",
|
||||||
|
"website": "https://maxun.io/",
|
||||||
|
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/svg/maxun.svg",
|
||||||
|
"description": "Maxun is an open-source self-hosted application.",
|
||||||
|
"install_methods": [
|
||||||
|
{
|
||||||
|
"type": "default",
|
||||||
|
"script": "ct/maxun.sh",
|
||||||
|
"resources": {
|
||||||
|
"cpu": 1,
|
||||||
|
"ram": 1024,
|
||||||
|
"hdd": 2,
|
||||||
|
"os": "Debian",
|
||||||
|
"version": "12"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default_credentials": {
|
||||||
|
"username": null,
|
||||||
|
"password": null
|
||||||
|
},
|
||||||
|
"notes": []
|
||||||
|
}
|
35
frontend/public/json/mealie.json
Normal file
35
frontend/public/json/mealie.json
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"name": "Mealie",
|
||||||
|
"slug": "mealie",
|
||||||
|
"categories": [
|
||||||
|
13
|
||||||
|
],
|
||||||
|
"date_created": "2025-07-02",
|
||||||
|
"type": "ct",
|
||||||
|
"updateable": true,
|
||||||
|
"privileged": false,
|
||||||
|
"config_path": "/opt/mealie/.env",
|
||||||
|
"interface_port": 3000,
|
||||||
|
"documentation": "https://mealie.io/",
|
||||||
|
"website": "https://mealie.io/",
|
||||||
|
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/svg/mealie.svg",
|
||||||
|
"description": "Mealie is an open-source self-hosted application.",
|
||||||
|
"install_methods": [
|
||||||
|
{
|
||||||
|
"type": "default",
|
||||||
|
"script": "ct/mealie.sh",
|
||||||
|
"resources": {
|
||||||
|
"cpu": 1,
|
||||||
|
"ram": 1024,
|
||||||
|
"hdd": 2,
|
||||||
|
"os": "Debian",
|
||||||
|
"version": "12"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default_credentials": {
|
||||||
|
"username": null,
|
||||||
|
"password": null
|
||||||
|
},
|
||||||
|
"notes": []
|
||||||
|
}
|
35
frontend/public/json/postiz.json
Normal file
35
frontend/public/json/postiz.json
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"name": "Postiz",
|
||||||
|
"slug": "postiz",
|
||||||
|
"categories": [
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"date_created": "2025-07-02",
|
||||||
|
"type": "ct",
|
||||||
|
"updateable": true,
|
||||||
|
"privileged": false,
|
||||||
|
"config_path": "/opt/postiz/.env",
|
||||||
|
"interface_port": 3000,
|
||||||
|
"documentation": "https://postiz.io/",
|
||||||
|
"website": "https://postiz.io/",
|
||||||
|
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/svg/postiz.svg",
|
||||||
|
"description": "Postiz is an open-source self-hosted application.",
|
||||||
|
"install_methods": [
|
||||||
|
{
|
||||||
|
"type": "default",
|
||||||
|
"script": "ct/postiz.sh",
|
||||||
|
"resources": {
|
||||||
|
"cpu": 1,
|
||||||
|
"ram": 1024,
|
||||||
|
"hdd": 2,
|
||||||
|
"os": "Debian",
|
||||||
|
"version": "12"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default_credentials": {
|
||||||
|
"username": null,
|
||||||
|
"password": null
|
||||||
|
},
|
||||||
|
"notes": []
|
||||||
|
}
|
35
frontend/public/json/saltmaster.json
Normal file
35
frontend/public/json/saltmaster.json
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"name": "Saltmaster",
|
||||||
|
"slug": "saltmaster",
|
||||||
|
"categories": [
|
||||||
|
1
|
||||||
|
],
|
||||||
|
"date_created": "2025-07-02",
|
||||||
|
"type": "ct",
|
||||||
|
"updateable": true,
|
||||||
|
"privileged": false,
|
||||||
|
"config_path": "/opt/saltmaster/.env",
|
||||||
|
"interface_port": 3000,
|
||||||
|
"documentation": "https://saltmaster.io/",
|
||||||
|
"website": "https://saltmaster.io/",
|
||||||
|
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/svg/saltmaster.svg",
|
||||||
|
"description": "Saltmaster is an open-source self-hosted application.",
|
||||||
|
"install_methods": [
|
||||||
|
{
|
||||||
|
"type": "default",
|
||||||
|
"script": "ct/saltmaster.sh",
|
||||||
|
"resources": {
|
||||||
|
"cpu": 1,
|
||||||
|
"ram": 1024,
|
||||||
|
"hdd": 2,
|
||||||
|
"os": "Debian",
|
||||||
|
"version": "12"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default_credentials": {
|
||||||
|
"username": null,
|
||||||
|
"password": null
|
||||||
|
},
|
||||||
|
"notes": []
|
||||||
|
}
|
40
frontend/public/json/scraparr.json
Normal file
40
frontend/public/json/scraparr.json
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
{
|
||||||
|
"name": "Scraparr",
|
||||||
|
"slug": "scraparr",
|
||||||
|
"categories": [
|
||||||
|
14
|
||||||
|
],
|
||||||
|
"date_created": "2024-05-02",
|
||||||
|
"type": "ct",
|
||||||
|
"updateable": true,
|
||||||
|
"privileged": false,
|
||||||
|
"interface_port": 7100,
|
||||||
|
"documentation": "https://github.com/thecfu/scraparr/blob/main/README.md",
|
||||||
|
"website": "https://github.com/thecfu/scraparr",
|
||||||
|
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/svg/scraparr-dark.svg",
|
||||||
|
"config_path": "/scraparr/config/config.yaml",
|
||||||
|
"description": "Scraparr is a Prometheus exporter for the *arr suite (Sonarr, Radarr, Lidarr, etc.). It provides metrics that can be scraped by Prometheus to monitor and visualize the health and performance of your *arr applications.",
|
||||||
|
"install_methods": [
|
||||||
|
{
|
||||||
|
"type": "default",
|
||||||
|
"script": "ct/scraparr.sh",
|
||||||
|
"resources": {
|
||||||
|
"cpu": 2,
|
||||||
|
"ram": 1024,
|
||||||
|
"hdd": 4,
|
||||||
|
"os": "debian",
|
||||||
|
"version": "12"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default_credentials": {
|
||||||
|
"username": null,
|
||||||
|
"password": null
|
||||||
|
},
|
||||||
|
"notes": [
|
||||||
|
{
|
||||||
|
"text": "Edit config file then restart the scraparr service: `systemctl restart scraparr`",
|
||||||
|
"type": "info"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -1,19 +1,244 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"name": "wazuh/wazuh",
|
||||||
|
"version": "coverity-w27-4.13.0",
|
||||||
|
"date": "2025-07-01T03:17:32Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "glpi-project/glpi",
|
||||||
|
"version": "10.0.18",
|
||||||
|
"date": "2025-02-12T11:07:02Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "emqx/emqx",
|
||||||
|
"version": "e5.9.1",
|
||||||
|
"date": "2025-07-02T08:11:50Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "apache/tomcat",
|
||||||
|
"version": "9.0.107",
|
||||||
|
"date": "2025-07-02T07:12:09Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "nzbgetcom/nzbget",
|
||||||
|
"version": "v25.1",
|
||||||
|
"date": "2025-06-27T09:14:14Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "qbittorrent/qBittorrent",
|
||||||
|
"version": "release-5.1.2",
|
||||||
|
"date": "2025-07-02T06:13:16Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "home-assistant/core",
|
||||||
|
"version": "2025.6.3",
|
||||||
|
"date": "2025-06-24T13:00:12Z"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Jackett/Jackett",
|
"name": "Jackett/Jackett",
|
||||||
"version": "v0.22.2075",
|
"version": "v0.22.2107",
|
||||||
"date": "2025-06-28T10:16:17Z"
|
"date": "2025-07-02T05:53:02Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "firefly-iii/firefly-iii",
|
||||||
|
"version": "v6.2.20",
|
||||||
|
"date": "2025-07-02T04:03:37Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "diced/zipline",
|
||||||
|
"version": "v4.2.0",
|
||||||
|
"date": "2025-07-02T00:45:31Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "sysadminsmedia/homebox",
|
||||||
|
"version": "v0.20.2",
|
||||||
|
"date": "2025-07-02T00:37:07Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "hyperion-project/hyperion.ng",
|
||||||
|
"version": "2.1.1",
|
||||||
|
"date": "2025-06-14T17:45:06Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mongodb/mongo",
|
||||||
|
"version": "r8.1.2",
|
||||||
|
"date": "2025-07-01T22:39:32Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Threadfin/Threadfin",
|
||||||
|
"version": "1.2.35",
|
||||||
|
"date": "2025-07-01T21:37:20Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "actualbudget/actual",
|
||||||
|
"version": "v25.7.0",
|
||||||
|
"date": "2025-07-01T21:02:27Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "TwiN/gatus",
|
||||||
|
"version": "v5.19.0",
|
||||||
|
"date": "2025-07-01T19:59:32Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Koenkk/zigbee2mqtt",
|
||||||
|
"version": "2.5.0",
|
||||||
|
"date": "2025-07-01T18:28:01Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "keycloak/keycloak",
|
||||||
|
"version": "26.3.0",
|
||||||
|
"date": "2025-07-01T13:18:12Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "hivemq/hivemq-community-edition",
|
||||||
|
"version": "2025.4",
|
||||||
|
"date": "2025-07-01T18:01:37Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "HabitRPG/habitica",
|
||||||
|
"version": "v5.37.1",
|
||||||
|
"date": "2025-07-01T16:57:43Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "navidrome/navidrome",
|
||||||
|
"version": "v0.57.0",
|
||||||
|
"date": "2025-07-01T16:47:46Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "jenkinsci/jenkins",
|
||||||
|
"version": "jenkins-2.517",
|
||||||
|
"date": "2025-07-01T16:08:23Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "element-hq/synapse",
|
||||||
|
"version": "v1.133.0",
|
||||||
|
"date": "2025-07-01T15:13:42Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "syncthing/syncthing",
|
||||||
|
"version": "v1.30.0",
|
||||||
|
"date": "2025-07-01T11:29:11Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Checkmk/checkmk",
|
||||||
|
"version": "v2.2.0p44-rc1",
|
||||||
|
"date": "2025-07-01T11:10:25Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "rcourtman/Pulse",
|
||||||
|
"version": "v99.99.99",
|
||||||
|
"date": "2025-07-01T08:26:41Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "zabbix/zabbix",
|
||||||
|
"version": "7.4.0",
|
||||||
|
"date": "2025-07-01T04:36:51Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "openobserve/openobserve",
|
||||||
|
"version": "v0.15.0-rc3",
|
||||||
|
"date": "2025-07-01T04:09:37Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "NginxProxyManager/nginx-proxy-manager",
|
||||||
|
"version": "v2.12.4",
|
||||||
|
"date": "2025-07-01T01:45:42Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "MagicMirrorOrg/MagicMirror",
|
||||||
|
"version": "v2.32.0",
|
||||||
|
"date": "2025-06-30T22:12:48Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "docker/compose",
|
||||||
|
"version": "v2.38.1",
|
||||||
|
"date": "2025-06-30T20:07:35Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "jhuckaby/Cronicle",
|
||||||
|
"version": "v0.9.81",
|
||||||
|
"date": "2025-06-30T16:40:33Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ollama/ollama",
|
||||||
|
"version": "v0.9.4-rc6",
|
||||||
|
"date": "2025-06-30T15:59:03Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "prometheus/prometheus",
|
||||||
|
"version": "v2.53.5",
|
||||||
|
"date": "2025-06-30T11:01:12Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "n8n-io/n8n",
|
||||||
|
"version": "n8n@1.100.0",
|
||||||
|
"date": "2025-06-23T12:48:35Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "jupyter/notebook",
|
||||||
|
"version": "v7.4.4",
|
||||||
|
"date": "2025-06-30T13:04:22Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Graylog2/graylog2-server",
|
||||||
|
"version": "6.3.0",
|
||||||
|
"date": "2025-06-30T11:26:45Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "grokability/snipe-it",
|
||||||
|
"version": "v8.1.17",
|
||||||
|
"date": "2025-06-30T11:26:27Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "documenso/documenso",
|
||||||
|
"version": "v1.12.0-rc.8",
|
||||||
|
"date": "2025-06-30T09:47:37Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "PrivateBin/PrivateBin",
|
||||||
|
"version": "1.7.8",
|
||||||
|
"date": "2025-06-30T09:00:54Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "fuma-nama/fumadocs",
|
||||||
|
"version": "fumadocs-mdx@11.6.10",
|
||||||
|
"date": "2025-06-30T07:07:36Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mattermost/mattermost",
|
||||||
|
"version": "preview-v0.1",
|
||||||
|
"date": "2025-06-27T14:35:47Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "typesense/typesense",
|
||||||
|
"version": "v29.0",
|
||||||
|
"date": "2025-06-30T03:52:33Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "dgtlmoon/changedetection.io",
|
||||||
|
"version": "0.50.5",
|
||||||
|
"date": "2025-06-29T08:54:47Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "theonedev/onedev",
|
||||||
|
"version": "v11.11.2",
|
||||||
|
"date": "2025-06-29T01:40:39Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "linkwarden/linkwarden",
|
||||||
|
"version": "v2.11.2",
|
||||||
|
"date": "2025-06-28T17:33:38Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "msgbyte/tianji",
|
||||||
|
"version": "v1.22.5",
|
||||||
|
"date": "2025-06-28T16:06:19Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Luligu/matterbridge",
|
"name": "Luligu/matterbridge",
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"date": "2025-06-28T09:02:38Z"
|
"date": "2025-06-28T09:02:38Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "firefly-iii/firefly-iii",
|
|
||||||
"version": "v6.2.19",
|
|
||||||
"date": "2025-06-28T06:53:45Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "esphome/esphome",
|
"name": "esphome/esphome",
|
||||||
"version": "2025.6.2",
|
"version": "2025.6.2",
|
||||||
@ -34,51 +259,21 @@
|
|||||||
"version": "v1.5.0",
|
"version": "v1.5.0",
|
||||||
"date": "2025-06-27T22:04:32Z"
|
"date": "2025-06-27T22:04:32Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "linkwarden/linkwarden",
|
|
||||||
"version": "v2.11.1",
|
|
||||||
"date": "2025-06-27T21:21:59Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "homarr-labs/homarr",
|
"name": "homarr-labs/homarr",
|
||||||
"version": "v1.26.0",
|
"version": "v1.26.0",
|
||||||
"date": "2025-06-27T19:15:24Z"
|
"date": "2025-06-27T19:15:24Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "ollama/ollama",
|
|
||||||
"version": "v0.9.4-rc1",
|
|
||||||
"date": "2025-06-27T18:45:33Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "home-assistant/core",
|
|
||||||
"version": "2025.6.3",
|
|
||||||
"date": "2025-06-24T13:00:12Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "mattermost/mattermost",
|
|
||||||
"version": "preview-v0.1",
|
|
||||||
"date": "2025-06-27T14:35:47Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "goauthentik/authentik",
|
"name": "goauthentik/authentik",
|
||||||
"version": "version/2025.6.3",
|
"version": "version/2025.6.3",
|
||||||
"date": "2025-06-27T14:01:06Z"
|
"date": "2025-06-27T14:01:06Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "keycloak/keycloak",
|
|
||||||
"version": "26.2.5",
|
|
||||||
"date": "2025-05-28T06:49:43Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "rclone/rclone",
|
"name": "rclone/rclone",
|
||||||
"version": "v1.70.2",
|
"version": "v1.70.2",
|
||||||
"date": "2025-06-27T13:21:17Z"
|
"date": "2025-06-27T13:21:17Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "documenso/documenso",
|
|
||||||
"version": "v1.12.0-rc.7",
|
|
||||||
"date": "2025-06-27T12:17:45Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "sabnzbd/sabnzbd",
|
"name": "sabnzbd/sabnzbd",
|
||||||
"version": "4.5.1",
|
"version": "4.5.1",
|
||||||
@ -89,31 +284,16 @@
|
|||||||
"version": "flowise@3.0.3",
|
"version": "flowise@3.0.3",
|
||||||
"date": "2025-06-27T09:53:57Z"
|
"date": "2025-06-27T09:53:57Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "nzbgetcom/nzbget",
|
|
||||||
"version": "v25.1",
|
|
||||||
"date": "2025-06-27T09:14:14Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "cockpit-project/cockpit",
|
"name": "cockpit-project/cockpit",
|
||||||
"version": "341.1",
|
"version": "341.1",
|
||||||
"date": "2025-06-27T08:50:16Z"
|
"date": "2025-06-27T08:50:16Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "zabbix/zabbix",
|
|
||||||
"version": "7.2.10",
|
|
||||||
"date": "2025-06-27T06:40:00Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "MediaBrowser/Emby.Releases",
|
"name": "MediaBrowser/Emby.Releases",
|
||||||
"version": "4.9.1.2",
|
"version": "4.9.1.2",
|
||||||
"date": "2025-06-26T22:08:00Z"
|
"date": "2025-06-26T22:08:00Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "prometheus/prometheus",
|
|
||||||
"version": "v3.4.2",
|
|
||||||
"date": "2025-06-26T21:45:21Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "home-assistant/operating-system",
|
"name": "home-assistant/operating-system",
|
||||||
"version": "15.2",
|
"version": "15.2",
|
||||||
@ -134,11 +314,6 @@
|
|||||||
"version": "v1.84.3",
|
"version": "v1.84.3",
|
||||||
"date": "2025-06-26T16:31:57Z"
|
"date": "2025-06-26T16:31:57Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "fuma-nama/fumadocs",
|
|
||||||
"version": "fumadocs-ui@15.5.5",
|
|
||||||
"date": "2025-06-26T15:54:17Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "traefik/traefik",
|
"name": "traefik/traefik",
|
||||||
"version": "v3.5.0-rc1",
|
"version": "v3.5.0-rc1",
|
||||||
@ -164,16 +339,6 @@
|
|||||||
"version": "18.0.7",
|
"version": "18.0.7",
|
||||||
"date": "2025-06-26T09:16:33Z"
|
"date": "2025-06-26T09:16:33Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "mongodb/mongo",
|
|
||||||
"version": "r8.1.2-rc1",
|
|
||||||
"date": "2025-06-25T22:42:04Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "rcourtman/Pulse",
|
|
||||||
"version": "v3.32.0",
|
|
||||||
"date": "2025-06-25T22:27:01Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "gristlabs/grist-core",
|
"name": "gristlabs/grist-core",
|
||||||
"version": "v1.6.1",
|
"version": "v1.6.1",
|
||||||
@ -184,11 +349,6 @@
|
|||||||
"version": "v4.101.2",
|
"version": "v4.101.2",
|
||||||
"date": "2025-06-25T21:18:52Z"
|
"date": "2025-06-25T21:18:52Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "msgbyte/tianji",
|
|
||||||
"version": "v1.22.4",
|
|
||||||
"date": "2025-06-25T20:46:20Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "influxdata/influxdb",
|
"name": "influxdata/influxdb",
|
||||||
"version": "v3.2.0",
|
"version": "v3.2.0",
|
||||||
@ -199,21 +359,11 @@
|
|||||||
"version": "2.0.5",
|
"version": "2.0.5",
|
||||||
"date": "2025-06-25T14:53:31Z"
|
"date": "2025-06-25T14:53:31Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "jenkinsci/jenkins",
|
|
||||||
"version": "jenkins-2.504.3",
|
|
||||||
"date": "2025-06-25T14:43:01Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "bunkerity/bunkerweb",
|
"name": "bunkerity/bunkerweb",
|
||||||
"version": "testing",
|
"version": "testing",
|
||||||
"date": "2025-06-16T18:10:42Z"
|
"date": "2025-06-16T18:10:42Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "n8n-io/n8n",
|
|
||||||
"version": "n8n@1.100.0",
|
|
||||||
"date": "2025-06-23T12:48:35Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "moghtech/komodo",
|
"name": "moghtech/komodo",
|
||||||
"version": "v1.18.4",
|
"version": "v1.18.4",
|
||||||
@ -239,31 +389,11 @@
|
|||||||
"version": "v2.18.0",
|
"version": "v2.18.0",
|
||||||
"date": "2025-06-24T08:29:55Z"
|
"date": "2025-06-24T08:29:55Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "element-hq/synapse",
|
|
||||||
"version": "v1.132.0",
|
|
||||||
"date": "2025-06-17T13:49:30Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "docker/compose",
|
|
||||||
"version": "v2.37.3",
|
|
||||||
"date": "2025-06-24T14:05:33Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Checkmk/checkmk",
|
|
||||||
"version": "v2.4.0p5",
|
|
||||||
"date": "2025-06-24T13:06:53Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "fallenbagel/jellyseerr",
|
"name": "fallenbagel/jellyseerr",
|
||||||
"version": "preview-fix-proxy-axios",
|
"version": "preview-fix-proxy-axios",
|
||||||
"date": "2025-06-24T08:50:22Z"
|
"date": "2025-06-24T08:50:22Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "wazuh/wazuh",
|
|
||||||
"version": "coverity-w26-4.13.0",
|
|
||||||
"date": "2025-06-24T02:02:34Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "minio/minio",
|
"name": "minio/minio",
|
||||||
"version": "RELEASE.2025-06-13T11-33-47Z",
|
"version": "RELEASE.2025-06-13T11-33-47Z",
|
||||||
@ -279,11 +409,6 @@
|
|||||||
"version": "pmm-6401-v1.120.0",
|
"version": "pmm-6401-v1.120.0",
|
||||||
"date": "2025-06-23T15:12:12Z"
|
"date": "2025-06-23T15:12:12Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "Graylog2/graylog2-server",
|
|
||||||
"version": "6.3.0-rc.2",
|
|
||||||
"date": "2025-06-23T11:31:38Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "gotson/komga",
|
"name": "gotson/komga",
|
||||||
"version": "1.22.0",
|
"version": "1.22.0",
|
||||||
@ -294,11 +419,6 @@
|
|||||||
"version": "2025.6.22",
|
"version": "2025.6.22",
|
||||||
"date": "2025-06-22T22:41:11Z"
|
"date": "2025-06-22T22:41:11Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "qbittorrent/qBittorrent",
|
|
||||||
"version": "release-5.1.1",
|
|
||||||
"date": "2025-06-22T21:41:17Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "clusterzx/paperless-ai",
|
"name": "clusterzx/paperless-ai",
|
||||||
"version": "v3.0.7",
|
"version": "v3.0.7",
|
||||||
@ -314,31 +434,16 @@
|
|||||||
"version": "0.17.14",
|
"version": "0.17.14",
|
||||||
"date": "2025-06-21T23:43:04Z"
|
"date": "2025-06-21T23:43:04Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "HabitRPG/habitica",
|
|
||||||
"version": "v5.37.0",
|
|
||||||
"date": "2025-06-21T14:05:12Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "rogerfar/rdt-client",
|
"name": "rogerfar/rdt-client",
|
||||||
"version": "v2.0.114",
|
"version": "v2.0.114",
|
||||||
"date": "2025-06-21T11:20:21Z"
|
"date": "2025-06-21T11:20:21Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "theonedev/onedev",
|
|
||||||
"version": "v11.11.1",
|
|
||||||
"date": "2025-06-21T09:23:39Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "pocketbase/pocketbase",
|
"name": "pocketbase/pocketbase",
|
||||||
"version": "v0.28.4",
|
"version": "v0.28.4",
|
||||||
"date": "2025-06-21T08:29:04Z"
|
"date": "2025-06-21T08:29:04Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "dgtlmoon/changedetection.io",
|
|
||||||
"version": "0.50.4",
|
|
||||||
"date": "2025-06-21T07:47:02Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "go-gitea/gitea",
|
"name": "go-gitea/gitea",
|
||||||
"version": "v1.24.2",
|
"version": "v1.24.2",
|
||||||
@ -354,11 +459,6 @@
|
|||||||
"version": "v4.0.15.2941",
|
"version": "v4.0.15.2941",
|
||||||
"date": "2025-06-20T17:20:54Z"
|
"date": "2025-06-20T17:20:54Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "syncthing/syncthing",
|
|
||||||
"version": "2.0.0-rc.19",
|
|
||||||
"date": "2025-06-02T17:56:25Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "benzino77/tasmocompiler",
|
"name": "benzino77/tasmocompiler",
|
||||||
"version": "v12.7.0",
|
"version": "v12.7.0",
|
||||||
@ -389,79 +489,9 @@
|
|||||||
"version": "v3.5.5",
|
"version": "v3.5.5",
|
||||||
"date": "2025-06-19T05:43:47Z"
|
"date": "2025-06-19T05:43:47Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "docmost/docmost",
|
|
||||||
"version": "v0.21.0",
|
|
||||||
"date": "2025-06-18T21:43:27Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "ipfs/kubo",
|
"name": "ipfs/kubo",
|
||||||
"version": "v0.35.0",
|
"version": "v0.35.0",
|
||||||
"date": "2025-05-21T18:00:32Z"
|
"date": "2025-05-21T18:00:32Z"
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "pterodactyl/panel",
|
|
||||||
"version": "v1.11.11",
|
|
||||||
"date": "2025-06-18T18:04:50Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "NodeBB/NodeBB",
|
|
||||||
"version": "v3.12.7",
|
|
||||||
"date": "2025-06-18T14:22:53Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "openhab/openhab-core",
|
|
||||||
"version": "5.0.0.M3",
|
|
||||||
"date": "2025-06-18T14:18:12Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Bubka/2FAuth",
|
|
||||||
"version": "v5.6.0",
|
|
||||||
"date": "2025-06-18T12:19:54Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "zwave-js/zwave-js-ui",
|
|
||||||
"version": "v10.7.0",
|
|
||||||
"date": "2025-06-18T11:57:05Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "forgejo/forgejo",
|
|
||||||
"version": "v11.0.2",
|
|
||||||
"date": "2025-06-18T09:38:19Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "silverbulletmd/silverbullet",
|
|
||||||
"version": "2.0.0-pre3",
|
|
||||||
"date": "2025-06-18T08:01:24Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "cross-seed/cross-seed",
|
|
||||||
"version": "v6.12.7",
|
|
||||||
"date": "2025-06-18T03:44:24Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "grafana/grafana",
|
|
||||||
"version": "v11.5.6",
|
|
||||||
"date": "2025-06-17T22:00:40Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "project-zot/zot",
|
|
||||||
"version": "v2.1.5",
|
|
||||||
"date": "2025-06-17T18:04:11Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "BookStackApp/BookStack",
|
|
||||||
"version": "v25.05.1",
|
|
||||||
"date": "2025-06-17T14:38:04Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "cloudflare/cloudflared",
|
|
||||||
"version": "2025.6.1",
|
|
||||||
"date": "2025-06-17T12:45:39Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "crowdsecurity/crowdsec",
|
|
||||||
"version": "v1.6.9",
|
|
||||||
"date": "2025-06-17T11:54:50Z"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
35
frontend/public/json/wallabag.json
Normal file
35
frontend/public/json/wallabag.json
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"name": "Wallabag",
|
||||||
|
"slug": "wallabag",
|
||||||
|
"categories": [
|
||||||
|
12
|
||||||
|
],
|
||||||
|
"date_created": "2025-07-02",
|
||||||
|
"type": "ct",
|
||||||
|
"updateable": true,
|
||||||
|
"privileged": false,
|
||||||
|
"config_path": "/opt/wallabag/.env",
|
||||||
|
"interface_port": 3000,
|
||||||
|
"documentation": "https://wallabag.io/",
|
||||||
|
"website": "https://wallabag.io/",
|
||||||
|
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/svg/wallabag.svg",
|
||||||
|
"description": "Wallabag is an open-source self-hosted application.",
|
||||||
|
"install_methods": [
|
||||||
|
{
|
||||||
|
"type": "default",
|
||||||
|
"script": "ct/wallabag.sh",
|
||||||
|
"resources": {
|
||||||
|
"cpu": 1,
|
||||||
|
"ram": 1024,
|
||||||
|
"hdd": 2,
|
||||||
|
"os": "Debian",
|
||||||
|
"version": "12"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default_credentials": {
|
||||||
|
"username": null,
|
||||||
|
"password": null
|
||||||
|
},
|
||||||
|
"notes": []
|
||||||
|
}
|
@ -1,29 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# Copyright (c) 2021-2025 community-scripts ORG
|
|
||||||
# Author: MickLesk (CanbiZ)
|
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
|
||||||
# Source: https://syncthing.net/
|
|
||||||
|
|
||||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
|
||||||
color
|
|
||||||
verb_ip6
|
|
||||||
catch_errors
|
|
||||||
setting_up_container
|
|
||||||
network_check
|
|
||||||
update_os
|
|
||||||
|
|
||||||
msg_info "Setup Syncthing"
|
|
||||||
$STD apk add --no-cache syncthing
|
|
||||||
msg_ok "Setup Syncthing"
|
|
||||||
|
|
||||||
msg_info "Enabling Syncthing Service"
|
|
||||||
$STD rc-update add syncthing default
|
|
||||||
msg_ok "Enabled Syncthing Service"
|
|
||||||
|
|
||||||
msg_info "Starting Syncthing"
|
|
||||||
$STD rc-service syncthing start
|
|
||||||
msg_ok "Started Syncthing"
|
|
||||||
|
|
||||||
motd_ssh
|
|
||||||
customize
|
|
@ -17,6 +17,8 @@ msg_info "Installing Dependencies"
|
|||||||
$STD apt-get install -y gpg
|
$STD apt-get install -y gpg
|
||||||
msg_ok "Installed Dependencies"
|
msg_ok "Installed Dependencies"
|
||||||
|
|
||||||
|
#FFMPEG_VERSION="n7.1.1" FFMPEG_TYPE="full" setup_ffmpeg
|
||||||
|
|
||||||
#fetch_and_deploy_gh_release "argus" "release-argus/Argus" "singlefile" "latest" "/opt/argus" "Argus-.*linux-amd64"
|
#fetch_and_deploy_gh_release "argus" "release-argus/Argus" "singlefile" "latest" "/opt/argus" "Argus-.*linux-amd64"
|
||||||
#fetch_and_deploy_gh_release "planka" "plankanban/planka" "prebuild" "latest" "/opt/planka" "planka-prebuild.zip"
|
#fetch_and_deploy_gh_release "planka" "plankanban/planka" "prebuild" "latest" "/opt/planka" "planka-prebuild.zip"
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
# Copyright (c) 2021-2025 tteck
|
# Copyright (c) 2021-2025 community-scripts ORG
|
||||||
# Author: tteck (tteckster)
|
# Author: MickLesk (CanbiZ)
|
||||||
# License: MIT
|
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
||||||
# https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
# Source: https://hanko.io/
|
||||||
|
|
||||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
||||||
color
|
color
|
||||||
|
@ -1,77 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# Copyright (c) 2021-2025 community-scripts ORG
|
|
||||||
# Author: Florianb63
|
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
|
||||||
# Source: https://itsm-ng.com/
|
|
||||||
|
|
||||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
|
||||||
color
|
|
||||||
verb_ip6
|
|
||||||
catch_errors
|
|
||||||
setting_up_container
|
|
||||||
network_check
|
|
||||||
update_os
|
|
||||||
|
|
||||||
setup_mariadb
|
|
||||||
|
|
||||||
msg_info "Installing Repository"
|
|
||||||
curl -fsSL http://deb.itsm-ng.org/pubkey.gpg | gpg --dearmor -o /etc/apt/trusted.gpg.d/itsm-ng-keyring.gpg
|
|
||||||
echo "deb http://deb.itsm-ng.org/$(. /etc/os-release && echo "$ID")/ $(. /etc/os-release && echo "$VERSION_CODENAME") main" > /etc/apt/sources.list.d/itsm-ng.list
|
|
||||||
$STD apt update
|
|
||||||
msg_ok "Installed Repository"
|
|
||||||
|
|
||||||
msg_info "Installing ITSM-NG"
|
|
||||||
$STD apt install -y itsm-ng
|
|
||||||
msg_ok "Installed ITSM-NG"
|
|
||||||
|
|
||||||
msg_info "Setting up database"
|
|
||||||
DB_NAME=itsmng_db
|
|
||||||
DB_USER=itsmng
|
|
||||||
DB_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13)
|
|
||||||
mariadb-tzinfo-to-sql /usr/share/zoneinfo | mysql mysql
|
|
||||||
mariadb -u root -e "CREATE DATABASE $DB_NAME;"
|
|
||||||
mariadb -u root -e "CREATE USER '$DB_USER'@'localhost' IDENTIFIED BY '$DB_PASS';"
|
|
||||||
mariadb -u root -e "GRANT ALL PRIVILEGES ON $DB_NAME.* TO '$DB_USER'@'localhost';"
|
|
||||||
mariadb -u root -e "GRANT SELECT ON \`mysql\`.\`time_zone_name\` TO '$DB_USER'@'localhost'; FLUSH PRIVILEGES;"
|
|
||||||
{
|
|
||||||
echo "ITSM-NG Database Credentials"
|
|
||||||
echo "Database: $DB_NAME"
|
|
||||||
echo "Username: $DB_USER"
|
|
||||||
echo "Password: $DB_PASS"
|
|
||||||
} >>~/itsmng_db.creds
|
|
||||||
msg_ok "Set up database"
|
|
||||||
|
|
||||||
msg_info "Installing ITSM-NG"
|
|
||||||
cd /usr/share/itsm-ng
|
|
||||||
$STD php bin/console db:install --db-name=$DB_NAME --db-user=$DB_USER --db-password=$DB_PASS --no-interaction
|
|
||||||
msg_ok "Installed ITSM-NG"
|
|
||||||
|
|
||||||
msg_info "Configuring webserver"
|
|
||||||
$STD a2dissite 000-default.conf
|
|
||||||
msg_ok "Setup Service"
|
|
||||||
|
|
||||||
msg_info "Setup Cronjob"
|
|
||||||
echo "* * * * * php /usr/share/itsm-ng/front/cron.php" | crontab -
|
|
||||||
msg_ok "Setup Cronjob"
|
|
||||||
|
|
||||||
msg_info "Update PHP Params"
|
|
||||||
PHP_VERSION=$(ls /etc/php/ | grep -E '^[0-9]+\.[0-9]+$' | head -n 1)
|
|
||||||
PHP_INI="/etc/php/$PHP_VERSION/apache2/php.ini"
|
|
||||||
sed -i 's/^upload_max_filesize = .*/upload_max_filesize = 20M/' $PHP_INI
|
|
||||||
sed -i 's/^post_max_size = .*/post_max_size = 20M/' $PHP_INI
|
|
||||||
sed -i 's/^max_execution_time = .*/max_execution_time = 60/' $PHP_INI
|
|
||||||
sed -i 's/^max_input_vars = .*/max_input_vars = 5000/' $PHP_INI
|
|
||||||
sed -i 's/^memory_limit = .*/memory_limit = 256M/' $PHP_INI
|
|
||||||
sed -i 's/^;\?\s*session.cookie_httponly\s*=.*/session.cookie_httponly = On/' $PHP_INI
|
|
||||||
systemctl restart apache2
|
|
||||||
msg_ok "Update PHP Params"
|
|
||||||
|
|
||||||
motd_ssh
|
|
||||||
customize
|
|
||||||
|
|
||||||
msg_info "Cleaning up"
|
|
||||||
rm -rf /usr/share/itsm-ng/install
|
|
||||||
$STD apt-get -y autoremove
|
|
||||||
$STD apt-get -y autoclean
|
|
||||||
msg_ok "Cleaned"
|
|
@ -1,64 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# Copyright (c) 2021-2025 tteck
|
|
||||||
# Author: tteck (tteckster)
|
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
|
||||||
# Source: https://jellyfin.org/
|
|
||||||
|
|
||||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
|
||||||
color
|
|
||||||
verb_ip6
|
|
||||||
catch_errors
|
|
||||||
setting_up_container
|
|
||||||
network_check
|
|
||||||
update_os
|
|
||||||
|
|
||||||
msg_info "Setting Up Hardware Acceleration"
|
|
||||||
$STD apt-get -y install {va-driver-all,ocl-icd-libopencl1,intel-opencl-icd,vainfo,intel-gpu-tools}
|
|
||||||
if [[ "$CTTYPE" == "0" ]]; then
|
|
||||||
chgrp video /dev/dri
|
|
||||||
chmod 755 /dev/dri
|
|
||||||
chmod 660 /dev/dri/*
|
|
||||||
$STD adduser $(id -u -n) video
|
|
||||||
$STD adduser $(id -u -n) render
|
|
||||||
fi
|
|
||||||
msg_ok "Set Up Hardware Acceleration"
|
|
||||||
|
|
||||||
msg_info "Installing Jellyfin"
|
|
||||||
VERSION="$(awk -F'=' '/^VERSION_CODENAME=/{ print $NF }' /etc/os-release)"
|
|
||||||
# If the keyring directory is absent, create it
|
|
||||||
if [[ ! -d /etc/apt/keyrings ]]; then
|
|
||||||
mkdir -p /etc/apt/keyrings
|
|
||||||
fi
|
|
||||||
# Download the repository signing key and install it to the keyring directory
|
|
||||||
curl -fsSL https://repo.jellyfin.org/jellyfin_team.gpg.key | gpg --dearmor --yes --output /etc/apt/keyrings/jellyfin.gpg
|
|
||||||
# Install the Deb822 format jellyfin.sources entry
|
|
||||||
cat <<EOF >/etc/apt/sources.list.d/jellyfin.sources
|
|
||||||
Types: deb
|
|
||||||
URIs: https://repo.jellyfin.org/${PCT_OSTYPE}
|
|
||||||
Suites: ${VERSION}
|
|
||||||
Components: main
|
|
||||||
Architectures: amd64
|
|
||||||
Signed-By: /etc/apt/keyrings/jellyfin.gpg
|
|
||||||
EOF
|
|
||||||
# Install Jellyfin using the metapackage (which will fetch jellyfin-server, jellyfin-web, and jellyfin-ffmpeg5)
|
|
||||||
$STD apt-get update
|
|
||||||
$STD apt-get install -y jellyfin
|
|
||||||
sed -i 's/"MinimumLevel": "Information"/"MinimumLevel": "Error"/g' /etc/jellyfin/logging.json
|
|
||||||
chown -R jellyfin:adm /etc/jellyfin
|
|
||||||
sleep 10
|
|
||||||
systemctl restart jellyfin
|
|
||||||
if [[ "$CTTYPE" == "0" ]]; then
|
|
||||||
sed -i -e 's/^ssl-cert:x:104:$/render:x:104:root,jellyfin/' -e 's/^render:x:108:root,jellyfin$/ssl-cert:x:108:/' /etc/group
|
|
||||||
else
|
|
||||||
sed -i -e 's/^ssl-cert:x:104:$/render:x:104:jellyfin/' -e 's/^render:x:108:jellyfin$/ssl-cert:x:108:/' /etc/group
|
|
||||||
fi
|
|
||||||
msg_ok "Installed Jellyfin"
|
|
||||||
|
|
||||||
motd_ssh
|
|
||||||
customize
|
|
||||||
|
|
||||||
msg_info "Cleaning up"
|
|
||||||
$STD apt-get -y autoremove
|
|
||||||
$STD apt-get -y autoclean
|
|
||||||
msg_ok "Cleaned"
|
|
@ -1,54 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# Copyright (c) 2021-2025 community-scripts ORG
|
|
||||||
# Author: Slaviša Arežina (tremor021)
|
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
|
||||||
# Source: https://github.com/Casvt/Kapowarr
|
|
||||||
|
|
||||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
|
||||||
color
|
|
||||||
verb_ip6
|
|
||||||
catch_errors
|
|
||||||
setting_up_container
|
|
||||||
network_check
|
|
||||||
update_os
|
|
||||||
|
|
||||||
msg_info "Setup Python3"
|
|
||||||
$STD apt-get install -y python3-pip
|
|
||||||
msg_ok "Setup Python3"
|
|
||||||
|
|
||||||
setup_uv
|
|
||||||
fetch_and_deploy_gh_release "kapowarr" "Casvt/Kapowarr"
|
|
||||||
|
|
||||||
msg_info "Setup Kapowarr"
|
|
||||||
cd /opt/kapowarr
|
|
||||||
$STD uv venv .venv
|
|
||||||
$STD source .venv/bin/activate
|
|
||||||
$STD uv pip install --upgrade pip
|
|
||||||
$STD uv pip install --no-cache-dir -r requirements.txt
|
|
||||||
msg_ok "Installed Kapowarr"
|
|
||||||
|
|
||||||
msg_info "Creating Service"
|
|
||||||
cat <<EOF >/etc/systemd/system/kapowarr.service
|
|
||||||
[Unit]
|
|
||||||
Description=Kapowarr Service
|
|
||||||
After=network.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
WorkingDirectory=/opt/kapowarr/
|
|
||||||
ExecStart=/opt/kapowarr/.venv/bin/python3 Kapowarr.py
|
|
||||||
Restart=always
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
EOF
|
|
||||||
systemctl enable -q --now kapowarr
|
|
||||||
msg_ok "Created Service"
|
|
||||||
|
|
||||||
motd_ssh
|
|
||||||
customize
|
|
||||||
|
|
||||||
msg_info "Cleaning up"
|
|
||||||
$STD apt-get -y autoremove
|
|
||||||
$STD apt-get -y autoclean
|
|
||||||
msg_ok "Cleaned"
|
|
56
install/scraparr-install.sh
Normal file
56
install/scraparr-install.sh
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Copyright (c) 2021-2025 community-scripts ORG
|
||||||
|
# Author: JasonGreenC
|
||||||
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||||
|
# Source: https://github.com/thecfu/scraparr
|
||||||
|
|
||||||
|
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
||||||
|
color
|
||||||
|
verb_ip6
|
||||||
|
catch_errors
|
||||||
|
setting_up_container
|
||||||
|
network_check
|
||||||
|
update_os
|
||||||
|
|
||||||
|
msg_info "Installing Scraparr"
|
||||||
|
PYTHON_VERSION="3.12" setup_uv
|
||||||
|
fetch_and_deploy_gh_release "scrappar" "thecfu/scraparr" "tarball" "latest" "/opt/scraparr"
|
||||||
|
cd /opt/scraparr || exit
|
||||||
|
$STD uv venv /opt/scraparr/.venv
|
||||||
|
$STD /opt/scraparr/.venv/bin/python -m ensurepip --upgrade
|
||||||
|
$STD /opt/scraparr/.venv/bin/python -m pip install --upgrade pip
|
||||||
|
$STD /opt/scraparr/.venv/bin/python -m pip install -r /opt/scraparr/src/scraparr/requirements.txt
|
||||||
|
chmod -R 755 /opt/scraparr
|
||||||
|
mkdir -p /scraparr/config
|
||||||
|
mv /opt/scraparr/config.yaml /scraparr/config/config.yaml
|
||||||
|
chmod -R 755 /scraparr
|
||||||
|
msg_ok "Installed Scraparr"
|
||||||
|
|
||||||
|
msg_info "Creating Service"
|
||||||
|
cat <<EOF >/etc/systemd/system/scraparr.service
|
||||||
|
[Unit]
|
||||||
|
Description=Scraparr
|
||||||
|
Wants=network-online.target
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
WorkingDirectory=/opt/scraparr/src
|
||||||
|
ExecStart=/opt/scraparr/.venv/bin/python -m scraparr.scraparr
|
||||||
|
Restart=always
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl enable -q --now scraparr
|
||||||
|
msg_ok "Configured Service"
|
||||||
|
|
||||||
|
motd_ssh
|
||||||
|
customize
|
||||||
|
|
||||||
|
msg_info "Cleaning up"
|
||||||
|
$STD apt-get -y autoremove
|
||||||
|
$STD apt-get -y autoclean
|
||||||
|
msg_ok "Cleaned"
|
@ -14,52 +14,46 @@ update_os
|
|||||||
|
|
||||||
msg_info "Installing Dependencies (Patience)"
|
msg_info "Installing Dependencies (Patience)"
|
||||||
$STD apt-get install -y \
|
$STD apt-get install -y \
|
||||||
curl \
|
make \
|
||||||
git \
|
apache2 \
|
||||||
unzip \
|
libapache2-mod-php \
|
||||||
sudo \
|
redis
|
||||||
make \
|
|
||||||
php8.2 \
|
|
||||||
php8.2-{cli,common,bcmath,intl,fpm,tidy,xml,mysql,mbstring,zip,gd,curl} \
|
|
||||||
composer \
|
|
||||||
apache2 \
|
|
||||||
libapache2-mod-php \
|
|
||||||
redis \
|
|
||||||
mariadb-server
|
|
||||||
msg_ok "Installed Dependencies"
|
msg_ok "Installed Dependencies"
|
||||||
|
|
||||||
|
setup_mariadb
|
||||||
|
PHP_VERSION="8.3" PHP_APACHE="YES" PHP_FPM="YES" PHP_MODULE="bcmath,bz2,cli,exif,common,curl,tidy,fpm,gd,intl,mbstring,xml,mysql,zip" setup_php
|
||||||
|
setup_composer
|
||||||
|
|
||||||
msg_info "Setting up Database"
|
msg_info "Setting up Database"
|
||||||
DB_NAME=wallabag_db
|
DB_NAME=wallabag_db
|
||||||
DB_USER=wallabag
|
DB_USER=wallabag
|
||||||
DB_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13)
|
DB_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13)
|
||||||
SECRET_KEY="$(openssl rand -base64 32 | tr -dc 'a-zA-Z0-9' | cut -c1-32)"
|
SECRET_KEY="$(openssl rand -base64 32 | tr -dc 'a-zA-Z0-9' | cut -c1-32)"
|
||||||
$STD mysql -u root -e "CREATE DATABASE $DB_NAME;"
|
$STD mariadb -u root -e "CREATE DATABASE $DB_NAME;"
|
||||||
$STD mysql -u root -e "CREATE USER '$DB_USER'@'localhost' IDENTIFIED BY '$DB_PASS';"
|
$STD mariadb -u root -e "CREATE USER '$DB_USER'@'localhost' IDENTIFIED BY '$DB_PASS';"
|
||||||
$STD mysql -u root -e "GRANT ALL PRIVILEGES ON $DB_NAME.* TO '$DB_USER'@'localhost'; FLUSH PRIVILEGES;"
|
$STD mariadb -u root -e "GRANT ALL PRIVILEGES ON $DB_NAME.* TO '$DB_USER'@'localhost'; FLUSH PRIVILEGES;"
|
||||||
{
|
{
|
||||||
echo "Wallabag Credentials"
|
echo "Wallabag Credentials"
|
||||||
echo "Database User: $DB_USER"
|
echo "Database User: $DB_USER"
|
||||||
echo "Database Password: $DB_PASS"
|
echo "Database Password: $DB_PASS"
|
||||||
echo "Database Name: $DB_NAME"
|
echo "Database Name: $DB_NAME"
|
||||||
} >> ~/wallabag.creds
|
} >>~/wallabag.creds
|
||||||
msg_ok "Set up Database"
|
msg_ok "Set up Database"
|
||||||
|
|
||||||
|
fetch_and_deploy_gh_release "wallabag" "wallabag/wallabag" "prebuild" "latest" "/opt/wallabag" "wallabag-*.tar.gz"
|
||||||
|
|
||||||
msg_info "Installing Wallabag (Patience)"
|
msg_info "Installing Wallabag (Patience)"
|
||||||
RELEASE=$(curl -s https://api.github.com/repos/wallabag/wallabag/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }')
|
|
||||||
wget -q "https://github.com/wallabag/wallabag/archive/refs/tags/${RELEASE}.zip"
|
|
||||||
unzip -q ${RELEASE}.zip
|
|
||||||
mv wallabag-${RELEASE} /opt/wallabag
|
|
||||||
cd /opt/wallabag
|
cd /opt/wallabag
|
||||||
useradd -d /opt/wallabag -s /bin/bash -M wallabag
|
useradd -d /opt/wallabag -s /bin/bash -M wallabag
|
||||||
chown -R wallabag:wallabag /opt/wallabag
|
chown -R wallabag:wallabag /opt/wallabag
|
||||||
mv /opt/wallabag/app/config/parameters.yml.dist /opt/wallabag/app/config/parameters.yml
|
mv /opt/wallabag/app/config/parameters.yml.dist /opt/wallabag/app/config/parameters.yml
|
||||||
sed -i \
|
sed -i \
|
||||||
-e 's|database_name: wallabag|database_name: wallabag_db|' \
|
-e 's|database_name: wallabag|database_name: wallabag_db|' \
|
||||||
-e 's|database_port: ~|database_port: 3306|' \
|
-e 's|database_port: ~|database_port: 3306|' \
|
||||||
-e 's|database_user: root|database_user: wallabag|' \
|
-e 's|database_user: root|database_user: wallabag|' \
|
||||||
-e 's|database_password: ~|database_password: '"$DB_PASS"'|' \
|
-e 's|database_password: ~|database_password: '"$DB_PASS"'|' \
|
||||||
-e 's|secret: .*|secret: '"$SECRET_KEY"'|' \
|
-e 's|secret: .*|secret: '"$SECRET_KEY"'|' \
|
||||||
/opt/wallabag/app/config/parameters.yml
|
/opt/wallabag/app/config/parameters.yml
|
||||||
|
|
||||||
export COMPOSER_ALLOW_SUPERUSER=1
|
export COMPOSER_ALLOW_SUPERUSER=1
|
||||||
sudo -u wallabag make install --no-interaction
|
sudo -u wallabag make install --no-interaction
|
||||||
@ -72,7 +66,7 @@ msg_info "Setting up Virtual Host"
|
|||||||
cat <<EOF >/etc/nginx/conf.d/wallabag.conf
|
cat <<EOF >/etc/nginx/conf.d/wallabag.conf
|
||||||
server {
|
server {
|
||||||
root /opt/wallabag/web;
|
root /opt/wallabag/web;
|
||||||
server_name $IPADDRESS;
|
server_name $IPADDRESS;
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
# try to serve file directly, fallback to app.php
|
# try to serve file directly, fallback to app.php
|
||||||
|
197
misc/build.func
197
misc/build.func
@ -186,92 +186,92 @@ ssh_check() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
select_storage() {
|
# select_storage() {
|
||||||
local CLASS=$1 CONTENT CONTENT_LABEL
|
# local CLASS=$1 CONTENT CONTENT_LABEL
|
||||||
case $CLASS in
|
# case $CLASS in
|
||||||
container)
|
# container)
|
||||||
CONTENT='rootdir'
|
# CONTENT='rootdir'
|
||||||
CONTENT_LABEL='Container'
|
# CONTENT_LABEL='Container'
|
||||||
;;
|
# ;;
|
||||||
template)
|
# template)
|
||||||
CONTENT='vztmpl'
|
# CONTENT='vztmpl'
|
||||||
CONTENT_LABEL='Template'
|
# CONTENT_LABEL='Template'
|
||||||
;;
|
# ;;
|
||||||
iso)
|
# iso)
|
||||||
CONTENT='iso'
|
# CONTENT='iso'
|
||||||
CONTENT_LABEL='ISO image'
|
# CONTENT_LABEL='ISO image'
|
||||||
;;
|
# ;;
|
||||||
images)
|
# images)
|
||||||
CONTENT='images'
|
# CONTENT='images'
|
||||||
CONTENT_LABEL='VM Disk image'
|
# CONTENT_LABEL='VM Disk image'
|
||||||
;;
|
# ;;
|
||||||
backup)
|
# backup)
|
||||||
CONTENT='backup'
|
# CONTENT='backup'
|
||||||
CONTENT_LABEL='Backup'
|
# CONTENT_LABEL='Backup'
|
||||||
;;
|
# ;;
|
||||||
snippets)
|
# snippets)
|
||||||
CONTENT='snippets'
|
# CONTENT='snippets'
|
||||||
CONTENT_LABEL='Snippets'
|
# CONTENT_LABEL='Snippets'
|
||||||
;;
|
# ;;
|
||||||
*)
|
# *)
|
||||||
msg_error "Invalid storage class '$CLASS'."
|
# msg_error "Invalid storage class '$CLASS'."
|
||||||
exit 201
|
# exit 201
|
||||||
;;
|
# ;;
|
||||||
esac
|
# esac
|
||||||
|
|
||||||
command -v whiptail >/dev/null || {
|
# command -v whiptail >/dev/null || {
|
||||||
msg_error "whiptail missing."
|
# msg_error "whiptail missing."
|
||||||
exit 220
|
# exit 220
|
||||||
}
|
# }
|
||||||
command -v numfmt >/dev/null || {
|
# command -v numfmt >/dev/null || {
|
||||||
msg_error "numfmt missing."
|
# msg_error "numfmt missing."
|
||||||
exit 221
|
# exit 221
|
||||||
}
|
# }
|
||||||
|
|
||||||
local -a MENU
|
# local -a MENU
|
||||||
while read -r line; do
|
# while read -r line; do
|
||||||
local TAG=$(echo "$line" | awk '{print $1}')
|
# local TAG=$(echo "$line" | awk '{print $1}')
|
||||||
local TYPE=$(echo "$line" | awk '{printf "%-10s", $2}')
|
# local TYPE=$(echo "$line" | awk '{printf "%-10s", $2}')
|
||||||
local FREE=$(echo "$line" | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf "%9sB", $6}')
|
# local FREE=$(echo "$line" | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf "%9sB", $6}')
|
||||||
MENU+=("$TAG" "Type: $TYPE Free: $FREE" "OFF")
|
# MENU+=("$TAG" "Type: $TYPE Free: $FREE" "OFF")
|
||||||
done < <(pvesm status -content "$CONTENT" | awk 'NR>1')
|
# done < <(pvesm status -content "$CONTENT" | awk 'NR>1')
|
||||||
|
|
||||||
if [ ${#MENU[@]} -eq 0 ]; then
|
# if [ ${#MENU[@]} -eq 0 ]; then
|
||||||
msg_error "No storage found for content type '$CONTENT'."
|
# msg_error "No storage found for content type '$CONTENT'."
|
||||||
exit 203
|
# exit 203
|
||||||
fi
|
# fi
|
||||||
|
|
||||||
if [ $((${#MENU[@]} / 3)) -eq 1 ]; then
|
# if [ $((${#MENU[@]} / 3)) -eq 1 ]; then
|
||||||
echo "${MENU[0]}"
|
# echo "${MENU[0]}"
|
||||||
return
|
# return
|
||||||
fi
|
# fi
|
||||||
|
|
||||||
local STORAGE
|
# local STORAGE
|
||||||
STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
|
# STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
|
||||||
"Which storage pool for ${CONTENT_LABEL,,}?\n(Spacebar to select)" \
|
# "Which storage pool for ${CONTENT_LABEL,,}?\n(Spacebar to select)" \
|
||||||
16 70 6 "${MENU[@]}" 3>&1 1>&2 2>&3) || {
|
# 16 70 6 "${MENU[@]}" 3>&1 1>&2 2>&3) || {
|
||||||
msg_error "Storage selection cancelled by user."
|
# msg_error "Storage selection cancelled by user."
|
||||||
exit 202
|
# exit 202
|
||||||
}
|
# }
|
||||||
echo "$STORAGE"
|
# echo "$STORAGE"
|
||||||
}
|
# }
|
||||||
|
|
||||||
manage_default_storage() {
|
# manage_default_storage() {
|
||||||
local file="/usr/local/community-scripts/default_storage"
|
# local file="/usr/local/community-scripts/default_storage"
|
||||||
mkdir -p /usr/local/community-scripts
|
# mkdir -p /usr/local/community-scripts
|
||||||
|
|
||||||
local tmpl=$(select_storage template)
|
# local tmpl=$(select_storage template)
|
||||||
local cont=$(select_storage container)
|
# local cont=$(select_storage container)
|
||||||
|
|
||||||
cat <<EOF >"$file"
|
# cat <<EOF >"$file"
|
||||||
TEMPLATE_STORAGE=$tmpl
|
# TEMPLATE_STORAGE=$tmpl
|
||||||
CONTAINER_STORAGE=$cont
|
# CONTAINER_STORAGE=$cont
|
||||||
EOF
|
# EOF
|
||||||
|
|
||||||
msg_ok "Default Storage set: Template=${BL}$tmpl${CL} ${GN}|${CL} Container=${BL}$cont${CL}"
|
# msg_ok "Default Storage set: Template=${BL}$tmpl${CL} ${GN}|${CL} Container=${BL}$cont${CL}"
|
||||||
whiptail --backtitle "[dev] Proxmox VE Helper Scripts" \
|
# whiptail --backtitle "[dev] Proxmox VE Helper Scripts" \
|
||||||
--msgbox "Default Storage set:\n\nTemplate: $tmpl\nContainer: $cont" 10 58
|
# --msgbox "Default Storage set:\n\nTemplate: $tmpl\nContainer: $cont" 10 58
|
||||||
}
|
# }
|
||||||
|
|
||||||
base_settings() {
|
base_settings() {
|
||||||
# Default Settings
|
# Default Settings
|
||||||
@ -333,13 +333,13 @@ write_config() {
|
|||||||
|
|
||||||
CT_TYPE="${CT_TYPE}"
|
CT_TYPE="${CT_TYPE}"
|
||||||
DISK_SIZE="${DISK_SIZE}"
|
DISK_SIZE="${DISK_SIZE}"
|
||||||
CORE_COUNT="${DISK_SIZE}"
|
CORE_COUNT="${CORE_COUNT}"
|
||||||
RAM_SIZE="${RAM_SIZE}"
|
RAM_SIZE="${RAM_SIZE}"
|
||||||
HN="${HN}"
|
HN="${HN}"
|
||||||
BRG="${BRG}"
|
BRG="${BRG}"
|
||||||
APT_CACHER_IP="${APT_CACHER_IP:-none}"
|
APT_CACHER_IP="${APT_CACHER_IP:-none}"
|
||||||
DISABLEIP6="${DISABLEIP6}"
|
DISABLEIP6="${DISABLEIP6}"
|
||||||
PW="${PW:-none}"
|
PW='${PW:-none}'
|
||||||
SSH="${SSH}"
|
SSH="${SSH}"
|
||||||
SSH_AUTHORIZED_KEY="${SSH_AUTHORIZED_KEY}"
|
SSH_AUTHORIZED_KEY="${SSH_AUTHORIZED_KEY}"
|
||||||
VERBOSE="${VERBOSE}"
|
VERBOSE="${VERBOSE}"
|
||||||
@ -351,6 +351,7 @@ SD="${SD:-none}"
|
|||||||
MAC="${MAC:-none}"
|
MAC="${MAC:-none}"
|
||||||
NS="${NS:-none}"
|
NS="${NS:-none}"
|
||||||
NET="${NET}"
|
NET="${NET}"
|
||||||
|
FUSE="${ENABLE_FUSE}"
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
echo -e "${INFO}${BOLD}${GN}Writing configuration to ${FILEPATH}${CL}"
|
echo -e "${INFO}${BOLD}${GN}Writing configuration to ${FILEPATH}${CL}"
|
||||||
@ -364,7 +365,7 @@ EOF
|
|||||||
|
|
||||||
CT_TYPE="${CT_TYPE}"
|
CT_TYPE="${CT_TYPE}"
|
||||||
DISK_SIZE="${DISK_SIZE}"
|
DISK_SIZE="${DISK_SIZE}"
|
||||||
CORE_COUNT="${DISK_SIZE}"
|
CORE_COUNT="${CORE_COUNT}"
|
||||||
RAM_SIZE="${RAM_SIZE}"
|
RAM_SIZE="${RAM_SIZE}"
|
||||||
HN="${HN}"
|
HN="${HN}"
|
||||||
BRG="${BRG}"
|
BRG="${BRG}"
|
||||||
@ -382,6 +383,7 @@ SD="${SD:-none}"
|
|||||||
MAC="${MAC:-none}"
|
MAC="${MAC:-none}"
|
||||||
NS="${NS:-none}"
|
NS="${NS:-none}"
|
||||||
NET="${NET}"
|
NET="${NET}"
|
||||||
|
FUSE="${ENABLE_FUSE}"
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
echo -e "${INFO}${BOLD}${GN}Writing configuration to ${FILEPATH}${CL}"
|
echo -e "${INFO}${BOLD}${GN}Writing configuration to ${FILEPATH}${CL}"
|
||||||
@ -402,9 +404,11 @@ echo_default() {
|
|||||||
|
|
||||||
# Output the selected values with icons
|
# Output the selected values with icons
|
||||||
echo -e "${CONTAINERID}${BOLD}${DGN}Container ID: ${BGN}${CT_ID}${CL}"
|
echo -e "${CONTAINERID}${BOLD}${DGN}Container ID: ${BGN}${CT_ID}${CL}"
|
||||||
echo -e "${OS}${BOLD}${DGN}Operating System: $var_os | Version: $var_version${CL}"
|
echo -e "${OS}${BOLD}${DGN}Operating System: ${BGN}$var_os ($var_version)${CL}"
|
||||||
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Container Type: ${BGN}$CT_TYPE_DESC${CL}"
|
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Container Type: ${BGN}$CT_TYPE_DESC${CL}"
|
||||||
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE} GB | ${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}${CORE_COUNT} | ${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE} MiB${CL}"
|
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE} GB${CL}"
|
||||||
|
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}${CORE_COUNT}${CL}"
|
||||||
|
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE} MiB${CL}"
|
||||||
if [ "$VERB" == "yes" ]; then
|
if [ "$VERB" == "yes" ]; then
|
||||||
echo -e "${SEARCH}${BOLD}${DGN}Verbose Mode: ${BGN}Enabled${CL}"
|
echo -e "${SEARCH}${BOLD}${DGN}Verbose Mode: ${BGN}Enabled${CL}"
|
||||||
fi
|
fi
|
||||||
@ -861,12 +865,12 @@ advanced_settings() {
|
|||||||
echo -e "${ROOTSSH}${BOLD}${DGN}Root SSH Access: ${BGN}$SSH${CL}"
|
echo -e "${ROOTSSH}${BOLD}${DGN}Root SSH Access: ${BGN}$SSH${CL}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# if (whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --defaultno --title "FUSE Support" --yesno "Enable FUSE support?\nRequired for tools like rclone, mergerfs, AppImage, etc." 10 58); then
|
if (whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "FUSE Support" --yesno "Enable FUSE support?\nRequired for tools like rclone, mergerfs, AppImage, etc." 10 58); then
|
||||||
# ENABLE_FUSE="yes"
|
ENABLE_FUSE="yes"
|
||||||
# else
|
else
|
||||||
# ENABLE_FUSE="no"
|
ENABLE_FUSE="no"
|
||||||
# fi
|
fi
|
||||||
# echo -e "${FUSE}${BOLD}${DGN}Enable FUSE Support: ${BGN}$ENABLE_FUSE${CL}"
|
echo -e "${FUSE}${BOLD}${DGN}Enable FUSE Support: ${BGN}$ENABLE_FUSE${CL}"
|
||||||
|
|
||||||
if (whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --defaultno --title "VERBOSE MODE" --yesno "Enable Verbose Mode?" 10 58); then
|
if (whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --defaultno --title "VERBOSE MODE" --yesno "Enable Verbose Mode?" 10 58); then
|
||||||
VERBOSE="yes"
|
VERBOSE="yes"
|
||||||
@ -1195,12 +1199,10 @@ build_container() {
|
|||||||
-unprivileged $CT_TYPE
|
-unprivileged $CT_TYPE
|
||||||
$PW
|
$PW
|
||||||
"
|
"
|
||||||
# This executes create_lxc.sh and creates the container and .conf file
|
bash -c "$(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/create_lxc.sh)"
|
||||||
CREATE_CMD="bash -c \"\$(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/create_lxc.sh)\""
|
|
||||||
eval "$CREATE_CMD"
|
|
||||||
RET=$?
|
RET=$?
|
||||||
if [[ $RET -ne 0 ]]; then
|
if [[ $RET -ne 0 ]]; then
|
||||||
msg_error "in line $LINENO: exit code $RET: while executing command $CREATE_CMD"
|
msg_error "rny: in line $LINENO: exit code $RET: while executing create_lxc.sh"
|
||||||
exit $RET
|
exit $RET
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -1273,21 +1275,24 @@ EOF'
|
|||||||
pct exec "$CTID" -- ash -c "apk add bash newt curl openssh nano mc ncurses >/dev/null"
|
pct exec "$CTID" -- ash -c "apk add bash newt curl openssh nano mc ncurses >/dev/null"
|
||||||
else
|
else
|
||||||
sleep 3
|
sleep 3
|
||||||
# Set locale and timezone before update
|
|
||||||
pct exec "$CTID" -- bash -c "sed -i '/$LANG/ s/^# //' /etc/locale.gen"
|
pct exec "$CTID" -- bash -c "sed -i '/$LANG/ s/^# //' /etc/locale.gen"
|
||||||
pct exec "$CTID" -- bash -c "locale_line=\$(grep -v '^#' /etc/locale.gen | grep -E '^[a-zA-Z]' | awk '{print \$1}' | head -n 1) && \
|
pct exec "$CTID" -- bash -c "locale_line=\$(grep -v '^#' /etc/locale.gen | grep -E '^[a-zA-Z]' | awk '{print \$1}' | head -n 1) && \
|
||||||
echo LANG=\$locale_line >/etc/default/locale && \
|
echo LANG=\$locale_line >/etc/default/locale && \
|
||||||
locale-gen >/dev/null && \
|
locale-gen >/dev/null && \
|
||||||
export LANG=\$locale_line"
|
export LANG=\$locale_line"
|
||||||
|
|
||||||
pct exec "$CTID" -- bash -c "echo $tz >/etc/timezone && ln -sf /usr/share/zoneinfo/$tz /etc/localtime"
|
if pct exec "$CTID" -- test -e "/usr/share/zoneinfo/$tz"; then
|
||||||
|
pct exec "$CTID" -- bash -c "echo $tz >/etc/timezone && ln -sf /usr/share/zoneinfo/$tz /etc/localtime"
|
||||||
|
else
|
||||||
|
msg_info "Skipping timezone setup – zone '$tz' not found in container"
|
||||||
|
fi
|
||||||
|
|
||||||
# Install curl
|
|
||||||
pct exec "$CTID" -- bash -c "apt-get update >/dev/null && apt-get install -y sudo curl mc gnupg2 >/dev/null"
|
pct exec "$CTID" -- bash -c "apt-get update >/dev/null && apt-get install -y sudo curl mc gnupg2 >/dev/null"
|
||||||
fi
|
fi
|
||||||
msg_ok "Customized LXC Container"
|
msg_ok "Customized LXC Container"
|
||||||
lxc-attach -n "$CTID" -- bash -c "$(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/install/$var_install.sh)" $?
|
|
||||||
|
|
||||||
|
lxc-attach -n "$CTID" -- bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/install/"$var_install".sh)" $?
|
||||||
}
|
}
|
||||||
|
|
||||||
# This function sets the description of the container.
|
# This function sets the description of the container.
|
||||||
|
366
misc/core.func
366
misc/core.func
@ -9,21 +9,21 @@
|
|||||||
# }
|
# }
|
||||||
# fi
|
# fi
|
||||||
|
|
||||||
trap 'on_error $? $LINENO' ERR
|
# trap 'on_error $? $LINENO' ERR
|
||||||
trap 'on_exit' EXIT
|
# trap 'on_exit' EXIT
|
||||||
trap 'on_interrupt' INT
|
# trap 'on_interrupt' INT
|
||||||
trap 'on_terminate' TERM
|
# trap 'on_terminate' TERM
|
||||||
|
|
||||||
if ! declare -f wait_for >/dev/null; then
|
# if ! declare -f wait_for >/dev/null; then
|
||||||
wait_for() {
|
# wait_for() {
|
||||||
true
|
# true
|
||||||
}
|
# }
|
||||||
fi
|
# fi
|
||||||
|
|
||||||
declare -A MSG_INFO_SHOWN=()
|
# declare -A MSG_INFO_SHOWN=()
|
||||||
SPINNER_PID=""
|
# SPINNER_PID=""
|
||||||
SPINNER_ACTIVE=0
|
# SPINNER_ACTIVE=0
|
||||||
SPINNER_MSG=""
|
# SPINNER_MSG=""
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Loads core utility groups once (colors, formatting, icons, defaults).
|
# Loads core utility groups once (colors, formatting, icons, defaults).
|
||||||
@ -47,9 +47,9 @@ load_functions() {
|
|||||||
# Error & Signal Handling – robust, universal, subshell-safe
|
# Error & Signal Handling – robust, universal, subshell-safe
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
_stop_spinner_on_error() {
|
# _stop_spinner_on_error() {
|
||||||
[[ -n "${SPINNER_PID:-}" ]] && kill "$SPINNER_PID" 2>/dev/null && wait "$SPINNER_PID" 2>/dev/null || true
|
# [[ -n "${SPINNER_PID:-}" ]] && kill "$SPINNER_PID" 2>/dev/null && wait "$SPINNER_PID" 2>/dev/null || true
|
||||||
}
|
# }
|
||||||
|
|
||||||
_tool_error_hint() {
|
_tool_error_hint() {
|
||||||
local cmd="$1"
|
local cmd="$1"
|
||||||
@ -89,44 +89,39 @@ _tool_error_hint() {
|
|||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
on_error() {
|
# on_error() {
|
||||||
local code="$?"
|
# local code="$?"
|
||||||
local line="${BASH_LINENO[0]:-unknown}"
|
# local line="${BASH_LINENO[0]:-unknown}"
|
||||||
local cmd="${BASH_COMMAND:-unknown}"
|
# local cmd="${BASH_COMMAND:-unknown}"
|
||||||
|
|
||||||
# Signalcode unterdrücken, falls INT/TERM kommt
|
# # Signalcode unterdrücken, falls INT/TERM kommt
|
||||||
[[ "$code" == "130" || "$code" == "143" ]] && return
|
# [[ "$code" == "130" || "$code" == "143" ]] && return
|
||||||
|
|
||||||
_stop_spinner_on_error
|
# _stop_spinner_on_error
|
||||||
msg_error "Script failed at line $line with exit code $code: $cmd"
|
# msg_error "Script failed at line $line with exit code $code: $cmd"
|
||||||
exit "$code"
|
# exit "$code"
|
||||||
}
|
# }
|
||||||
|
|
||||||
on_exit() {
|
# on_exit() {
|
||||||
_stop_spinner_on_error
|
# _stop_spinner_on_error
|
||||||
[[ "${VERBOSE:-no}" == "yes" ]] && msg_info "Script exited cleanly"
|
# [[ "${VERBOSE:-no}" == "yes" ]] && msg_info "Script exited cleanly"
|
||||||
}
|
# }
|
||||||
|
|
||||||
on_interrupt() {
|
# on_interrupt() {
|
||||||
_stop_spinner_on_error
|
# _stop_spinner_on_error
|
||||||
msg_error "Interrupted by user (CTRL+C)"
|
# msg_error "Interrupted by user (CTRL+C)"
|
||||||
exit 130
|
# exit 130
|
||||||
}
|
# }
|
||||||
|
|
||||||
on_terminate() {
|
# on_terminate() {
|
||||||
_stop_spinner_on_error
|
# _stop_spinner_on_error
|
||||||
msg_error "Terminated by signal (SIGTERM)"
|
# msg_error "Terminated by signal (SIGTERM)"
|
||||||
exit 143
|
# exit 143
|
||||||
}
|
# }
|
||||||
|
|
||||||
catch_errors() {
|
catch_errors() {
|
||||||
trap 'on_error' ERR
|
|
||||||
trap 'on_exit' EXIT
|
|
||||||
trap 'on_interrupt' INT
|
|
||||||
trap 'on_terminate' TERM
|
|
||||||
|
|
||||||
set -Eeuo pipefail
|
set -Eeuo pipefail
|
||||||
shopt -s inherit_errexit
|
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
|
||||||
}
|
}
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
@ -143,6 +138,13 @@ color() {
|
|||||||
CL=$(echo "\033[m")
|
CL=$(echo "\033[m")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Special for spinner and colorized output via printf
|
||||||
|
color_spinner() {
|
||||||
|
CS_YW=$'\033[33m'
|
||||||
|
CS_YWB=$'\033[93m'
|
||||||
|
CS_CL=$'\033[m'
|
||||||
|
}
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Defines formatting helpers like tab, bold, and line reset sequences.
|
# Defines formatting helpers like tab, bold, and line reset sequences.
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
@ -363,149 +365,215 @@ fatal() {
|
|||||||
kill -INT $$
|
kill -INT $$
|
||||||
}
|
}
|
||||||
|
|
||||||
# Ensure POSIX compatibility across Alpine and Debian/Ubuntu
|
# # Ensure POSIX compatibility across Alpine and Debian/Ubuntu
|
||||||
# === Spinner Start ===
|
# # === Spinner Start ===
|
||||||
# Trap cleanup on various signals
|
# # Trap cleanup on various signals
|
||||||
trap 'cleanup_spinner' EXIT INT TERM HUP
|
# trap 'cleanup_spinner' EXIT INT TERM HUP
|
||||||
|
|
||||||
spinner_frames=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
|
# spinner_frames=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
|
||||||
|
|
||||||
# === Spinner Start ===
|
# # === Spinner Start ===
|
||||||
start_spinner() {
|
# start_spinner() {
|
||||||
local msg="$1"
|
# local msg="$1"
|
||||||
local spin_i=0
|
# local spin_i=0
|
||||||
local interval=0.1
|
# local interval=0.1
|
||||||
|
|
||||||
stop_spinner
|
# stop_spinner
|
||||||
SPINNER_MSG="$msg"
|
# SPINNER_MSG="$msg"
|
||||||
SPINNER_ACTIVE=1
|
# SPINNER_ACTIVE=1
|
||||||
|
|
||||||
{
|
# {
|
||||||
while [[ "$SPINNER_ACTIVE" -eq 1 ]]; do
|
# while [[ "$SPINNER_ACTIVE" -eq 1 ]]; do
|
||||||
if [[ -t 2 ]]; then
|
# if [[ -t 2 ]]; then
|
||||||
printf "\r\e[2K%s %b" "${TAB}${spinner_frames[spin_i]}${TAB}" "${YW}${SPINNER_MSG}${CL}" >&2
|
# printf "\r\e[2K%s %b" "${TAB}${spinner_frames[spin_i]}${TAB}" "${YW}${SPINNER_MSG}${CL}" >&2
|
||||||
else
|
# else
|
||||||
printf "%s...\n" "$SPINNER_MSG" >&2
|
# printf "%s...\n" "$SPINNER_MSG" >&2
|
||||||
break
|
# break
|
||||||
fi
|
# fi
|
||||||
spin_i=$(((spin_i + 1) % ${#spinner_frames[@]}))
|
# spin_i=$(((spin_i + 1) % ${#spinner_frames[@]}))
|
||||||
sleep "$interval"
|
# sleep "$interval"
|
||||||
done
|
# done
|
||||||
} &
|
# } &
|
||||||
|
|
||||||
local pid=$!
|
# local pid=$!
|
||||||
if ps -p "$pid" >/dev/null 2>&1; then
|
# if ps -p "$pid" >/dev/null 2>&1; then
|
||||||
SPINNER_PID="$pid"
|
# SPINNER_PID="$pid"
|
||||||
else
|
# else
|
||||||
SPINNER_ACTIVE=0
|
# SPINNER_ACTIVE=0
|
||||||
SPINNER_PID=""
|
# SPINNER_PID=""
|
||||||
fi
|
# fi
|
||||||
|
# }
|
||||||
|
|
||||||
|
# # === Spinner Stop ===
|
||||||
|
# stop_spinner() {
|
||||||
|
# if [[ "$SPINNER_ACTIVE" -eq 1 && -n "$SPINNER_PID" ]]; then
|
||||||
|
# SPINNER_ACTIVE=0
|
||||||
|
|
||||||
|
# if kill -0 "$SPINNER_PID" 2>/dev/null; then
|
||||||
|
# kill "$SPINNER_PID" 2>/dev/null || true
|
||||||
|
# for _ in $(seq 1 10); do
|
||||||
|
# sleep 0.05
|
||||||
|
# kill -0 "$SPINNER_PID" 2>/dev/null || break
|
||||||
|
# done
|
||||||
|
# fi
|
||||||
|
|
||||||
|
# if [[ "$SPINNER_PID" =~ ^[0-9]+$ ]]; then
|
||||||
|
# ps -p "$SPINNER_PID" -o pid= >/dev/null 2>&1 && wait "$SPINNER_PID" 2>/dev/null || true
|
||||||
|
# fi
|
||||||
|
|
||||||
|
# printf "\r\e[2K" >&2
|
||||||
|
# SPINNER_PID=""
|
||||||
|
# fi
|
||||||
|
# }
|
||||||
|
|
||||||
|
# cleanup_spinner() {
|
||||||
|
# stop_spinner
|
||||||
|
# }
|
||||||
|
|
||||||
|
# msg_info() {
|
||||||
|
# local msg="$1"
|
||||||
|
# [[ -z "$msg" || -n "${MSG_INFO_SHOWN["$msg"]+x}" ]] && return
|
||||||
|
# MSG_INFO_SHOWN["$msg"]=1
|
||||||
|
|
||||||
|
# stop_spinner
|
||||||
|
# echo -e "OS: ${var_os:-}"
|
||||||
|
# if [[ "${VERBOSE:-no}" != "no" || "${var_os:-}" == "alpine" || ! -t 2 ]]; then
|
||||||
|
# printf "\r\e[2K%s %b\n" "$HOURGLASS" "${YW}${msg}${CL}" >&2
|
||||||
|
# else
|
||||||
|
# start_spinner "$msg"
|
||||||
|
# fi
|
||||||
|
# }
|
||||||
|
|
||||||
|
spinner() {
|
||||||
|
local chars=(⠋ ⠙ ⠹ ⠸ ⠼ ⠴ ⠦ ⠧ ⠇ ⠏)
|
||||||
|
local i=0
|
||||||
|
while true; do
|
||||||
|
local index=$((i++ % ${#chars[@]}))
|
||||||
|
printf "\r\033[2K%s %b" "${CS_YWB}${chars[$index]}${CS_CL}" "${CS_YWB}${SPINNER_MSG:-}${CS_CL}"
|
||||||
|
sleep 0.1
|
||||||
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
# === Spinner Stop ===
|
|
||||||
stop_spinner() {
|
stop_spinner() {
|
||||||
if [[ "$SPINNER_ACTIVE" -eq 1 && -n "$SPINNER_PID" ]]; then
|
local pid="${SPINNER_PID:-}"
|
||||||
SPINNER_ACTIVE=0
|
[[ -z "$pid" && -f /tmp/.spinner.pid ]] && pid=$(</tmp/.spinner.pid)
|
||||||
|
|
||||||
if kill -0 "$SPINNER_PID" 2>/dev/null; then
|
if [[ -n "$pid" && "$pid" =~ ^[0-9]+$ ]]; then
|
||||||
kill "$SPINNER_PID" 2>/dev/null || true
|
if kill "$pid" 2>/dev/null; then
|
||||||
for _ in $(seq 1 10); do
|
sleep 0.05
|
||||||
sleep 0.05
|
kill -9 "$pid" 2>/dev/null || true
|
||||||
kill -0 "$SPINNER_PID" 2>/dev/null || break
|
wait "$pid" 2>/dev/null || true
|
||||||
done
|
|
||||||
fi
|
fi
|
||||||
|
rm -f /tmp/.spinner.pid
|
||||||
if [[ "$SPINNER_PID" =~ ^[0-9]+$ ]]; then
|
unset SPINNER_PID
|
||||||
ps -p "$SPINNER_PID" -o pid= >/dev/null 2>&1 && wait "$SPINNER_PID" 2>/dev/null || true
|
|
||||||
fi
|
|
||||||
|
|
||||||
printf "\r\e[2K" >&2
|
|
||||||
SPINNER_PID=""
|
|
||||||
fi
|
fi
|
||||||
}
|
|
||||||
|
|
||||||
cleanup_spinner() {
|
stty sane 2>/dev/null
|
||||||
stop_spinner
|
#printf "\r\033[K\e[?25h\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
msg_info() {
|
msg_info() {
|
||||||
local msg="$1"
|
local msg="$1"
|
||||||
[[ -z "$msg" || -n "${MSG_INFO_SHOWN["$msg"]+x}" ]] && return
|
SPINNER_MSG="$msg"
|
||||||
MSG_INFO_SHOWN["$msg"]=1
|
color_spinner
|
||||||
|
spinner &
|
||||||
stop_spinner
|
SPINNER_PID=$!
|
||||||
|
echo "$SPINNER_PID" >/tmp/.spinner.pid
|
||||||
if [[ "${VERBOSE:-no}" != "no" || "${var_os:-}" == "alpine" || ! -t 2 ]]; then
|
disown "$SPINNER_PID" 2>/dev/null || true
|
||||||
printf "\r\e[2K%s %b\n" "$HOURGLASS" "${YW}${msg}${CL}" >&2
|
|
||||||
else
|
|
||||||
start_spinner "$msg"
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
msg_ok() {
|
msg_ok() {
|
||||||
local msg="$1"
|
|
||||||
[[ -z "$msg" ]] && return
|
|
||||||
stop_spinner
|
stop_spinner
|
||||||
printf "\r\e[2K%s %b\n" "$CM" "${GN}${msg}${CL}" >&2
|
local msg="$1"
|
||||||
if declare -p MSG_INFO_SHOWN &>/dev/null && [[ "$(declare -p MSG_INFO_SHOWN 2>/dev/null)" =~ "declare -A" ]]; then
|
echo -e "${BFR:-} ${CM:-✔️} ${GN}${msg}${CL}"
|
||||||
unset MSG_INFO_SHOWN["$msg"]
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
msg_error() {
|
msg_error() {
|
||||||
local msg="$1"
|
|
||||||
[[ -z "$msg" ]] && return
|
|
||||||
stop_spinner
|
stop_spinner
|
||||||
printf "\r\e[2K%s %b\n" "$CROSS" "${RD}${msg}${CL}" >&2
|
local msg="$1"
|
||||||
|
echo -e "${BFR:-} ${CROSS:-✖️} ${RD}${msg}${CL}"
|
||||||
}
|
}
|
||||||
|
|
||||||
msg_warn() {
|
msg_warn() {
|
||||||
local msg="$1"
|
|
||||||
[[ -z "$msg" ]] && return
|
|
||||||
stop_spinner
|
stop_spinner
|
||||||
printf "\r\e[2K%s %b\n" "$INFO" "${YWB}${msg}${CL}" >&2
|
local msg="$1"
|
||||||
if declare -p MSG_INFO_SHOWN &>/dev/null && [[ "$(declare -p MSG_INFO_SHOWN 2>/dev/null)" =~ "declare -A" ]]; then
|
echo -e "${BFR:-} ${INFO:-ℹ️} ${YWB}${msg}${CL}"
|
||||||
unset MSG_INFO_SHOWN["$msg"]
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
msg_custom() {
|
msg_custom() {
|
||||||
local symbol="${1:-"[*]"}"
|
local symbol="${1:-"[*]"}"
|
||||||
local color="${2:-"\e[36m"}" # Default: Cyan
|
local color="${2:-"\e[36m"}"
|
||||||
local msg="${3:-}"
|
local msg="${3:-}"
|
||||||
|
|
||||||
[[ -z "$msg" ]] && return
|
[[ -z "$msg" ]] && return
|
||||||
stop_spinner 2>/dev/null || true
|
stop_spinner
|
||||||
printf "\r\e[2K%s %b\n" "$symbol" "${color}${msg}${CL:-\e[0m}" >&2
|
echo -e "${BFR:-} ${symbol} ${color}${msg}${CL:-\e[0m}"
|
||||||
|
printf "\r\033[K\e[?25h\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
msg_progress() {
|
# msg_ok() {
|
||||||
local current="$1"
|
# local msg="$1"
|
||||||
local total="$2"
|
# [[ -z "$msg" ]] && return
|
||||||
local label="$3"
|
# stop_spinner
|
||||||
local width=40
|
# printf "\r\e[2K%s %b\n" "$CM" "${GN}${msg}${CL}" >&2
|
||||||
local filled percent bar empty
|
# if declare -p MSG_INFO_SHOWN &>/dev/null && [[ "$(declare -p MSG_INFO_SHOWN 2>/dev/null)" =~ "declare -A" ]]; then
|
||||||
local fill_char="#"
|
# unset MSG_INFO_SHOWN["$msg"]
|
||||||
local empty_char="-"
|
# fi
|
||||||
|
# }
|
||||||
|
|
||||||
if ! [[ "$current" =~ ^[0-9]+$ ]] || ! [[ "$total" =~ ^[0-9]+$ ]] || [[ "$total" -eq 0 ]]; then
|
# msg_error() {
|
||||||
printf "\r\e[2K%s %b\n" "$CROSS" "${RD}Invalid progress input${CL}" >&2
|
# local msg="$1"
|
||||||
return
|
# [[ -z "$msg" ]] && return
|
||||||
fi
|
# stop_spinner
|
||||||
|
# printf "\r\e[2K%s %b\n" "$CROSS" "${RD}${msg}${CL}" >&2
|
||||||
|
# }
|
||||||
|
|
||||||
percent=$(((current * 100) / total))
|
# msg_warn() {
|
||||||
filled=$(((current * width) / total))
|
# local msg="$1"
|
||||||
empty=$((width - filled))
|
# [[ -z "$msg" ]] && return
|
||||||
|
# stop_spinner
|
||||||
|
# printf "\r\e[2K%s %b\n" "$INFO" "${YWB}${msg}${CL}" >&2
|
||||||
|
# if declare -p MSG_INFO_SHOWN &>/dev/null && [[ "$(declare -p MSG_INFO_SHOWN 2>/dev/null)" =~ "declare -A" ]]; then
|
||||||
|
# unset MSG_INFO_SHOWN["$msg"]
|
||||||
|
# fi
|
||||||
|
# }
|
||||||
|
|
||||||
bar=$(printf "%${filled}s" | tr ' ' "$fill_char")
|
# msg_custom() {
|
||||||
bar+=$(printf "%${empty}s" | tr ' ' "$empty_char")
|
# local symbol="${1:-"[*]"}"
|
||||||
|
# local color="${2:-"\e[36m"}" # Default: Cyan
|
||||||
|
# local msg="${3:-}"
|
||||||
|
|
||||||
printf "\r\e[2K%s [%s] %3d%% %s" "${TAB}" "$bar" "$percent" "$label" >&2
|
# [[ -z "$msg" ]] && return
|
||||||
|
# stop_spinner 2>/dev/null || true
|
||||||
|
# printf "\r\e[2K%s %b\n" "$symbol" "${color}${msg}${CL:-\e[0m}" >&2
|
||||||
|
# }
|
||||||
|
|
||||||
if [[ "$current" -eq "$total" ]]; then
|
# msg_progress() {
|
||||||
printf "\n" >&2
|
# local current="$1"
|
||||||
fi
|
# local total="$2"
|
||||||
}
|
# local label="$3"
|
||||||
|
# local width=40
|
||||||
|
# local filled percent bar empty
|
||||||
|
# local fill_char="#"
|
||||||
|
# local empty_char="-"
|
||||||
|
|
||||||
|
# if ! [[ "$current" =~ ^[0-9]+$ ]] || ! [[ "$total" =~ ^[0-9]+$ ]] || [[ "$total" -eq 0 ]]; then
|
||||||
|
# printf "\r\e[2K%s %b\n" "$CROSS" "${RD}Invalid progress input${CL}" >&2
|
||||||
|
# return
|
||||||
|
# fi
|
||||||
|
|
||||||
|
# percent=$(((current * 100) / total))
|
||||||
|
# filled=$(((current * width) / total))
|
||||||
|
# empty=$((width - filled))
|
||||||
|
|
||||||
|
# bar=$(printf "%${filled}s" | tr ' ' "$fill_char")
|
||||||
|
# bar+=$(printf "%${empty}s" | tr ' ' "$empty_char")
|
||||||
|
|
||||||
|
# printf "\r\e[2K%s [%s] %3d%% %s" "${TAB}" "$bar" "$percent" "$label" >&2
|
||||||
|
|
||||||
|
# if [[ "$current" -eq "$total" ]]; then
|
||||||
|
# printf "\n" >&2
|
||||||
|
# fi
|
||||||
|
# }
|
||||||
|
|
||||||
run_container_safe() {
|
run_container_safe() {
|
||||||
local ct="$1"
|
local ct="$1"
|
||||||
@ -555,3 +623,5 @@ check_or_create_swap() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trap 'stop_spinner' EXIT INT TERM
|
||||||
|
@ -27,7 +27,7 @@ trap on_terminate TERM
|
|||||||
|
|
||||||
function on_exit() {
|
function on_exit() {
|
||||||
local exit_code="$?"
|
local exit_code="$?"
|
||||||
[[ -n "${lockfile:-}" ]]
|
[[ -n "${lockfile:-}" && -e "$lockfile" ]] && rm -f "$lockfile"
|
||||||
exit "$exit_code"
|
exit "$exit_code"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,18 +50,30 @@ function on_terminate() {
|
|||||||
exit 143
|
exit 143
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function check_storage_support() {
|
||||||
|
local CONTENT="$1"
|
||||||
|
local -a VALID_STORAGES=()
|
||||||
|
|
||||||
|
while IFS= read -r line; do
|
||||||
|
local STORAGE=$(awk '{print $1}' <<<"$line")
|
||||||
|
[[ "$STORAGE" == "storage" || -z "$STORAGE" ]] && continue
|
||||||
|
VALID_STORAGES+=("$STORAGE")
|
||||||
|
done < <(pvesm status -content "$CONTENT" 2>/dev/null | awk 'NR>1')
|
||||||
|
|
||||||
|
[[ ${#VALID_STORAGES[@]} -gt 0 ]]
|
||||||
|
}
|
||||||
|
|
||||||
# This checks for the presence of valid Container Storage and Template Storage locations
|
# This checks for the presence of valid Container Storage and Template Storage locations
|
||||||
msg_info "Validating Storage"
|
msg_info "Validating Storage"
|
||||||
VALIDCT=$(pvesm status -content rootdir | awk 'NR>1')
|
if ! check_storage_support "rootdir"; then
|
||||||
if [ -z "$VALIDCT" ]; then
|
msg_error "No valid storage found for 'rootdir' (Container)."
|
||||||
msg_error "Unable to detect a valid Container Storage location."
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
VALIDTMP=$(pvesm status -content vztmpl | awk 'NR>1')
|
if ! check_storage_support "vztmpl"; then
|
||||||
if [ -z "$VALIDTMP" ]; then
|
msg_error "No valid storage found for 'vztmpl' (Template)."
|
||||||
msg_error "Unable to detect a valid Template Storage location."
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
msg_ok "Storage types rootdir and vztmpl are supported."
|
||||||
|
|
||||||
# This function is used to select the storage class and determine the corresponding storage content type and label.
|
# This function is used to select the storage class and determine the corresponding storage content type and label.
|
||||||
function select_storage() {
|
function select_storage() {
|
||||||
@ -107,12 +119,19 @@ function select_storage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
local -a MENU
|
local -a MENU
|
||||||
while read -r line; do
|
local -A STORAGE_MAP=()
|
||||||
local TAG=$(echo $line | awk '{print $1}')
|
local COL_WIDTH=0
|
||||||
local TYPE=$(echo $line | awk '{printf "%-10s", $2}')
|
|
||||||
local FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
|
while read -r TAG TYPE _ TOTAL USED FREE _; do
|
||||||
MENU+=("$TAG" "Type: $TYPE Free: $FREE " "OFF")
|
[[ -n "$TAG" && -n "$TYPE" ]] || continue
|
||||||
done < <(pvesm status -content $CONTENT | awk 'NR>1')
|
local DISPLAY="${TAG} (${TYPE})"
|
||||||
|
local USED_FMT=$(numfmt --to=iec --from-unit=K --format %.1f <<<"$USED")
|
||||||
|
local FREE_FMT=$(numfmt --to=iec --from-unit=K --format %.1f <<<"$FREE")
|
||||||
|
local INFO="Free: ${FREE_FMT}B Used: ${USED_FMT}B"
|
||||||
|
STORAGE_MAP["$DISPLAY"]="$TAG" # Map DISPLAY to actual TAG
|
||||||
|
MENU+=("$DISPLAY" "$INFO" "OFF")
|
||||||
|
((${#DISPLAY} > COL_WIDTH)) && COL_WIDTH=${#DISPLAY}
|
||||||
|
done < <(pvesm status -content "$CONTENT" | awk 'NR>1')
|
||||||
|
|
||||||
if [ ${#MENU[@]} -eq 0 ]; then
|
if [ ${#MENU[@]} -eq 0 ]; then
|
||||||
msg_error "No storage found for content type '$CONTENT'."
|
msg_error "No storage found for content type '$CONTENT'."
|
||||||
@ -120,18 +139,32 @@ function select_storage() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [ $((${#MENU[@]} / 3)) -eq 1 ]; then
|
if [ $((${#MENU[@]} / 3)) -eq 1 ]; then
|
||||||
printf "%s" "${MENU[0]}"
|
echo "${STORAGE_MAP[${MENU[0]}]}"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local STORAGE
|
local WIDTH=$((COL_WIDTH + 42))
|
||||||
STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
|
local DISPLAY_SELECTED=""
|
||||||
"Which storage pool for ${CONTENT_LABEL,,}?\n(Spacebar to select)" \
|
while true; do
|
||||||
16 70 6 "${MENU[@]}" 3>&1 1>&2 2>&3) || {
|
DISPLAY_SELECTED=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
|
||||||
msg_error "Storage selection cancelled by user."
|
"Which storage pool for ${CONTENT_LABEL,,}?\n(Spacebar to select)" \
|
||||||
exit 202
|
16 "$WIDTH" 6 "${MENU[@]}" 3>&1 1>&2 2>&3) || {
|
||||||
}
|
msg_error "Storage selection cancelled by user."
|
||||||
printf "%s" "$STORAGE"
|
exit 202
|
||||||
|
}
|
||||||
|
|
||||||
|
# Validierung gegen STORAGE_MAP
|
||||||
|
if [[ -z "$DISPLAY_SELECTED" || -z "${STORAGE_MAP[$DISPLAY_SELECTED]+_}" ]]; then
|
||||||
|
whiptail --backtitle "Proxmox VE Helper Scripts" --title "Invalid Selection" \
|
||||||
|
--msgbox "No valid storage selected. Please choose a storage pool to continue." 9 60
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
break
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "${STORAGE_MAP["$DISPLAY_SELECTED"]}"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Test if required variables are set
|
# Test if required variables are set
|
||||||
@ -172,10 +205,29 @@ if [[ -f "$DEFAULT_FILE" ]]; then
|
|||||||
msg_ok "Using ${BL}$CONTAINER_STORAGE${CL} ${GN}for Container Storage."
|
msg_ok "Using ${BL}$CONTAINER_STORAGE${CL} ${GN}for Container Storage."
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
TEMPLATE_STORAGE=$(select_storage template)
|
# TEMPLATE STORAGE SELECTION
|
||||||
|
# Template Storage
|
||||||
|
if ! TEMPLATE_STORAGE=$(select_storage template); then
|
||||||
|
[[ $? -eq 202 ]] && {
|
||||||
|
msg_error "Template Storage selection cancelled by user. Exiting."
|
||||||
|
kill -INT $$
|
||||||
|
}
|
||||||
|
msg_error "Unexpected error during template storage selection."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
msg_ok "Using ${BL}$TEMPLATE_STORAGE${CL} ${GN}for Template Storage."
|
msg_ok "Using ${BL}$TEMPLATE_STORAGE${CL} ${GN}for Template Storage."
|
||||||
CONTAINER_STORAGE=$(select_storage container)
|
|
||||||
|
# Container Storage
|
||||||
|
if ! CONTAINER_STORAGE=$(select_storage container); then
|
||||||
|
[[ $? -eq 202 ]] && {
|
||||||
|
msg_error "Container Storage selection cancelled by user. Exiting."
|
||||||
|
kill -INT $$
|
||||||
|
}
|
||||||
|
msg_error "Unexpected error during container storage selection."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
msg_ok "Using ${BL}$CONTAINER_STORAGE${CL} ${GN}for Container Storage."
|
msg_ok "Using ${BL}$CONTAINER_STORAGE${CL} ${GN}for Container Storage."
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check free space on selected container storage
|
# Check free space on selected container storage
|
||||||
|
@ -31,7 +31,7 @@ catch_errors() {
|
|||||||
|
|
||||||
# This function handles errors
|
# This function handles errors
|
||||||
error_handler() {
|
error_handler() {
|
||||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func)
|
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/api.func)
|
||||||
printf "\e[?25h"
|
printf "\e[?25h"
|
||||||
local exit_code="$?"
|
local exit_code="$?"
|
||||||
local line_number="$1"
|
local line_number="$1"
|
||||||
@ -65,7 +65,8 @@ setting_up_container() {
|
|||||||
rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED
|
rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED
|
||||||
systemctl disable -q --now systemd-networkd-wait-online.service
|
systemctl disable -q --now systemd-networkd-wait-online.service
|
||||||
msg_ok "Set up Container OS"
|
msg_ok "Set up Container OS"
|
||||||
msg_custom "${CM}" "${GN}" "Network Connected: ${BL}$(hostname -I)"
|
#msg_custom "${CM}" "${GN}" "Network Connected: ${BL}$(hostname -I)"
|
||||||
|
msg_ok "Network Connected: ${BL}$(hostname -I)"
|
||||||
}
|
}
|
||||||
|
|
||||||
# This function checks the network connection by pinging a known IP address and prompts the user to continue if the internet is not connected
|
# This function checks the network connection by pinging a known IP address and prompts the user to continue if the internet is not connected
|
||||||
@ -104,24 +105,24 @@ network_check() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# DNS resolution checks for GitHub-related domains (IPv4 and/or IPv6)
|
# DNS resolution checks for GitHub-related domains (IPv4 and/or IPv6)
|
||||||
GITHUB_HOSTS=("github.com" "raw.githubusercontent.com" "api.github.com" "git.community-scripts.org")
|
GIT_HOSTS=("github.com" "raw.githubusercontent.com" "api.github.com" "git.community-scripts.org")
|
||||||
GITHUB_STATUS="GitHub DNS:"
|
GIT_STATUS="Git DNS:"
|
||||||
DNS_FAILED=false
|
DNS_FAILED=false
|
||||||
|
|
||||||
for HOST in "${GITHUB_HOSTS[@]}"; do
|
for HOST in "${GIT_HOSTS[@]}"; do
|
||||||
RESOLVEDIP=$(getent hosts "$HOST" | awk '{ print $1 }' | grep -E '(^([0-9]{1,3}\.){3}[0-9]{1,3}$)|(^[a-fA-F0-9:]+$)' | head -n1)
|
RESOLVEDIP=$(getent hosts "$HOST" | awk '{ print $1 }' | grep -E '(^([0-9]{1,3}\.){3}[0-9]{1,3}$)|(^[a-fA-F0-9:]+$)' | head -n1)
|
||||||
if [[ -z "$RESOLVEDIP" ]]; then
|
if [[ -z "$RESOLVEDIP" ]]; then
|
||||||
GITHUB_STATUS+="$HOST:($DNSFAIL)"
|
GIT_STATUS+="$HOST:($DNSFAIL)"
|
||||||
DNS_FAILED=true
|
DNS_FAILED=true
|
||||||
else
|
else
|
||||||
GITHUB_STATUS+=" $HOST:($DNSOK)"
|
GIT_STATUS+=" $HOST:($DNSOK)"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
if [[ "$DNS_FAILED" == true ]]; then
|
if [[ "$DNS_FAILED" == true ]]; then
|
||||||
fatal "$GITHUB_STATUS"
|
fatal "$GIT_STATUS"
|
||||||
else
|
else
|
||||||
msg_ok "$GITHUB_STATUS"
|
msg_ok "$GIT_STATUS"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
167
misc/tools.func
167
misc/tools.func
@ -238,7 +238,6 @@ setup_mariadb() {
|
|||||||
msg_info "Setting up MariaDB $MARIADB_VERSION"
|
msg_info "Setting up MariaDB $MARIADB_VERSION"
|
||||||
# grab dynamic latest LTS version
|
# grab dynamic latest LTS version
|
||||||
if [[ "$MARIADB_VERSION" == "latest" ]]; then
|
if [[ "$MARIADB_VERSION" == "latest" ]]; then
|
||||||
$STD msg_info "Resolving latest GA MariaDB version"
|
|
||||||
MARIADB_VERSION=$(curl -fsSL http://mirror.mariadb.org/repo/ |
|
MARIADB_VERSION=$(curl -fsSL http://mirror.mariadb.org/repo/ |
|
||||||
grep -Eo '[0-9]+\.[0-9]+\.[0-9]+/' |
|
grep -Eo '[0-9]+\.[0-9]+\.[0-9]+/' |
|
||||||
grep -vE 'rc/|rolling/' |
|
grep -vE 'rc/|rolling/' |
|
||||||
@ -249,7 +248,6 @@ setup_mariadb() {
|
|||||||
msg_error "Could not determine latest GA MariaDB version"
|
msg_error "Could not determine latest GA MariaDB version"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
$STD msg_ok "Latest GA MariaDB version is $MARIADB_VERSION"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local CURRENT_VERSION=""
|
local CURRENT_VERSION=""
|
||||||
@ -274,7 +272,6 @@ setup_mariadb() {
|
|||||||
$STD msg_info "Setup MariaDB $MARIADB_VERSION"
|
$STD msg_info "Setup MariaDB $MARIADB_VERSION"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
$STD msg_info "Setting up MariaDB Repository"
|
|
||||||
curl -fsSL "https://mariadb.org/mariadb_release_signing_key.asc" |
|
curl -fsSL "https://mariadb.org/mariadb_release_signing_key.asc" |
|
||||||
gpg --dearmor -o /etc/apt/trusted.gpg.d/mariadb.gpg
|
gpg --dearmor -o /etc/apt/trusted.gpg.d/mariadb.gpg
|
||||||
|
|
||||||
@ -824,19 +821,30 @@ function fetch_and_deploy_gh_release() {
|
|||||||
elif [[ "$mode" == "binary" ]]; then
|
elif [[ "$mode" == "binary" ]]; then
|
||||||
local arch
|
local arch
|
||||||
arch=$(dpkg --print-architecture 2>/dev/null || uname -m)
|
arch=$(dpkg --print-architecture 2>/dev/null || uname -m)
|
||||||
[[ "$arch" == "x86_64" ]] && arch="x86_64"
|
[[ "$arch" == "x86_64" ]] && arch="amd64"
|
||||||
[[ "$arch" == "aarch64" ]] && arch="arm64"
|
[[ "$arch" == "aarch64" ]] && arch="arm64"
|
||||||
|
|
||||||
local assets url_match=""
|
local assets url_match=""
|
||||||
assets=$(echo "$json" | jq -r '.assets[].browser_download_url')
|
assets=$(echo "$json" | jq -r '.assets[].browser_download_url')
|
||||||
|
|
||||||
for u in $assets; do
|
# If explicit filename pattern is provided (param $6), match that first
|
||||||
if [[ "$u" =~ ($arch|amd64|x86_64|aarch64|arm64).*\.deb$ ]]; then
|
if [[ -n "$6" ]]; then
|
||||||
url_match="$u"
|
for u in $assets; do
|
||||||
break
|
[[ "$u" =~ $6 || "$u" == *"$6" ]] && url_match="$u" && break
|
||||||
fi
|
done
|
||||||
done
|
fi
|
||||||
|
|
||||||
|
# If no match via explicit pattern, fall back to architecture heuristic
|
||||||
|
if [[ -z "$url_match" ]]; then
|
||||||
|
for u in $assets; do
|
||||||
|
if [[ "$u" =~ ($arch|amd64|x86_64|aarch64|arm64).*\.deb$ ]]; then
|
||||||
|
url_match="$u"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Fallback: any .deb file
|
||||||
if [[ -z "$url_match" ]]; then
|
if [[ -z "$url_match" ]]; then
|
||||||
for u in $assets; do
|
for u in $assets; do
|
||||||
[[ "$u" =~ \.deb$ ]] && url_match="$u" && break
|
[[ "$u" =~ \.deb$ ]] && url_match="$u" && break
|
||||||
@ -1611,3 +1619,142 @@ function setup_imagemagick() {
|
|||||||
ensure_usr_local_bin_persist
|
ensure_usr_local_bin_persist
|
||||||
msg_ok "Setup ImageMagick $VERSION"
|
msg_ok "Setup ImageMagick $VERSION"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# Installs FFmpeg from source or prebuilt binary (Debian/Ubuntu only).
|
||||||
|
#
|
||||||
|
# Description:
|
||||||
|
# - Downloads and builds FFmpeg from GitHub (https://github.com/FFmpeg/FFmpeg)
|
||||||
|
# - Supports specific version override via FFMPEG_VERSION (e.g. n7.1.1)
|
||||||
|
# - Supports build profile via FFMPEG_TYPE:
|
||||||
|
# - minimal : x264, vpx, mp3 only
|
||||||
|
# - medium : adds subtitles, fonts, opus, vorbis
|
||||||
|
# - full : adds dav1d, svt-av1, zlib, numa
|
||||||
|
# - binary : downloads static build (johnvansickle.com)
|
||||||
|
# - Defaults to latest stable version and full feature set
|
||||||
|
#
|
||||||
|
# Notes:
|
||||||
|
# - Requires: curl, jq, build-essential, and matching codec libraries
|
||||||
|
# - Result is installed to /usr/local/bin/ffmpeg
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function setup_ffmpeg() {
|
||||||
|
local TMP_DIR
|
||||||
|
TMP_DIR=$(mktemp -d)
|
||||||
|
local GITHUB_REPO="FFmpeg/FFmpeg"
|
||||||
|
local VERSION="${FFMPEG_VERSION:-}"
|
||||||
|
local TYPE="${FFMPEG_TYPE:-full}"
|
||||||
|
local BIN_PATH="/usr/local/bin/ffmpeg"
|
||||||
|
|
||||||
|
# Binary fallback mode
|
||||||
|
if [[ "$TYPE" == "binary" ]]; then
|
||||||
|
msg_info "Installing FFmpeg (static binary)"
|
||||||
|
curl -fsSL https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz -o "$TMP_DIR/ffmpeg.tar.xz"
|
||||||
|
tar -xf "$TMP_DIR/ffmpeg.tar.xz" -C "$TMP_DIR"
|
||||||
|
local EXTRACTED_DIR
|
||||||
|
EXTRACTED_DIR=$(find "$TMP_DIR" -maxdepth 1 -type d -name "ffmpeg-*")
|
||||||
|
cp "$EXTRACTED_DIR/ffmpeg" "$BIN_PATH"
|
||||||
|
cp "$EXTRACTED_DIR/ffprobe" /usr/local/bin/ffprobe
|
||||||
|
chmod +x "$BIN_PATH" /usr/local/bin/ffprobe
|
||||||
|
rm -rf "$TMP_DIR"
|
||||||
|
msg_ok "Installed FFmpeg binary ($($BIN_PATH -version | head -n1))"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Auto-detect latest stable version if none specified
|
||||||
|
if [[ -z "$VERSION" ]]; then
|
||||||
|
msg_info "Fetching latest stable FFmpeg tag"
|
||||||
|
VERSION=$(curl -fsSL "https://api.github.com/repos/${GITHUB_REPO}/tags" |
|
||||||
|
jq -r '.[].name' |
|
||||||
|
grep -E '^n[0-9]+\.[0-9]+\.[0-9]+$' | # stable only
|
||||||
|
sort -V | tail -n1)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "$VERSION" ]]; then
|
||||||
|
msg_error "Could not determine FFmpeg version"
|
||||||
|
rm -rf "$TMP_DIR"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
msg_info "Installing FFmpeg ${VERSION} ($TYPE)"
|
||||||
|
|
||||||
|
# Dependency selection
|
||||||
|
local DEPS=(build-essential yasm nasm pkg-config)
|
||||||
|
case "$TYPE" in
|
||||||
|
minimal)
|
||||||
|
DEPS+=(libx264-dev libvpx-dev libmp3lame-dev)
|
||||||
|
;;
|
||||||
|
medium)
|
||||||
|
DEPS+=(libx264-dev libvpx-dev libmp3lame-dev libfreetype6-dev libass-dev libopus-dev libvorbis-dev)
|
||||||
|
;;
|
||||||
|
full)
|
||||||
|
DEPS+=(
|
||||||
|
libx264-dev libx265-dev libvpx-dev libmp3lame-dev
|
||||||
|
libfreetype6-dev libass-dev libopus-dev libvorbis-dev
|
||||||
|
libdav1d-dev libsvtav1-dev zlib1g-dev libnuma-dev
|
||||||
|
)
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
msg_error "Invalid FFMPEG_TYPE: $TYPE"
|
||||||
|
rm -rf "$TMP_DIR"
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
$STD apt-get update
|
||||||
|
$STD apt-get install -y "${DEPS[@]}"
|
||||||
|
|
||||||
|
curl -fsSL "https://github.com/${GITHUB_REPO}/archive/refs/tags/${VERSION}.tar.gz" -o "$TMP_DIR/ffmpeg.tar.gz"
|
||||||
|
tar -xzf "$TMP_DIR/ffmpeg.tar.gz" -C "$TMP_DIR"
|
||||||
|
cd "$TMP_DIR/FFmpeg-"* || {
|
||||||
|
msg_error "Source extraction failed"
|
||||||
|
rm -rf "$TMP_DIR"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
local args=(
|
||||||
|
--enable-gpl
|
||||||
|
--enable-shared
|
||||||
|
--enable-nonfree
|
||||||
|
--disable-static
|
||||||
|
--enable-libx264
|
||||||
|
--enable-libvpx
|
||||||
|
--enable-libmp3lame
|
||||||
|
)
|
||||||
|
|
||||||
|
if [[ "$TYPE" != "minimal" ]]; then
|
||||||
|
args+=(--enable-libfreetype --enable-libass --enable-libopus --enable-libvorbis)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$TYPE" == "full" ]]; then
|
||||||
|
args+=(--enable-libx265 --enable-libdav1d --enable-zlib)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ${#args[@]} -eq 0 ]]; then
|
||||||
|
msg_error "FFmpeg configure args array is empty – aborting."
|
||||||
|
rm -rf "$TMP_DIR"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
./configure "${args[@]}" >"$TMP_DIR/configure.log" 2>&1 || {
|
||||||
|
msg_error "FFmpeg ./configure failed (see $TMP_DIR/configure.log)"
|
||||||
|
cat "$TMP_DIR/configure.log" | tail -n 20
|
||||||
|
rm -rf "$TMP_DIR"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
$STD make -j"$(nproc)"
|
||||||
|
$STD make install
|
||||||
|
|
||||||
|
if ! command -v ffmpeg &>/dev/null; then
|
||||||
|
msg_error "FFmpeg installation failed"
|
||||||
|
rm -rf "$TMP_DIR"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local FINAL_VERSION
|
||||||
|
FINAL_VERSION=$(ffmpeg -version | head -n1 | awk '{print $3}')
|
||||||
|
rm -rf "$TMP_DIR"
|
||||||
|
ensure_usr_local_bin_persist
|
||||||
|
msg_ok "Setup FFmpeg $FINAL_VERSION"
|
||||||
|
}
|
||||||
|
@ -40,53 +40,72 @@ CM="${TAB}✔️${TAB}${CL}"
|
|||||||
|
|
||||||
header_info
|
header_info
|
||||||
echo "Loading..."
|
echo "Loading..."
|
||||||
whiptail --backtitle "Proxmox VE Helper Scripts" --title "Proxmox VE LXC Deletion" --yesno "This will delete LXC containers. Proceed?" 10 58
|
if ! whiptail --backtitle "Proxmox VE Helper Scripts" --title "Proxmox VE LXC Deletion" --yesno "This will delete LXC containers. Proceed?" 10 58; then
|
||||||
|
echo -e "${RD}Aborted by user.${CL}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
NODE=$(hostname)
|
mapfile -t containers < <(pct list | tail -n +2)
|
||||||
containers=$(pct list | tail -n +2 | awk '{print $0 " " $4}')
|
|
||||||
|
|
||||||
if [ -z "$containers" ]; then
|
if [ ${#containers[@]} -eq 0 ]; then
|
||||||
whiptail --title "LXC Container Delete" --msgbox "No LXC containers available!" 10 60
|
whiptail --title "LXC Container Delete" --msgbox "No LXC containers available!" 10 60
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
menu_items=("ALL" "Delete ALL containers" "OFF") # Add as first option
|
menu_items=("ALL" "Delete ALL containers" "OFF")
|
||||||
FORMAT="%-10s %-15s %-10s"
|
FORMAT="%-10s %-10s %-10s %-10s"
|
||||||
|
|
||||||
while read -r container; do
|
for line in "${containers[@]}"; do
|
||||||
container_id=$(echo $container | awk '{print $1}')
|
container_id=$(echo "$line" | awk '{print $1}')
|
||||||
container_name=$(echo $container | awk '{print $2}')
|
container_name=$(echo "$line" | awk '{print $2}')
|
||||||
container_status=$(echo $container | awk '{print $3}')
|
container_status=$(echo "$line" | awk '{print $3}')
|
||||||
formatted_line=$(printf "$FORMAT" "$container_name" "$container_status")
|
container_os=$(echo "$line" | awk '{print $4}')
|
||||||
|
protected=$(pct config "$container_id" | awk '/^protection:/ {print $2}')
|
||||||
|
is_protected="No"
|
||||||
|
[[ "$protected" == "1" ]] && is_protected="Yes"
|
||||||
|
formatted_line=$(printf "$FORMAT" "$container_name" "$container_status" "$container_os" "$is_protected")
|
||||||
menu_items+=("$container_id" "$formatted_line" "OFF")
|
menu_items+=("$container_id" "$formatted_line" "OFF")
|
||||||
done <<<"$containers"
|
done
|
||||||
|
|
||||||
CHOICES=$(whiptail --title "LXC Container Delete" \
|
CHOICES=$(whiptail --title "LXC Container Delete" \
|
||||||
--checklist "Select LXC containers to delete:" 25 60 13 \
|
--checklist "Select LXC containers to delete:\n\nNAME STATUS OS PROTECTED" 25 70 15 \
|
||||||
"${menu_items[@]}" 3>&2 2>&1 1>&3)
|
"${menu_items[@]}" 3>&2 2>&1 1>&3)
|
||||||
|
|
||||||
if [ -z "$CHOICES" ]; then
|
if [ -z "$CHOICES" ]; then
|
||||||
whiptail --title "LXC Container Delete" \
|
whiptail --title "LXC Container Delete" --msgbox "No containers selected!" 10 60
|
||||||
--msgbox "No containers selected!" 10 60
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
read -p "Delete containers manually or automatically? (Default: manual) m/a: " DELETE_MODE
|
read -p "Delete containers manually or automatically? (Default: manual) m/a: " DELETE_MODE
|
||||||
DELETE_MODE=${DELETE_MODE:-m}
|
DELETE_MODE=${DELETE_MODE:-m}
|
||||||
|
|
||||||
selected_ids=$(echo "$CHOICES" | tr -d '"' | tr -s ' ' '\n')
|
selected_ids=$(echo "$CHOICES" | tr -d '"' | tr -s ' ' '\n')
|
||||||
|
|
||||||
# If "ALL" is selected, override with all container IDs
|
# ALL ausgewählt
|
||||||
if echo "$selected_ids" | grep -q "^ALL$"; then
|
if echo "$selected_ids" | grep -q "^ALL$"; then
|
||||||
selected_ids=$(echo "$containers" | awk '{print $1}')
|
selected_ids=$(printf '%s\n' "${containers[@]}" | awk '{print $1}')
|
||||||
fi
|
fi
|
||||||
|
|
||||||
for container_id in $selected_ids; do
|
for container_id in $selected_ids; do
|
||||||
status=$(pct status $container_id)
|
status=$(pct status "$container_id")
|
||||||
|
protected=$(pct config "$container_id" | awk '/^protection:/ {print $2}')
|
||||||
|
is_protected="No"
|
||||||
|
[[ "$protected" == "1" ]] && is_protected="Yes"
|
||||||
|
|
||||||
if [ "$status" == "status: running" ]; then
|
if [[ "$is_protected" == "Yes" && "$DELETE_MODE" == "a" ]]; then
|
||||||
|
echo -e "${BL}[Info]${RD} Skipping protected container $container_id (auto mode).${CL}"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$status" == "status: running" ]]; then
|
||||||
|
if [[ "$is_protected" == "Yes" && "$DELETE_MODE" == "m" ]]; then
|
||||||
|
read -p "⚠️ Container $container_id is PROTECTED. Delete anyway? (y/N): " CONFIRM_PROTECTED
|
||||||
|
[[ ! "$CONFIRM_PROTECTED" =~ ^[Yy]$ ]] && {
|
||||||
|
echo -e "${BL}[Info]${RD} Skipping protected container $container_id...${CL}"
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fi
|
||||||
echo -e "${BL}[Info]${GN} Stopping container $container_id...${CL}"
|
echo -e "${BL}[Info]${GN} Stopping container $container_id...${CL}"
|
||||||
pct stop $container_id &
|
pct stop "$container_id" &
|
||||||
sleep 5
|
sleep 5
|
||||||
echo -e "${BL}[Info]${GN} Container $container_id stopped.${CL}"
|
echo -e "${BL}[Info]${GN} Container $container_id stopped.${CL}"
|
||||||
fi
|
fi
|
||||||
@ -96,15 +115,30 @@ for container_id in $selected_ids; do
|
|||||||
pct destroy "$container_id" -f &
|
pct destroy "$container_id" -f &
|
||||||
pid=$!
|
pid=$!
|
||||||
spinner $pid
|
spinner $pid
|
||||||
[ $? -eq 0 ] && echo "Container $container_id deleted." || whiptail --title "Error" --msgbox "Failed to delete container $container_id." 10 60
|
if [ $? -eq 0 ]; then
|
||||||
|
echo "Container $container_id deleted."
|
||||||
|
else
|
||||||
|
whiptail --title "Error" --msgbox "Failed to delete container $container_id." 10 60
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
read -p "Delete container $container_id? (y/N): " CONFIRM
|
read -p "Delete container $container_id? (y/N): " CONFIRM
|
||||||
if [[ "$CONFIRM" =~ ^[Yy]$ ]]; then
|
if [[ "$CONFIRM" =~ ^[Yy]$ ]]; then
|
||||||
|
if [[ "$is_protected" == "Yes" ]]; then
|
||||||
|
read -p "⚠️ Container $container_id is PROTECTED. Delete anyway? (y/N): " CONFIRM_PROTECTED
|
||||||
|
[[ ! "$CONFIRM_PROTECTED" =~ ^[Yy]$ ]] && {
|
||||||
|
echo -e "${BL}[Info]${RD} Skipping protected container $container_id...${CL}"
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fi
|
||||||
echo -e "${BL}[Info]${GN} Deleting container $container_id...${CL}"
|
echo -e "${BL}[Info]${GN} Deleting container $container_id...${CL}"
|
||||||
pct destroy "$container_id" -f &
|
pct destroy "$container_id" -f &
|
||||||
pid=$!
|
pid=$!
|
||||||
spinner $pid
|
spinner $pid
|
||||||
[ $? -eq 0 ] && echo "Container $container_id deleted." || whiptail --title "Error" --msgbox "Failed to delete container $container_id." 10 60
|
if [ $? -eq 0 ]; then
|
||||||
|
echo "Container $container_id deleted."
|
||||||
|
else
|
||||||
|
whiptail --title "Error" --msgbox "Failed to delete container $container_id." 10 60
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${BL}[Info]${RD} Skipping container $container_id...${CL}"
|
echo -e "${BL}[Info]${RD} Skipping container $container_id...${CL}"
|
||||||
fi
|
fi
|
||||||
|
Loading…
x
Reference in New Issue
Block a user