Merge branch 'community-scripts:main' into pr-update-lxcs-services

This commit is contained in:
Rémi Bédard-Couture 2025-07-02 14:09:12 -04:00 committed by GitHub
commit 507057693a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
45 changed files with 1464 additions and 1133 deletions

View File

@ -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}"

View File

@ -11,7 +11,7 @@ var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-512}"
var_disk="${var_disk:-1}"
var_os="${var_os:-alpine}"
var_version="${var_version:-3.21}"
var_version="${var_version:-3.22}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"

View File

@ -40,5 +40,5 @@ start
build_container
description
msg_ok "Completed Successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
msg_ok "Completed Successfully!"
msg_custom "🚀" "${GN}" "${APP} setup has been successfully initialized!"

View File

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

View File

@ -1,6 +0,0 @@
_ __
(_) /__________ ___ ____ ____ _
/ / __/ ___/ __ `__ \/ __ \/ __ `/
/ / /_(__ ) / / / / / / / / /_/ /
/_/\__/____/_/ /_/ /_/_/ /_/\__, /
/____/

View File

@ -1,6 +0,0 @@
__ ____ _____
/ /__ / / /_ __/ __(_)___
__ / / _ \/ / / / / / /_/ / __ \
/ /_/ / __/ / / /_/ / __/ / / / /
\____/\___/_/_/\__, /_/ /_/_/ /_/
/____/

View File

@ -1,6 +0,0 @@
__ __
/ //_/___ _____ ____ _ ______ ___________
/ ,< / __ `/ __ \/ __ \ | /| / / __ `/ ___/ ___/
/ /| / /_/ / /_/ / /_/ / |/ |/ / /_/ / / / /
/_/ |_\__,_/ .___/\____/|__/|__/\__,_/_/ /_/
/_/

View File

@ -1,6 +0,0 @@
_ ______ __ ___ __
/ | / / __ \/ |/ /___ / /_ _______
/ |/ / /_/ / /|_/ / __ \/ / / / / ___/
/ /| / ____/ / / / /_/ / / /_/ (__ )
/_/ |_/_/ /_/ /_/ .___/_/\__,_/____/
/_/

6
ct/headers/scraparr Normal file
View File

@ -0,0 +1,6 @@
_____
/ ___/______________ _____ ____ ___________
\__ \/ ___/ ___/ __ `/ __ \/ __ `/ ___/ ___/
___/ / /__/ / / /_/ / /_/ / /_/ / / / /
/____/\___/_/ \__,_/ .___/\__,_/_/ /_/
/_/

6
ct/headers/zigbee2mqtt Normal file
View File

@ -0,0 +1,6 @@
_____ _ __ ___ __ _______ ____________
/__ / (_)___ _/ /_ ___ ___ |__ \ / |/ / __ \/_ __/_ __/
/ / / / __ `/ __ \/ _ \/ _ \__/ // /|_/ / / / / / / / /
/ /__/ / /_/ / /_/ / __/ __/ __// / / / /_/ / / / / /
/____/_/\__, /_.___/\___/\___/____/_/ /_/\___\_\/_/ /_/
/____/

View File

@ -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}"

View File

@ -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}"

View File

@ -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}"

View File

@ -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
View 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
View 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}"

View 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": []
}

View 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": []
}

View 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": []
}

View 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": []
}

View File

@ -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": []
}

View File

@ -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": []
}

View 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": []
}

View 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": []
}

View 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": []
}

View 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": []
}

View 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"
}
]
}

View File

@ -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",
"version": "v0.22.2075",
"date": "2025-06-28T10:16:17Z"
"version": "v0.22.2107",
"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",
"version": "3.1.0",
"date": "2025-06-28T09:02:38Z"
},
{
"name": "firefly-iii/firefly-iii",
"version": "v6.2.19",
"date": "2025-06-28T06:53:45Z"
},
{
"name": "esphome/esphome",
"version": "2025.6.2",
@ -34,51 +259,21 @@
"version": "v1.5.0",
"date": "2025-06-27T22:04:32Z"
},
{
"name": "linkwarden/linkwarden",
"version": "v2.11.1",
"date": "2025-06-27T21:21:59Z"
},
{
"name": "homarr-labs/homarr",
"version": "v1.26.0",
"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",
"version": "version/2025.6.3",
"date": "2025-06-27T14:01:06Z"
},
{
"name": "keycloak/keycloak",
"version": "26.2.5",
"date": "2025-05-28T06:49:43Z"
},
{
"name": "rclone/rclone",
"version": "v1.70.2",
"date": "2025-06-27T13:21:17Z"
},
{
"name": "documenso/documenso",
"version": "v1.12.0-rc.7",
"date": "2025-06-27T12:17:45Z"
},
{
"name": "sabnzbd/sabnzbd",
"version": "4.5.1",
@ -89,31 +284,16 @@
"version": "flowise@3.0.3",
"date": "2025-06-27T09:53:57Z"
},
{
"name": "nzbgetcom/nzbget",
"version": "v25.1",
"date": "2025-06-27T09:14:14Z"
},
{
"name": "cockpit-project/cockpit",
"version": "341.1",
"date": "2025-06-27T08:50:16Z"
},
{
"name": "zabbix/zabbix",
"version": "7.2.10",
"date": "2025-06-27T06:40:00Z"
},
{
"name": "MediaBrowser/Emby.Releases",
"version": "4.9.1.2",
"date": "2025-06-26T22:08:00Z"
},
{
"name": "prometheus/prometheus",
"version": "v3.4.2",
"date": "2025-06-26T21:45:21Z"
},
{
"name": "home-assistant/operating-system",
"version": "15.2",
@ -134,11 +314,6 @@
"version": "v1.84.3",
"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",
"version": "v3.5.0-rc1",
@ -164,16 +339,6 @@
"version": "18.0.7",
"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",
"version": "v1.6.1",
@ -184,11 +349,6 @@
"version": "v4.101.2",
"date": "2025-06-25T21:18:52Z"
},
{
"name": "msgbyte/tianji",
"version": "v1.22.4",
"date": "2025-06-25T20:46:20Z"
},
{
"name": "influxdata/influxdb",
"version": "v3.2.0",
@ -199,21 +359,11 @@
"version": "2.0.5",
"date": "2025-06-25T14:53:31Z"
},
{
"name": "jenkinsci/jenkins",
"version": "jenkins-2.504.3",
"date": "2025-06-25T14:43:01Z"
},
{
"name": "bunkerity/bunkerweb",
"version": "testing",
"date": "2025-06-16T18:10:42Z"
},
{
"name": "n8n-io/n8n",
"version": "n8n@1.100.0",
"date": "2025-06-23T12:48:35Z"
},
{
"name": "moghtech/komodo",
"version": "v1.18.4",
@ -239,31 +389,11 @@
"version": "v2.18.0",
"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",
"version": "preview-fix-proxy-axios",
"date": "2025-06-24T08:50:22Z"
},
{
"name": "wazuh/wazuh",
"version": "coverity-w26-4.13.0",
"date": "2025-06-24T02:02:34Z"
},
{
"name": "minio/minio",
"version": "RELEASE.2025-06-13T11-33-47Z",
@ -279,11 +409,6 @@
"version": "pmm-6401-v1.120.0",
"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",
"version": "1.22.0",
@ -294,11 +419,6 @@
"version": "2025.6.22",
"date": "2025-06-22T22:41:11Z"
},
{
"name": "qbittorrent/qBittorrent",
"version": "release-5.1.1",
"date": "2025-06-22T21:41:17Z"
},
{
"name": "clusterzx/paperless-ai",
"version": "v3.0.7",
@ -314,31 +434,16 @@
"version": "0.17.14",
"date": "2025-06-21T23:43:04Z"
},
{
"name": "HabitRPG/habitica",
"version": "v5.37.0",
"date": "2025-06-21T14:05:12Z"
},
{
"name": "rogerfar/rdt-client",
"version": "v2.0.114",
"date": "2025-06-21T11:20:21Z"
},
{
"name": "theonedev/onedev",
"version": "v11.11.1",
"date": "2025-06-21T09:23:39Z"
},
{
"name": "pocketbase/pocketbase",
"version": "v0.28.4",
"date": "2025-06-21T08:29:04Z"
},
{
"name": "dgtlmoon/changedetection.io",
"version": "0.50.4",
"date": "2025-06-21T07:47:02Z"
},
{
"name": "go-gitea/gitea",
"version": "v1.24.2",
@ -354,11 +459,6 @@
"version": "v4.0.15.2941",
"date": "2025-06-20T17:20:54Z"
},
{
"name": "syncthing/syncthing",
"version": "2.0.0-rc.19",
"date": "2025-06-02T17:56:25Z"
},
{
"name": "benzino77/tasmocompiler",
"version": "v12.7.0",
@ -389,79 +489,9 @@
"version": "v3.5.5",
"date": "2025-06-19T05:43:47Z"
},
{
"name": "docmost/docmost",
"version": "v0.21.0",
"date": "2025-06-18T21:43:27Z"
},
{
"name": "ipfs/kubo",
"version": "v0.35.0",
"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"
}
]

View 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": []
}

View File

@ -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

View File

@ -17,6 +17,8 @@ msg_info "Installing Dependencies"
$STD apt-get install -y gpg
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 "planka" "plankanban/planka" "prebuild" "latest" "/opt/planka" "planka-prebuild.zip"

View File

@ -1,9 +1,9 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2025 tteck
# Author: tteck (tteckster)
# License: MIT
# https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Copyright (c) 2021-2025 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://hanko.io/
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
color

View File

@ -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"

View File

@ -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"

View File

@ -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"

View 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"

View File

@ -14,41 +14,35 @@ update_os
msg_info "Installing Dependencies (Patience)"
$STD apt-get install -y \
curl \
git \
unzip \
sudo \
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
redis
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"
DB_NAME=wallabag_db
DB_USER=wallabag
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)"
$STD mysql -u root -e "CREATE DATABASE $DB_NAME;"
$STD mysql -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 "CREATE DATABASE $DB_NAME;"
$STD mariadb -u root -e "CREATE USER '$DB_USER'@'localhost' IDENTIFIED BY '$DB_PASS';"
$STD mariadb -u root -e "GRANT ALL PRIVILEGES ON $DB_NAME.* TO '$DB_USER'@'localhost'; FLUSH PRIVILEGES;"
{
echo "Wallabag Credentials"
echo "Database User: $DB_USER"
echo "Database Password: $DB_PASS"
echo "Database Name: $DB_NAME"
} >> ~/wallabag.creds
} >>~/wallabag.creds
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)"
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
useradd -d /opt/wallabag -s /bin/bash -M wallabag
chown -R wallabag:wallabag /opt/wallabag

View File

@ -186,92 +186,92 @@ ssh_check() {
fi
}
select_storage() {
local CLASS=$1 CONTENT CONTENT_LABEL
case $CLASS in
container)
CONTENT='rootdir'
CONTENT_LABEL='Container'
;;
template)
CONTENT='vztmpl'
CONTENT_LABEL='Template'
;;
iso)
CONTENT='iso'
CONTENT_LABEL='ISO image'
;;
images)
CONTENT='images'
CONTENT_LABEL='VM Disk image'
;;
backup)
CONTENT='backup'
CONTENT_LABEL='Backup'
;;
snippets)
CONTENT='snippets'
CONTENT_LABEL='Snippets'
;;
*)
msg_error "Invalid storage class '$CLASS'."
exit 201
;;
esac
# select_storage() {
# local CLASS=$1 CONTENT CONTENT_LABEL
# case $CLASS in
# container)
# CONTENT='rootdir'
# CONTENT_LABEL='Container'
# ;;
# template)
# CONTENT='vztmpl'
# CONTENT_LABEL='Template'
# ;;
# iso)
# CONTENT='iso'
# CONTENT_LABEL='ISO image'
# ;;
# images)
# CONTENT='images'
# CONTENT_LABEL='VM Disk image'
# ;;
# backup)
# CONTENT='backup'
# CONTENT_LABEL='Backup'
# ;;
# snippets)
# CONTENT='snippets'
# CONTENT_LABEL='Snippets'
# ;;
# *)
# msg_error "Invalid storage class '$CLASS'."
# exit 201
# ;;
# esac
command -v whiptail >/dev/null || {
msg_error "whiptail missing."
exit 220
}
command -v numfmt >/dev/null || {
msg_error "numfmt missing."
exit 221
}
# command -v whiptail >/dev/null || {
# msg_error "whiptail missing."
# exit 220
# }
# command -v numfmt >/dev/null || {
# msg_error "numfmt missing."
# exit 221
# }
local -a MENU
while read -r line; do
local TAG=$(echo "$line" | awk '{print $1}')
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}')
MENU+=("$TAG" "Type: $TYPE Free: $FREE" "OFF")
done < <(pvesm status -content "$CONTENT" | awk 'NR>1')
# local -a MENU
# while read -r line; do
# local TAG=$(echo "$line" | awk '{print $1}')
# 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}')
# MENU+=("$TAG" "Type: $TYPE Free: $FREE" "OFF")
# done < <(pvesm status -content "$CONTENT" | awk 'NR>1')
if [ ${#MENU[@]} -eq 0 ]; then
msg_error "No storage found for content type '$CONTENT'."
exit 203
fi
# if [ ${#MENU[@]} -eq 0 ]; then
# msg_error "No storage found for content type '$CONTENT'."
# exit 203
# fi
if [ $((${#MENU[@]} / 3)) -eq 1 ]; then
echo "${MENU[0]}"
return
fi
# if [ $((${#MENU[@]} / 3)) -eq 1 ]; then
# echo "${MENU[0]}"
# return
# fi
local STORAGE
STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
"Which storage pool for ${CONTENT_LABEL,,}?\n(Spacebar to select)" \
16 70 6 "${MENU[@]}" 3>&1 1>&2 2>&3) || {
msg_error "Storage selection cancelled by user."
exit 202
}
echo "$STORAGE"
}
# local STORAGE
# STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
# "Which storage pool for ${CONTENT_LABEL,,}?\n(Spacebar to select)" \
# 16 70 6 "${MENU[@]}" 3>&1 1>&2 2>&3) || {
# msg_error "Storage selection cancelled by user."
# exit 202
# }
# echo "$STORAGE"
# }
manage_default_storage() {
local file="/usr/local/community-scripts/default_storage"
mkdir -p /usr/local/community-scripts
# manage_default_storage() {
# local file="/usr/local/community-scripts/default_storage"
# mkdir -p /usr/local/community-scripts
local tmpl=$(select_storage template)
local cont=$(select_storage container)
# local tmpl=$(select_storage template)
# local cont=$(select_storage container)
cat <<EOF >"$file"
TEMPLATE_STORAGE=$tmpl
CONTAINER_STORAGE=$cont
EOF
# cat <<EOF >"$file"
# TEMPLATE_STORAGE=$tmpl
# CONTAINER_STORAGE=$cont
# EOF
msg_ok "Default Storage set: Template=${BL}$tmpl${CL} ${GN}|${CL} Container=${BL}$cont${CL}"
whiptail --backtitle "[dev] Proxmox VE Helper Scripts" \
--msgbox "Default Storage set:\n\nTemplate: $tmpl\nContainer: $cont" 10 58
}
# msg_ok "Default Storage set: Template=${BL}$tmpl${CL} ${GN}|${CL} Container=${BL}$cont${CL}"
# whiptail --backtitle "[dev] Proxmox VE Helper Scripts" \
# --msgbox "Default Storage set:\n\nTemplate: $tmpl\nContainer: $cont" 10 58
# }
base_settings() {
# Default Settings
@ -333,13 +333,13 @@ write_config() {
CT_TYPE="${CT_TYPE}"
DISK_SIZE="${DISK_SIZE}"
CORE_COUNT="${DISK_SIZE}"
CORE_COUNT="${CORE_COUNT}"
RAM_SIZE="${RAM_SIZE}"
HN="${HN}"
BRG="${BRG}"
APT_CACHER_IP="${APT_CACHER_IP:-none}"
DISABLEIP6="${DISABLEIP6}"
PW="${PW:-none}"
PW='${PW:-none}'
SSH="${SSH}"
SSH_AUTHORIZED_KEY="${SSH_AUTHORIZED_KEY}"
VERBOSE="${VERBOSE}"
@ -351,6 +351,7 @@ SD="${SD:-none}"
MAC="${MAC:-none}"
NS="${NS:-none}"
NET="${NET}"
FUSE="${ENABLE_FUSE}"
EOF
echo -e "${INFO}${BOLD}${GN}Writing configuration to ${FILEPATH}${CL}"
@ -364,7 +365,7 @@ EOF
CT_TYPE="${CT_TYPE}"
DISK_SIZE="${DISK_SIZE}"
CORE_COUNT="${DISK_SIZE}"
CORE_COUNT="${CORE_COUNT}"
RAM_SIZE="${RAM_SIZE}"
HN="${HN}"
BRG="${BRG}"
@ -382,6 +383,7 @@ SD="${SD:-none}"
MAC="${MAC:-none}"
NS="${NS:-none}"
NET="${NET}"
FUSE="${ENABLE_FUSE}"
EOF
echo -e "${INFO}${BOLD}${GN}Writing configuration to ${FILEPATH}${CL}"
@ -402,9 +404,11 @@ echo_default() {
# Output the selected values with icons
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 "${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
echo -e "${SEARCH}${BOLD}${DGN}Verbose Mode: ${BGN}Enabled${CL}"
fi
@ -861,12 +865,12 @@ advanced_settings() {
echo -e "${ROOTSSH}${BOLD}${DGN}Root SSH Access: ${BGN}$SSH${CL}"
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
# ENABLE_FUSE="yes"
# else
# ENABLE_FUSE="no"
# fi
# echo -e "${FUSE}${BOLD}${DGN}Enable FUSE Support: ${BGN}$ENABLE_FUSE${CL}"
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"
else
ENABLE_FUSE="no"
fi
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
VERBOSE="yes"
@ -1195,12 +1199,10 @@ build_container() {
-unprivileged $CT_TYPE
$PW
"
# This executes create_lxc.sh and creates the container and .conf file
CREATE_CMD="bash -c \"\$(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/create_lxc.sh)\""
eval "$CREATE_CMD"
bash -c "$(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/create_lxc.sh)"
RET=$?
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
fi
@ -1273,21 +1275,24 @@ EOF'
pct exec "$CTID" -- ash -c "apk add bash newt curl openssh nano mc ncurses >/dev/null"
else
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 "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 && \
locale-gen >/dev/null && \
export LANG=\$locale_line"
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"
fi
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.

View File

@ -9,21 +9,21 @@
# }
# fi
trap 'on_error $? $LINENO' ERR
trap 'on_exit' EXIT
trap 'on_interrupt' INT
trap 'on_terminate' TERM
# trap 'on_error $? $LINENO' ERR
# trap 'on_exit' EXIT
# trap 'on_interrupt' INT
# trap 'on_terminate' TERM
if ! declare -f wait_for >/dev/null; then
wait_for() {
true
}
fi
# if ! declare -f wait_for >/dev/null; then
# wait_for() {
# true
# }
# fi
declare -A MSG_INFO_SHOWN=()
SPINNER_PID=""
SPINNER_ACTIVE=0
SPINNER_MSG=""
# declare -A MSG_INFO_SHOWN=()
# SPINNER_PID=""
# SPINNER_ACTIVE=0
# SPINNER_MSG=""
# ------------------------------------------------------------------------------
# Loads core utility groups once (colors, formatting, icons, defaults).
@ -47,9 +47,9 @@ load_functions() {
# Error & Signal Handling robust, universal, subshell-safe
# ============================================================================
_stop_spinner_on_error() {
[[ -n "${SPINNER_PID:-}" ]] && kill "$SPINNER_PID" 2>/dev/null && wait "$SPINNER_PID" 2>/dev/null || true
}
# _stop_spinner_on_error() {
# [[ -n "${SPINNER_PID:-}" ]] && kill "$SPINNER_PID" 2>/dev/null && wait "$SPINNER_PID" 2>/dev/null || true
# }
_tool_error_hint() {
local cmd="$1"
@ -89,44 +89,39 @@ _tool_error_hint() {
esac
}
on_error() {
local code="$?"
local line="${BASH_LINENO[0]:-unknown}"
local cmd="${BASH_COMMAND:-unknown}"
# on_error() {
# local code="$?"
# local line="${BASH_LINENO[0]:-unknown}"
# local cmd="${BASH_COMMAND:-unknown}"
# Signalcode unterdrücken, falls INT/TERM kommt
[[ "$code" == "130" || "$code" == "143" ]] && return
# # Signalcode unterdrücken, falls INT/TERM kommt
# [[ "$code" == "130" || "$code" == "143" ]] && return
_stop_spinner_on_error
msg_error "Script failed at line $line with exit code $code: $cmd"
exit "$code"
}
# _stop_spinner_on_error
# msg_error "Script failed at line $line with exit code $code: $cmd"
# exit "$code"
# }
on_exit() {
_stop_spinner_on_error
[[ "${VERBOSE:-no}" == "yes" ]] && msg_info "Script exited cleanly"
}
# on_exit() {
# _stop_spinner_on_error
# [[ "${VERBOSE:-no}" == "yes" ]] && msg_info "Script exited cleanly"
# }
on_interrupt() {
_stop_spinner_on_error
msg_error "Interrupted by user (CTRL+C)"
exit 130
}
# on_interrupt() {
# _stop_spinner_on_error
# msg_error "Interrupted by user (CTRL+C)"
# exit 130
# }
on_terminate() {
_stop_spinner_on_error
msg_error "Terminated by signal (SIGTERM)"
exit 143
}
# on_terminate() {
# _stop_spinner_on_error
# msg_error "Terminated by signal (SIGTERM)"
# exit 143
# }
catch_errors() {
trap 'on_error' ERR
trap 'on_exit' EXIT
trap 'on_interrupt' INT
trap 'on_terminate' TERM
set -Eeuo pipefail
shopt -s inherit_errexit
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
}
# ------------------------------------------------------------------------------
@ -143,6 +138,13 @@ color() {
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.
# ------------------------------------------------------------------------------
@ -363,149 +365,215 @@ fatal() {
kill -INT $$
}
# Ensure POSIX compatibility across Alpine and Debian/Ubuntu
# === Spinner Start ===
# Trap cleanup on various signals
trap 'cleanup_spinner' EXIT INT TERM HUP
# # Ensure POSIX compatibility across Alpine and Debian/Ubuntu
# # === Spinner Start ===
# # Trap cleanup on various signals
# trap 'cleanup_spinner' EXIT INT TERM HUP
spinner_frames=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
# spinner_frames=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
# === Spinner Start ===
start_spinner() {
local msg="$1"
local spin_i=0
local interval=0.1
# # === Spinner Start ===
# start_spinner() {
# local msg="$1"
# local spin_i=0
# local interval=0.1
stop_spinner
SPINNER_MSG="$msg"
SPINNER_ACTIVE=1
# stop_spinner
# SPINNER_MSG="$msg"
# SPINNER_ACTIVE=1
{
while [[ "$SPINNER_ACTIVE" -eq 1 ]]; do
if [[ -t 2 ]]; then
printf "\r\e[2K%s %b" "${TAB}${spinner_frames[spin_i]}${TAB}" "${YW}${SPINNER_MSG}${CL}" >&2
else
printf "%s...\n" "$SPINNER_MSG" >&2
break
fi
spin_i=$(((spin_i + 1) % ${#spinner_frames[@]}))
sleep "$interval"
# {
# while [[ "$SPINNER_ACTIVE" -eq 1 ]]; do
# if [[ -t 2 ]]; then
# printf "\r\e[2K%s %b" "${TAB}${spinner_frames[spin_i]}${TAB}" "${YW}${SPINNER_MSG}${CL}" >&2
# else
# printf "%s...\n" "$SPINNER_MSG" >&2
# break
# fi
# spin_i=$(((spin_i + 1) % ${#spinner_frames[@]}))
# sleep "$interval"
# done
# } &
# local pid=$!
# if ps -p "$pid" >/dev/null 2>&1; then
# SPINNER_PID="$pid"
# else
# SPINNER_ACTIVE=0
# SPINNER_PID=""
# 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
} &
local pid=$!
if ps -p "$pid" >/dev/null 2>&1; then
SPINNER_PID="$pid"
else
SPINNER_ACTIVE=0
SPINNER_PID=""
fi
}
# === Spinner Stop ===
stop_spinner() {
if [[ "$SPINNER_ACTIVE" -eq 1 && -n "$SPINNER_PID" ]]; then
SPINNER_ACTIVE=0
local pid="${SPINNER_PID:-}"
[[ -z "$pid" && -f /tmp/.spinner.pid ]] && pid=$(</tmp/.spinner.pid)
if kill -0 "$SPINNER_PID" 2>/dev/null; then
kill "$SPINNER_PID" 2>/dev/null || true
for _ in $(seq 1 10); do
if [[ -n "$pid" && "$pid" =~ ^[0-9]+$ ]]; then
if kill "$pid" 2>/dev/null; then
sleep 0.05
kill -0 "$SPINNER_PID" 2>/dev/null || break
done
kill -9 "$pid" 2>/dev/null || true
wait "$pid" 2>/dev/null || true
fi
rm -f /tmp/.spinner.pid
unset SPINNER_PID
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
stty sane 2>/dev/null
#printf "\r\033[K\e[?25h\n"
}
msg_info() {
local msg="$1"
[[ -z "$msg" || -n "${MSG_INFO_SHOWN["$msg"]+x}" ]] && return
MSG_INFO_SHOWN["$msg"]=1
stop_spinner
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_MSG="$msg"
color_spinner
spinner &
SPINNER_PID=$!
echo "$SPINNER_PID" >/tmp/.spinner.pid
disown "$SPINNER_PID" 2>/dev/null || true
}
msg_ok() {
local msg="$1"
[[ -z "$msg" ]] && return
stop_spinner
printf "\r\e[2K%s %b\n" "$CM" "${GN}${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
local msg="$1"
echo -e "${BFR:-} ${CM:-✔️} ${GN}${msg}${CL}"
}
msg_error() {
local msg="$1"
[[ -z "$msg" ]] && return
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() {
local msg="$1"
[[ -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
local msg="$1"
echo -e "${BFR:-} ${INFO:-} ${YWB}${msg}${CL}"
}
msg_custom() {
local symbol="${1:-"[*]"}"
local color="${2:-"\e[36m"}" # Default: Cyan
local color="${2:-"\e[36m"}"
local msg="${3:-}"
[[ -z "$msg" ]] && return
stop_spinner 2>/dev/null || true
printf "\r\e[2K%s %b\n" "$symbol" "${color}${msg}${CL:-\e[0m}" >&2
stop_spinner
echo -e "${BFR:-} ${symbol} ${color}${msg}${CL:-\e[0m}"
printf "\r\033[K\e[?25h\n"
}
msg_progress() {
local current="$1"
local total="$2"
local label="$3"
local width=40
local filled percent bar empty
local fill_char="#"
local empty_char="-"
# msg_ok() {
# local msg="$1"
# [[ -z "$msg" ]] && return
# stop_spinner
# printf "\r\e[2K%s %b\n" "$CM" "${GN}${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
# }
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
# msg_error() {
# local msg="$1"
# [[ -z "$msg" ]] && return
# stop_spinner
# printf "\r\e[2K%s %b\n" "$CROSS" "${RD}${msg}${CL}" >&2
# }
percent=$(((current * 100) / total))
filled=$(((current * width) / total))
empty=$((width - filled))
# msg_warn() {
# local msg="$1"
# [[ -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")
bar+=$(printf "%${empty}s" | tr ' ' "$empty_char")
# msg_custom() {
# 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
printf "\n" >&2
fi
}
# msg_progress() {
# local current="$1"
# 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() {
local ct="$1"
@ -555,3 +623,5 @@ check_or_create_swap() {
return 1
fi
}
trap 'stop_spinner' EXIT INT TERM

View File

@ -27,7 +27,7 @@ trap on_terminate TERM
function on_exit() {
local exit_code="$?"
[[ -n "${lockfile:-}" ]]
[[ -n "${lockfile:-}" && -e "$lockfile" ]] && rm -f "$lockfile"
exit "$exit_code"
}
@ -50,18 +50,30 @@ function on_terminate() {
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
msg_info "Validating Storage"
VALIDCT=$(pvesm status -content rootdir | awk 'NR>1')
if [ -z "$VALIDCT" ]; then
msg_error "Unable to detect a valid Container Storage location."
if ! check_storage_support "rootdir"; then
msg_error "No valid storage found for 'rootdir' (Container)."
exit 1
fi
VALIDTMP=$(pvesm status -content vztmpl | awk 'NR>1')
if [ -z "$VALIDTMP" ]; then
msg_error "Unable to detect a valid Template Storage location."
if ! check_storage_support "vztmpl"; then
msg_error "No valid storage found for 'vztmpl' (Template)."
exit 1
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.
function select_storage() {
@ -107,12 +119,19 @@ function select_storage() {
}
local -a MENU
while read -r line; do
local TAG=$(echo $line | awk '{print $1}')
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)}')
MENU+=("$TAG" "Type: $TYPE Free: $FREE " "OFF")
done < <(pvesm status -content $CONTENT | awk 'NR>1')
local -A STORAGE_MAP=()
local COL_WIDTH=0
while read -r TAG TYPE _ TOTAL USED FREE _; do
[[ -n "$TAG" && -n "$TYPE" ]] || continue
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
msg_error "No storage found for content type '$CONTENT'."
@ -120,18 +139,32 @@ function select_storage() {
fi
if [ $((${#MENU[@]} / 3)) -eq 1 ]; then
printf "%s" "${MENU[0]}"
echo "${STORAGE_MAP[${MENU[0]}]}"
return
fi
local STORAGE
STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
local WIDTH=$((COL_WIDTH + 42))
local DISPLAY_SELECTED=""
while true; do
DISPLAY_SELECTED=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
"Which storage pool for ${CONTENT_LABEL,,}?\n(Spacebar to select)" \
16 70 6 "${MENU[@]}" 3>&1 1>&2 2>&3) || {
16 "$WIDTH" 6 "${MENU[@]}" 3>&1 1>&2 2>&3) || {
msg_error "Storage selection cancelled by user."
exit 202
}
printf "%s" "$STORAGE"
# 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
@ -172,10 +205,29 @@ if [[ -f "$DEFAULT_FILE" ]]; then
msg_ok "Using ${BL}$CONTAINER_STORAGE${CL} ${GN}for Container Storage."
fi
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."
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."
fi
# Check free space on selected container storage

View File

@ -31,7 +31,7 @@ catch_errors() {
# This function handles errors
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"
local exit_code="$?"
local line_number="$1"
@ -65,7 +65,8 @@ setting_up_container() {
rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED
systemctl disable -q --now systemd-networkd-wait-online.service
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
@ -104,24 +105,24 @@ network_check() {
fi
# 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")
GITHUB_STATUS="GitHub DNS:"
GIT_HOSTS=("github.com" "raw.githubusercontent.com" "api.github.com" "git.community-scripts.org")
GIT_STATUS="Git DNS:"
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)
if [[ -z "$RESOLVEDIP" ]]; then
GITHUB_STATUS+="$HOST:($DNSFAIL)"
GIT_STATUS+="$HOST:($DNSFAIL)"
DNS_FAILED=true
else
GITHUB_STATUS+=" $HOST:($DNSOK)"
GIT_STATUS+=" $HOST:($DNSOK)"
fi
done
if [[ "$DNS_FAILED" == true ]]; then
fatal "$GITHUB_STATUS"
fatal "$GIT_STATUS"
else
msg_ok "$GITHUB_STATUS"
msg_ok "$GIT_STATUS"
fi
set -e

View File

@ -238,7 +238,6 @@ setup_mariadb() {
msg_info "Setting up MariaDB $MARIADB_VERSION"
# grab dynamic latest LTS version
if [[ "$MARIADB_VERSION" == "latest" ]]; then
$STD msg_info "Resolving latest GA MariaDB version"
MARIADB_VERSION=$(curl -fsSL http://mirror.mariadb.org/repo/ |
grep -Eo '[0-9]+\.[0-9]+\.[0-9]+/' |
grep -vE 'rc/|rolling/' |
@ -249,7 +248,6 @@ setup_mariadb() {
msg_error "Could not determine latest GA MariaDB version"
return 1
fi
$STD msg_ok "Latest GA MariaDB version is $MARIADB_VERSION"
fi
local CURRENT_VERSION=""
@ -274,7 +272,6 @@ setup_mariadb() {
$STD msg_info "Setup MariaDB $MARIADB_VERSION"
fi
$STD msg_info "Setting up MariaDB Repository"
curl -fsSL "https://mariadb.org/mariadb_release_signing_key.asc" |
gpg --dearmor -o /etc/apt/trusted.gpg.d/mariadb.gpg
@ -824,19 +821,30 @@ function fetch_and_deploy_gh_release() {
elif [[ "$mode" == "binary" ]]; then
local arch
arch=$(dpkg --print-architecture 2>/dev/null || uname -m)
[[ "$arch" == "x86_64" ]] && arch="x86_64"
[[ "$arch" == "x86_64" ]] && arch="amd64"
[[ "$arch" == "aarch64" ]] && arch="arm64"
local assets url_match=""
assets=$(echo "$json" | jq -r '.assets[].browser_download_url')
# If explicit filename pattern is provided (param $6), match that first
if [[ -n "$6" ]]; then
for u in $assets; do
[[ "$u" =~ $6 || "$u" == *"$6" ]] && url_match="$u" && break
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
for u in $assets; do
[[ "$u" =~ \.deb$ ]] && url_match="$u" && break
@ -1611,3 +1619,142 @@ function setup_imagemagick() {
ensure_usr_local_bin_persist
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"
}

View File

@ -40,53 +40,72 @@ CM="${TAB}✔️${TAB}${CL}"
header_info
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)
containers=$(pct list | tail -n +2 | awk '{print $0 " " $4}')
mapfile -t containers < <(pct list | tail -n +2)
if [ -z "$containers" ]; then
if [ ${#containers[@]} -eq 0 ]; then
whiptail --title "LXC Container Delete" --msgbox "No LXC containers available!" 10 60
exit 1
fi
menu_items=("ALL" "Delete ALL containers" "OFF") # Add as first option
FORMAT="%-10s %-15s %-10s"
menu_items=("ALL" "Delete ALL containers" "OFF")
FORMAT="%-10s %-10s %-10s %-10s"
while read -r container; do
container_id=$(echo $container | awk '{print $1}')
container_name=$(echo $container | awk '{print $2}')
container_status=$(echo $container | awk '{print $3}')
formatted_line=$(printf "$FORMAT" "$container_name" "$container_status")
for line in "${containers[@]}"; do
container_id=$(echo "$line" | awk '{print $1}')
container_name=$(echo "$line" | awk '{print $2}')
container_status=$(echo "$line" | awk '{print $3}')
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")
done <<<"$containers"
done
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)
if [ -z "$CHOICES" ]; then
whiptail --title "LXC Container Delete" \
--msgbox "No containers selected!" 10 60
whiptail --title "LXC Container Delete" --msgbox "No containers selected!" 10 60
exit 1
fi
read -p "Delete containers manually or automatically? (Default: manual) m/a: " DELETE_MODE
DELETE_MODE=${DELETE_MODE:-m}
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
selected_ids=$(echo "$containers" | awk '{print $1}')
selected_ids=$(printf '%s\n' "${containers[@]}" | awk '{print $1}')
fi
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}"
pct stop $container_id &
pct stop "$container_id" &
sleep 5
echo -e "${BL}[Info]${GN} Container $container_id stopped.${CL}"
fi
@ -96,15 +115,30 @@ for container_id in $selected_ids; do
pct destroy "$container_id" -f &
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
read -p "Delete container $container_id? (y/N): " CONFIRM
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}"
pct destroy "$container_id" -f &
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
echo -e "${BL}[Info]${RD} Skipping container $container_id...${CL}"
fi