diff --git a/CHANGELOG.md b/CHANGELOG.md index 0cd78d955..02259874c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,12 +10,241 @@ > [!CAUTION] Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit the project's popularity for potentially malicious purposes. +## 2025-11-06 + +### 🚀 Updated Scripts + + - #### 🐞 Bug Fixes + + - npm: add Debian version check to update script [@MickLesk](https://github.com/MickLesk) ([#8901](https://github.com/community-scripts/ProxmoxVE/pull/8901)) + + - #### ✨ New Features + + - MongoDB: install script now use setup_mongodb [@MickLesk](https://github.com/MickLesk) ([#8897](https://github.com/community-scripts/ProxmoxVE/pull/8897)) + +## 2025-11-05 + +### 🚀 Updated Scripts + + - #### 🐞 Bug Fixes + + - Immich: Pin version to 2.2.3 [@vhsdream](https://github.com/vhsdream) ([#8861](https://github.com/community-scripts/ProxmoxVE/pull/8861)) + - Jotty: increase RAM to 4GB [@vhsdream](https://github.com/vhsdream) ([#8887](https://github.com/community-scripts/ProxmoxVE/pull/8887)) + - Zabbix: fix agent service recognition in update [@MickLesk](https://github.com/MickLesk) ([#8881](https://github.com/community-scripts/ProxmoxVE/pull/8881)) + + - #### 💥 Breaking Changes + + - fix: npm: refactor for v2.13.x [@CrazyWolf13](https://github.com/CrazyWolf13) ([#8870](https://github.com/community-scripts/ProxmoxVE/pull/8870)) + + - #### 🔧 Refactor + + - Refactor: Open WebUI [@tremor021](https://github.com/tremor021) ([#8874](https://github.com/community-scripts/ProxmoxVE/pull/8874)) + - Refactor(tools.func): Add Retry Logic, OS-Upgrade Safety, Smart Version Detection + 10 Critical Bugfixes [@MickLesk](https://github.com/MickLesk) ([#8871](https://github.com/community-scripts/ProxmoxVE/pull/8871)) + +### 🌐 Website + + - #### 📝 Script Information + + - npm: Increase RAM and HDD, update Certbot notes [@MickLesk](https://github.com/MickLesk) ([#8882](https://github.com/community-scripts/ProxmoxVE/pull/8882)) + - Update config_path in donetick.json [@fyxtro](https://github.com/fyxtro) ([#8872](https://github.com/community-scripts/ProxmoxVE/pull/8872)) + +## 2025-11-04 + +### 🚀 Updated Scripts + + - #### ✨ New Features + + - stirling-pdf: add native jbig2 dep to installation script [@MickLesk](https://github.com/MickLesk) ([#8858](https://github.com/community-scripts/ProxmoxVE/pull/8858)) + +## 2025-11-03 + +### 🆕 New Scripts + + - Donetick ([#8835](https://github.com/community-scripts/ProxmoxVE/pull/8835)) + +### 🚀 Updated Scripts + + - #### 🐞 Bug Fixes + + - Immich: Pin version to 2.2.2 [@vhsdream](https://github.com/vhsdream) ([#8848](https://github.com/community-scripts/ProxmoxVE/pull/8848)) + - Asterisk: handle errors in version retrieval commands [@MickLesk](https://github.com/MickLesk) ([#8844](https://github.com/community-scripts/ProxmoxVE/pull/8844)) + - linkstack: fix wrong directory installation [@omertahaoztop](https://github.com/omertahaoztop) ([#8814](https://github.com/community-scripts/ProxmoxVE/pull/8814)) + - Remove BOM from shebang lines in ct scripts [@MickLesk](https://github.com/MickLesk) ([#8833](https://github.com/community-scripts/ProxmoxVE/pull/8833)) + + - #### 💥 Breaking Changes + + - Removed: MeTube [@MickLesk](https://github.com/MickLesk) ([#8830](https://github.com/community-scripts/ProxmoxVE/pull/8830)) + +## 2025-11-02 + +### 🚀 Updated Scripts + + - Zigbee2MQTT: fix: pnpm workspace in update [@fkroeger](https://github.com/fkroeger) ([#8825](https://github.com/community-scripts/ProxmoxVE/pull/8825)) + + - #### 🐞 Bug Fixes + + - Pangolin: Fix install and database migration [@tremor021](https://github.com/tremor021) ([#8828](https://github.com/community-scripts/ProxmoxVE/pull/8828)) + - MediaManager: fix BASE_PATH error preventing main page load [@vhsdream](https://github.com/vhsdream) ([#8821](https://github.com/community-scripts/ProxmoxVE/pull/8821)) + +## 2025-11-01 + +### 🆕 New Scripts + + - Pangolin ([#8809](https://github.com/community-scripts/ProxmoxVE/pull/8809)) + +### 🚀 Updated Scripts + + - #### 🐞 Bug Fixes + + - VictoriaMetrics: Fix release fetching for Victori Logs add-on [@tremor021](https://github.com/tremor021) ([#8807](https://github.com/community-scripts/ProxmoxVE/pull/8807)) + - Immich: Pin version to 2.2.1 [@vhsdream](https://github.com/vhsdream) ([#8800](https://github.com/community-scripts/ProxmoxVE/pull/8800)) + - jellyfin: fix: initial update [@CrazyWolf13](https://github.com/CrazyWolf13) ([#8784](https://github.com/community-scripts/ProxmoxVE/pull/8784)) + +### 🌐 Website + + - frontend: chore: bump debian OS [@CrazyWolf13](https://github.com/CrazyWolf13) ([#8798](https://github.com/community-scripts/ProxmoxVE/pull/8798)) + +## 2025-10-31 + +### 🚀 Updated Scripts + + - #### 🐞 Bug Fixes + + - Reitti: Fix missing data directory [@tremor021](https://github.com/tremor021) ([#8787](https://github.com/community-scripts/ProxmoxVE/pull/8787)) + - omada: fix update script with mongodb 8 [@MickLesk](https://github.com/MickLesk) ([#8724](https://github.com/community-scripts/ProxmoxVE/pull/8724)) + - Booklore: Fix port configuration for Nginx [@tremor021](https://github.com/tremor021) ([#8780](https://github.com/community-scripts/ProxmoxVE/pull/8780)) + - Fix paths in grist.sh [@mrinaldi](https://github.com/mrinaldi) ([#8777](https://github.com/community-scripts/ProxmoxVE/pull/8777)) + +### 🌐 Website + + - #### 📝 Script Information + + - Removed errant ` from wireguard.json [@AndrewDragonCh](https://github.com/AndrewDragonCh) ([#8791](https://github.com/community-scripts/ProxmoxVE/pull/8791)) + +## 2025-10-30 + +### 🆕 New Scripts + + - Livebook ([#8739](https://github.com/community-scripts/ProxmoxVE/pull/8739)) +- Reitti ([#8736](https://github.com/community-scripts/ProxmoxVE/pull/8736)) +- BentoPDF ([#8735](https://github.com/community-scripts/ProxmoxVE/pull/8735)) + +### 🚀 Updated Scripts + + - #### 🐞 Bug Fixes + + - Open Archiver: Fix missing daemon-reload [@tremor021](https://github.com/tremor021) ([#8768](https://github.com/community-scripts/ProxmoxVE/pull/8768)) + - Open Archiver: Fix missing command in update procedure [@tremor021](https://github.com/tremor021) ([#8765](https://github.com/community-scripts/ProxmoxVE/pull/8765)) + - Kimai: Fix database connection string [@tremor021](https://github.com/tremor021) ([#8758](https://github.com/community-scripts/ProxmoxVE/pull/8758)) + - Add explicit exit calls to update_script functions [@MickLesk](https://github.com/MickLesk) ([#8752](https://github.com/community-scripts/ProxmoxVE/pull/8752)) + - kimai: Set global SQL mode to empty in install script [@MickLesk](https://github.com/MickLesk) ([#8747](https://github.com/community-scripts/ProxmoxVE/pull/8747)) + + - #### ✨ New Features + + - Immich: Updates for v2.2.0 [@vhsdream](https://github.com/vhsdream) ([#8770](https://github.com/community-scripts/ProxmoxVE/pull/8770)) + - Standardize update success messages in scripts [@MickLesk](https://github.com/MickLesk) ([#8757](https://github.com/community-scripts/ProxmoxVE/pull/8757)) + - core: add function cleanup_lxc [@MickLesk](https://github.com/MickLesk) ([#8749](https://github.com/community-scripts/ProxmoxVE/pull/8749)) + - Asterisk: add interactive version selection to installer [@MickLesk](https://github.com/MickLesk) ([#8726](https://github.com/community-scripts/ProxmoxVE/pull/8726)) + +### 🌐 Website + + - #### 📝 Script Information + + - Cronicle: Update default credentials [@tremor021](https://github.com/tremor021) ([#8720](https://github.com/community-scripts/ProxmoxVE/pull/8720)) + +## 2025-10-29 + +### 🚀 Updated Scripts + + - #### 🐞 Bug Fixes + + - Docker-VM: add workaround for libguestfs issue on Proxmox VE 9+ [@MickLesk](https://github.com/MickLesk) ([#8722](https://github.com/community-scripts/ProxmoxVE/pull/8722)) + - Dispatcharr: add folders in installer / add more build ressources [@MickLesk](https://github.com/MickLesk) ([#8708](https://github.com/community-scripts/ProxmoxVE/pull/8708)) + - LibreTranslate: bump torch version [@MickLesk](https://github.com/MickLesk) ([#8710](https://github.com/community-scripts/ProxmoxVE/pull/8710)) + + - #### ✨ New Features + + - Archivebox: add Chromium and Node modules [@MickLesk](https://github.com/MickLesk) ([#8725](https://github.com/community-scripts/ProxmoxVE/pull/8725)) + + - #### 🔧 Refactor + + - tracktor: refactor envfile [@CrazyWolf13](https://github.com/CrazyWolf13) ([#8711](https://github.com/community-scripts/ProxmoxVE/pull/8711)) + - Kimai / Ghost / ManageMyDamnLife: Switch to MariaDB [@MickLesk](https://github.com/MickLesk) ([#8712](https://github.com/community-scripts/ProxmoxVE/pull/8712)) + +## 2025-10-28 + +### 🚀 Updated Scripts + + - #### 🐞 Bug Fixes + + - Update alpine-komodo.sh fixing missing pull images command [@glopes](https://github.com/glopes) ([#8689](https://github.com/community-scripts/ProxmoxVE/pull/8689)) + + - #### ✨ New Features + + - Update SABnzbd. Include par2cmdline-turbo [@burgerga](https://github.com/burgerga) ([#8648](https://github.com/community-scripts/ProxmoxVE/pull/8648)) + - jotty: Add more ENV VARS (disabled) [@vhsdream](https://github.com/vhsdream) ([#8688](https://github.com/community-scripts/ProxmoxVE/pull/8688)) + - Bump bazarr to Debian 13 [@burgerga](https://github.com/burgerga) ([#8677](https://github.com/community-scripts/ProxmoxVE/pull/8677)) + - Update flaresolverr to Debian 13 [@burgerga](https://github.com/burgerga) ([#8672](https://github.com/community-scripts/ProxmoxVE/pull/8672)) + +## 2025-10-27 + +### 🆕 New Scripts + + - Dispatcharr ([#8658](https://github.com/community-scripts/ProxmoxVE/pull/8658)) +- Garage | Alpine-Garage ([#8656](https://github.com/community-scripts/ProxmoxVE/pull/8656)) + +### 🚀 Updated Scripts + + - #### 🐞 Bug Fixes + + - Add typescript and esbuild to browserless setup [@MickLesk](https://github.com/MickLesk) ([#8666](https://github.com/community-scripts/ProxmoxVE/pull/8666)) + - jellyfin: fix: intel deps [@CrazyWolf13](https://github.com/CrazyWolf13) ([#8657](https://github.com/community-scripts/ProxmoxVE/pull/8657)) + +## 2025-10-26 + +### 🆕 New Scripts + + - ComfyUI ([#8633](https://github.com/community-scripts/ProxmoxVE/pull/8633)) + +### 🚀 Updated Scripts + + - #### 🐞 Bug Fixes + + - PiHole: Bump to Debian 12 [@MickLesk](https://github.com/MickLesk) ([#8649](https://github.com/community-scripts/ProxmoxVE/pull/8649)) + + - #### 🔧 Refactor + + - Refactor: Mylar3 [@tremor021](https://github.com/tremor021) ([#8642](https://github.com/community-scripts/ProxmoxVE/pull/8642)) + +## 2025-10-25 + +### 🆕 New Scripts + + - PatchMon ([#8632](https://github.com/community-scripts/ProxmoxVE/pull/8632)) + +### 🚀 Updated Scripts + + - #### 🐞 Bug Fixes + + - UrBackup Server: Fix install going interactive [@tremor021](https://github.com/tremor021) ([#8622](https://github.com/community-scripts/ProxmoxVE/pull/8622)) + +## 2025-10-24 + +### 🌐 Website + + - #### 📝 Script Information + + - Fix config path for BunkerWeb [@Nonolanlan1007](https://github.com/Nonolanlan1007) ([#8618](https://github.com/community-scripts/ProxmoxVE/pull/8618)) + - Update logo URL in guardian.json [@HydroshieldMKII](https://github.com/HydroshieldMKII) ([#8615](https://github.com/community-scripts/ProxmoxVE/pull/8615)) + ## 2025-10-23 ### 🚀 Updated Scripts - #### 🐞 Bug Fixes + - Radicale: Update dependencies [@ilofX](https://github.com/ilofX) ([#8603](https://github.com/community-scripts/ProxmoxVE/pull/8603)) + - Various Downgrades to Debian 12 (MySQL / OMW / Technitium) [@MickLesk](https://github.com/MickLesk) ([#8595](https://github.com/community-scripts/ProxmoxVE/pull/8595)) - MeTube: Fix inserting path into .bashrc [@tremor021](https://github.com/tremor021) ([#8589](https://github.com/community-scripts/ProxmoxVE/pull/8589)) - #### 🔧 Refactor diff --git a/ct/2fauth.sh b/ct/2fauth.sh index a98850017..f6ffecc21 100644 --- a/ct/2fauth.sh +++ b/ct/2fauth.sh @@ -66,7 +66,7 @@ function update_script() { $STD apt -y autoclean $STD apt -y clean msg_ok "Cleanup Completed" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/actualbudget.sh b/ct/actualbudget.sh index 55b80b1f9..3dd4c4bf0 100644 --- a/ct/actualbudget.sh +++ b/ct/actualbudget.sh @@ -44,6 +44,7 @@ function update_script() { msg_info "Starting Service" systemctl start actualbudget msg_ok "Started Service" + msg_ok "Updated successfully!" else msg_info "${APP} is already up to date" fi @@ -51,7 +52,7 @@ function update_script() { msg_info "Old Installation Found, you need to migrate your data and recreate to a new container" msg_info "Please follow the instructions on the ${APP} website to migrate your data" msg_info "https://actualbudget.org/docs/backup-restore/backup" - exit 1 + exit fi exit } diff --git a/ct/adventurelog.sh b/ct/adventurelog.sh index 65e48a0ca..2902c76cf 100644 --- a/ct/adventurelog.sh +++ b/ct/adventurelog.sh @@ -73,7 +73,7 @@ function update_script() { msg_info "Cleaning Up" rm -rf /opt/adventurelog-backup msg_ok "Cleaned" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/agentdvr.sh b/ct/agentdvr.sh index b006590b6..c0d9fd5ce 100644 --- a/ct/agentdvr.sh +++ b/ct/agentdvr.sh @@ -27,7 +27,7 @@ function update_script() { msg_error "No ${APP} Installation Found!" exit fi - + RELEASE=$(curl -fsSL "https://www.ispyconnect.com/api/Agent/DownloadLocation4?platform=Linux64&fromVersion=0" | grep -o 'https://.*\.zip') if [[ "${RELEASE}" != "$(cat ~/.agentdvr 2>/dev/null)" ]] || [[ ! -f ~/.agentdvr ]]; then msg_info "Stopping service" @@ -39,15 +39,14 @@ function update_script() { curl -fsSL "$RELEASE" -o $(basename "$RELEASE") $STD unzip -o Agent_Linux64*.zip chmod +x ./Agent - echo $RELEASE > ~/.agentdvr + echo $RELEASE >~/.agentdvr rm -rf Agent_Linux64*.zip msg_ok "Updated $APP" msg_info "Starting service" systemctl start AgentDVR msg_ok "Service started" - - msg_ok "Updated $APP successfully" + msg_ok "Updated successfully!" else msg_ok "No update required. ${APP} is already at ${RELEASE}" fi diff --git a/ct/alpine-adguard.sh b/ct/alpine-adguard.sh index 5609001ed..4a766ca6b 100644 --- a/ct/alpine-adguard.sh +++ b/ct/alpine-adguard.sh @@ -32,7 +32,7 @@ function update_script() { msg_info "Restarting AdGuard Home" $STD rc-service adguardhome restart msg_ok "Restarted AdGuard Home" - + msg_ok "Updated successfully!" exit 0 } diff --git a/ct/alpine-bitmagnet.sh b/ct/alpine-bitmagnet.sh index d5ccc0b68..90eb6781e 100644 --- a/ct/alpine-bitmagnet.sh +++ b/ct/alpine-bitmagnet.sh @@ -24,7 +24,7 @@ function update_script() { if [[ ! -d /opt/bitmagnet ]]; then msg_error "No ${APP} Installation Found!" - exit 1 + exit fi RELEASE=$(curl -fsSL https://api.github.com/repos/bitmagnet-io/bitmagnet/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }') if [ "${RELEASE}" != "$(cat /opt/bitmagnet_version.txt)" ] || [ ! -f /opt/bitmagnet_version.txt ]; then @@ -71,11 +71,10 @@ function update_script() { rm -f "$temp_file" echo "${RELEASE}" >/opt/bitmagnet_version.txt $STD service bitmagnet start - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" else msg_ok "No update required. ${APP} is already at ${RELEASE}" fi - exit 0 } diff --git a/ct/alpine-caddy.sh b/ct/alpine-caddy.sh index e51ac7fe6..9022647b7 100644 --- a/ct/alpine-caddy.sh +++ b/ct/alpine-caddy.sh @@ -32,7 +32,8 @@ function update_script() { msg_info "Restarting Caddy" rc-service caddy restart msg_ok "Restarted Caddy" - exit + msg_ok "Updated successfully!" + exit 0 } start diff --git a/ct/alpine-docker.sh b/ct/alpine-docker.sh index f18b8edac..698e2b1ba 100644 --- a/ct/alpine-docker.sh +++ b/ct/alpine-docker.sh @@ -37,10 +37,12 @@ function update_script() { case $CHOICE in 1) $STD apk -U upgrade + msg_ok "Updated successfully!" exit ;; esac done + exit 0 } start diff --git a/ct/alpine-forgejo.sh b/ct/alpine-forgejo.sh index ff1773aee..e6e39ecf2 100644 --- a/ct/alpine-forgejo.sh +++ b/ct/alpine-forgejo.sh @@ -31,7 +31,7 @@ function update_script() { msg_info "Restarting Forgejo" $STD rc-service forgejo restart msg_ok "Restarted Forgejo" - + msg_ok "Updated successfully!" exit 0 } diff --git a/ct/alpine-garage.sh b/ct/alpine-garage.sh new file mode 100644 index 000000000..bd48fcc5f --- /dev/null +++ b/ct/alpine-garage.sh @@ -0,0 +1,63 @@ +#!/usr/bin/env bash +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/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://garagehq.deuxfleurs.fr/ + +APP="Alpine-Garage" +var_tags="${var_tags:-alpine;object-storage}" +var_cpu="${var_cpu:-1}" +var_ram="${var_ram:-512}" +var_disk="${var_disk:-5}" +var_os="${var_os:-alpine}" +var_version="${var_version:-3.22}" +var_unprivileged="${var_unprivileged:-1}" + +header_info "$APP" +variables +color +catch_errors + +function update_script() { + header_info + if [[ ! -f /usr/local/bin/garage ]]; then + msg_error "No ${APP} Installation Found!" + exit + fi + + GITEA_RELEASE=$(curl -fsSL https://api.github.com/repos/deuxfleurs-org/garage/tags | jq -r '.[0].name') + if [[ "${GITEA_RELEASE}" != "$(cat ~/.garage 2>/dev/null)" ]] || [[ ! -f ~/.garage ]]; then + msg_info "Stopping Service" + rc-service garage stop || true + msg_ok "Stopped Service" + + msg_info "Backing Up Data" + cp /usr/local/bin/garage /usr/local/bin/garage.old 2>/dev/null || true + cp /etc/garage.toml /etc/garage.toml.bak 2>/dev/null || true + msg_ok "Backed Up Data" + + msg_info "Updating Garage" + curl -fsSL "https://garagehq.deuxfleurs.fr/_releases/${GITEA_RELEASE}/x86_64-unknown-linux-musl/garage" -o /usr/local/bin/garage + chmod +x /usr/local/bin/garage + echo "${GITEA_RELEASE}" >~/.garage + msg_ok "Updated Garage" + + msg_info "Starting Service" + rc-service garage start || rc-service garage restart + msg_ok "Started Service" + msg_ok "Updated successfully!" + else + msg_ok "No update required. Garage is already at ${GITEA_RELEASE}" + fi + 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}http://${IP}${CL}" diff --git a/ct/alpine-gatus.sh b/ct/alpine-gatus.sh index 60e9fccec..0dd2cf0c2 100644 --- a/ct/alpine-gatus.sh +++ b/ct/alpine-gatus.sh @@ -24,7 +24,7 @@ function update_script() { if [[ ! -d /opt/gatus ]]; then msg_error "No ${APP} Installation Found!" - exit 1 + exit fi RELEASE=$(curl -s https://api.github.com/repos/TwiN/gatus/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }') if [ "${RELEASE}" != "$(cat /opt/gatus_version.txt)" ] || [ ! -f /opt/gatus_version.txt ]; then @@ -44,11 +44,10 @@ function update_script() { rm -f "$temp_file" echo "${RELEASE}" >/opt/gatus_version.txt $STD service gatus start - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" else msg_ok "No update required. ${APP} is already at ${RELEASE}" fi - exit 0 } diff --git a/ct/alpine-gitea.sh b/ct/alpine-gitea.sh index 526f87533..993851ff4 100644 --- a/ct/alpine-gitea.sh +++ b/ct/alpine-gitea.sh @@ -32,6 +32,8 @@ function update_script() { msg_info "Restarting Gitea" rc-service gitea restart msg_ok "Restarted Gitea" + msg_ok "Updated successfully!" + exit 0 } start diff --git a/ct/alpine-grafana.sh b/ct/alpine-grafana.sh index 82f7d3220..8c6f64a35 100644 --- a/ct/alpine-grafana.sh +++ b/ct/alpine-grafana.sh @@ -40,20 +40,24 @@ function update_script() { case $CHOICE in 1) $STD apk -U upgrade + msg_ok "Updated successfully!" exit ;; 2) sed -i -e "s/cfg:server.http_addr=.*/cfg:server.http_addr=0.0.0.0/g" /etc/conf.d/grafana service grafana restart + msg_ok "Allowed listening on all interfaces!" exit ;; 3) sed -i -e "s/cfg:server.http_addr=.*/cfg:server.http_addr=$LXCIP/g" /etc/conf.d/grafana service grafana restart + msg_ok "Allowed listening only on ${LXCIP}!" exit ;; esac done + exit 0 } start diff --git a/ct/alpine-it-tools.sh b/ct/alpine-it-tools.sh index fdf8c73db..b06058af8 100644 --- a/ct/alpine-it-tools.sh +++ b/ct/alpine-it-tools.sh @@ -24,7 +24,7 @@ function update_script() { if [ ! -d /usr/share/nginx/html ]; then msg_error "No ${APP} Installation Found!" - exit 1 + exit fi RELEASE=$(curl -fsSL https://api.github.com/repos/sharevb/it-tools/releases/latest | grep '"tag_name":' | cut -d '"' -f4) @@ -37,11 +37,10 @@ function update_script() { cp -r /tmp/dist/* /usr/share/nginx/html rm -rf /tmp/dist rm -f it-tools.zip - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" else msg_ok "No update required. ${APP} is already at ${RELEASE}" fi - exit 0 } diff --git a/ct/alpine-komodo.sh b/ct/alpine-komodo.sh index 50912fe06..a356a1fd0 100644 --- a/ct/alpine-komodo.sh +++ b/ct/alpine-komodo.sh @@ -22,14 +22,14 @@ catch_errors function update_script() { [[ -d /opt/komodo ]] || { msg_error "No ${APP} Installation Found!" - exit 1 + exit } msg_info "Updating ${APP}" COMPOSE_FILE=$(find /opt/komodo -maxdepth 1 -type f -name '*.compose.yaml' ! -name 'compose.env' | head -n1) if [[ -z "$COMPOSE_FILE" ]]; then msg_error "No valid compose file found in /opt/komodo!" - exit 1 + exit fi COMPOSE_BASENAME=$(basename "$COMPOSE_FILE") @@ -38,23 +38,25 @@ function update_script() { echo -e "${YW}This configuration is no longer supported since Komodo v1.18.0.${CL}" echo -e "${YW}Please follow the migration guide:${CL}" echo -e "${BGN}https://github.com/community-scripts/ProxmoxVE/discussions/5689${CL}\n" - exit 1 + exit fi BACKUP_FILE="/opt/komodo/${COMPOSE_BASENAME}.bak_$(date +%Y%m%d_%H%M%S)" cp "$COMPOSE_FILE" "$BACKUP_FILE" || { msg_error "Failed to create backup of ${COMPOSE_BASENAME}!" - exit 1 + exit } GITHUB_URL="https://raw.githubusercontent.com/moghtech/komodo/main/compose/${COMPOSE_BASENAME}" if ! curl -fsSL "$GITHUB_URL" -o "$COMPOSE_FILE"; then msg_error "Failed to download ${COMPOSE_BASENAME} from GitHub!" mv "$BACKUP_FILE" "$COMPOSE_FILE" - exit 1 + exit fi + $STD docker compose -p komodo -f "$COMPOSE_FILE" --env-file /opt/komodo/compose.env pull $STD docker compose -p komodo -f "$COMPOSE_FILE" --env-file /opt/komodo/compose.env up -d - msg_ok "Updated ${APP}" - exit + msg_ok "Updated Alpine-Komodo" + msg_ok "Updated successfully!" + exit 0 } start diff --git a/ct/alpine-mariadb.sh b/ct/alpine-mariadb.sh index 171cac391..55c29ac88 100644 --- a/ct/alpine-mariadb.sh +++ b/ct/alpine-mariadb.sh @@ -31,7 +31,7 @@ function update_script() { msg_info "Restarting MariaDB" $STD rc-service mariadb restart msg_ok "Restarted MariaDB" - + msg_ok "Updated successfully!" exit 0 } diff --git a/ct/alpine-nextcloud.sh b/ct/alpine-nextcloud.sh index 566b9c0d1..624653e30 100644 --- a/ct/alpine-nextcloud.sh +++ b/ct/alpine-nextcloud.sh @@ -50,6 +50,7 @@ function update_script() { ;; esac done + exit 0 } start diff --git a/ct/alpine-node-red.sh b/ct/alpine-node-red.sh index 054cbbb2e..8645fdb15 100644 --- a/ct/alpine-node-red.sh +++ b/ct/alpine-node-red.sh @@ -31,7 +31,7 @@ function update_script() { msg_info "Updating Node-RED" $STD npm install -g --unsafe-perm node-red msg_ok "Updated Node-RED" - + msg_ok "Updated successfully!" exit 0 } diff --git a/ct/alpine-postgresql.sh b/ct/alpine-postgresql.sh index e8ed89045..96b13dd68 100644 --- a/ct/alpine-postgresql.sh +++ b/ct/alpine-postgresql.sh @@ -31,7 +31,7 @@ function update_script() { msg_info "Restarting PostgreSQL" $STD rc-service postgresql restart msg_ok "Restarted PostgreSQL" - + msg_ok "Updated successfully!" exit 0 } diff --git a/ct/alpine-prometheus.sh b/ct/alpine-prometheus.sh index e1b1796e6..6772be228 100644 --- a/ct/alpine-prometheus.sh +++ b/ct/alpine-prometheus.sh @@ -31,7 +31,7 @@ function update_script() { msg_info "Restarting Prometheus" $STD rc-service prometheus restart msg_ok "Restarted Prometheus" - + msg_ok "Updated successfully!" exit 0 } diff --git a/ct/alpine-rclone.sh b/ct/alpine-rclone.sh index c8c4c9255..72f31b4a7 100644 --- a/ct/alpine-rclone.sh +++ b/ct/alpine-rclone.sh @@ -24,7 +24,7 @@ function update_script() { header_info if [ ! -d /opt/rclone ]; then msg_error "No ${APP} Installation Found!" - exit 1 + exit fi RELEASE=$(curl -s https://api.github.com/repos/rclone/rclone/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }') if [ "${RELEASE}" != "$(cat /opt/rclone_version.txt)" ] || [ ! -f /opt/rclone_version.txt ]; then @@ -34,11 +34,10 @@ function update_script() { $STD unzip -o "$temp_file" '*/**' -d /opt/rclone rm -f "$temp_file" echo "${RELEASE}" >/opt/rclone_version.txt - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" else msg_ok "No update required. ${APP} is already at ${RELEASE}" fi - exit 0 } diff --git a/ct/alpine-redis.sh b/ct/alpine-redis.sh index 70ad28207..a42216b9f 100644 --- a/ct/alpine-redis.sh +++ b/ct/alpine-redis.sh @@ -42,7 +42,7 @@ function update_script() { msg_info "Updating Redis" apk update && apk upgrade redis rc-service redis restart - msg_ok "Redis updated successfully!" + msg_ok "Updated successfully!" exit ;; 2) diff --git a/ct/alpine-redlib.sh b/ct/alpine-redlib.sh index fa78845e1..463af04d8 100644 --- a/ct/alpine-redlib.sh +++ b/ct/alpine-redlib.sh @@ -41,9 +41,8 @@ function update_script() { msg_info "Starting Service" $STD rc-service redlib start msg_ok "Started Service" - - msg_ok "Update Successful" - exit + msg_ok "Updated successfully!" + exit 0 } start diff --git a/ct/alpine-rustdeskserver.sh b/ct/alpine-rustdeskserver.sh index 17ba52e4f..40b223c3f 100644 --- a/ct/alpine-rustdeskserver.sh +++ b/ct/alpine-rustdeskserver.sh @@ -23,7 +23,7 @@ function update_script() { header_info if [[ ! -d /opt/rustdesk-server ]]; then msg_error "No ${APP} Installation Found!" - exit 1 + exit fi APIRELEASE=$(curl -s https://api.github.com/repos/lejianwen/rustdesk-api/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }') diff --git a/ct/alpine-syncthing.sh b/ct/alpine-syncthing.sh index 3d41f5dba..fe2bfe6da 100644 --- a/ct/alpine-syncthing.sh +++ b/ct/alpine-syncthing.sh @@ -31,8 +31,8 @@ function update_script() { msg_info "Restarting Syncthing" $STD rc-service syncthing restart msg_ok "Restarted Syncthing" - - exit 1 + msg_ok "Updated successfully!" + exit 0 } start diff --git a/ct/alpine-teamspeak-server.sh b/ct/alpine-teamspeak-server.sh index 524f02aaa..0e84d52e1 100644 --- a/ct/alpine-teamspeak-server.sh +++ b/ct/alpine-teamspeak-server.sh @@ -24,7 +24,7 @@ function update_script() { if [[ ! -d /opt/teamspeak-server ]]; then msg_error "No ${APP} Installation Found!" - exit 1 + exit fi set +o pipefail && RELEASE=$(curl -fsSL https://teamspeak.com/en/downloads/#server | sed -n 's/.*teamspeak3-server_linux_amd64-\([0-9.]*[0-9]\).*/\1/p' | head -1) && set -o pipefail @@ -40,11 +40,10 @@ function update_script() { rm -rf teamspeak3-server_linux_amd64 echo "${RELEASE}" >~/.teamspeak-server $STD service teamspeak start - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" else msg_ok "No update required. ${APP} is already at ${RELEASE}" fi - exit 0 } diff --git a/ct/alpine-tinyauth.sh b/ct/alpine-tinyauth.sh index b3e341732..9c5adf6df 100644 --- a/ct/alpine-tinyauth.sh +++ b/ct/alpine-tinyauth.sh @@ -22,7 +22,7 @@ catch_errors function update_script() { if [[ ! -d /opt/tinyauth ]]; then msg_error "No ${APP} Installation Found!" - exit 1 + exit fi msg_info "Updating packages" @@ -45,7 +45,7 @@ function update_script() { msg_info "Restarting Tinyauth" $STD service tinyauth start msg_ok "Restarted Tinyauth" - msg_ok "Updated Tinyauth" + msg_ok "Updated successfully!" else msg_ok "No update required. ${APP} is already at ${RELEASE}" fi diff --git a/ct/alpine-traefik.sh b/ct/alpine-traefik.sh index c472b985a..8c7c0173c 100644 --- a/ct/alpine-traefik.sh +++ b/ct/alpine-traefik.sh @@ -25,10 +25,11 @@ function update_script() { $STD apk -U upgrade msg_ok "Updated Alpine Packages" - msg_info "Upgrading traefik from edge" + msg_info "Updating traefik from edge" $STD apk add traefik --repository=https://dl-cdn.alpinelinux.org/alpine/edge/community - msg_ok "Upgraded traefik" - exit + msg_ok "Updated traefik" + msg_ok "Updated successfully!" + exit 0 } start diff --git a/ct/alpine-transmission.sh b/ct/alpine-transmission.sh index b311e3c96..9c1da6869 100644 --- a/ct/alpine-transmission.sh +++ b/ct/alpine-transmission.sh @@ -31,8 +31,8 @@ function update_script() { msg_info "Restarting Transmission" $STD rc-service transmission-daemon restart msg_ok "Restarted Transmission" - - exit 1 + msg_ok "Updated successfully!" + exit 0 } start diff --git a/ct/alpine-wireguard.sh b/ct/alpine-wireguard.sh index e7d11d49c..47a3ae692 100644 --- a/ct/alpine-wireguard.sh +++ b/ct/alpine-wireguard.sh @@ -36,7 +36,6 @@ function update_script() { $STD ./wgd.sh start msg_ok "WGDashboard updated" fi - exit 0 } diff --git a/ct/alpine.sh b/ct/alpine.sh index ca1c09c0f..803ef695e 100644 --- a/ct/alpine.sh +++ b/ct/alpine.sh @@ -29,7 +29,8 @@ function update_script() { header_info if [ "$UPD" == "1" ]; then $STD apk -U upgrade - exit + msg_ok "Updated successfully!" + exit 0 fi } diff --git a/ct/apache-tika.sh b/ct/apache-tika.sh index 07b3fcf00..952d92a7b 100755 --- a/ct/apache-tika.sh +++ b/ct/apache-tika.sh @@ -47,7 +47,7 @@ function update_script() { msg_info "Cleaning Up" rm -rf /opt/apache-tika/tika-server-standard-prev-version.jar msg_ok "Cleanup Completed" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" else msg_ok "No update required. ${APP} is already at v${RELEASE}" fi diff --git a/ct/apt-cacher-ng.sh b/ct/apt-cacher-ng.sh index 1ee2402be..e85ec453e 100644 --- a/ct/apt-cacher-ng.sh +++ b/ct/apt-cacher-ng.sh @@ -31,6 +31,7 @@ function update_script() { $STD apt-get update $STD apt-get -y upgrade msg_ok "Updated $APP LXC" + msg_ok "Updated successfully!" exit } diff --git a/ct/archivebox.sh b/ct/archivebox.sh index 7a792a7bb..d28661f23 100644 --- a/ct/archivebox.sh +++ b/ct/archivebox.sh @@ -28,12 +28,18 @@ function update_script() { exit fi - NODE_VERSION="22" setup_nodejs + NODE_VERSION="22" NODE_MODULE="@postlight/parser@latest,single-file-cli@latest" setup_nodejs PYTHON_VERSION="3.13" setup_uv - msg_info "Stopping ArchiveBox" + if ! dpkg -l | grep -q "^ii chromium "; then + msg_info "Installing System Dependencies" + $STD apt-get install -y chromium + msg_ok "Installed System Dependencies" + fi + + msg_info "Stopping Service" systemctl stop archivebox - msg_ok "Stopped ArchiveBox" + msg_ok "Stopped Service" msg_info "Upgrading Playwright" $STD uv pip install playwright --system @@ -46,11 +52,10 @@ function update_script() { sudo -u archivebox archivebox init msg_ok "Updated ArchiveBox" - msg_info "Starting ArchiveBox" + msg_info "Starting Service" systemctl start archivebox - msg_ok "Started ArchiveBox" - - msg_ok "Updated Successfully" + msg_ok "Started Service" + msg_ok "Updated successfully!" exit } diff --git a/ct/argus.sh b/ct/argus.sh index 58de85f0b..57c175505 100644 --- a/ct/argus.sh +++ b/ct/argus.sh @@ -37,7 +37,7 @@ function update_script() { msg_info "Starting service" systemctl start argus msg_ok "Service started" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/aria2.sh b/ct/aria2.sh index 9b88f6d48..6f918ce00 100644 --- a/ct/aria2.sh +++ b/ct/aria2.sh @@ -20,18 +20,19 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources - if [[ ! -d /var ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - msg_info "Updating $APP LXC" - $STD apt-get update - $STD apt-get -y upgrade - msg_ok "Updated $APP LXC" + header_info + check_container_storage + check_container_resources + if [[ ! -d /var ]]; then + msg_error "No ${APP} Installation Found!" exit + fi + msg_info "Updating $APP LXC" + $STD apt-get update + $STD apt-get -y upgrade + msg_ok "Updated $APP LXC" + msg_ok "Updated successfully!" + exit } start @@ -41,4 +42,4 @@ 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}:6880${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:6880${CL}" diff --git a/ct/audiobookshelf.sh b/ct/audiobookshelf.sh index 0a8a1919e..81ea9c85c 100644 --- a/ct/audiobookshelf.sh +++ b/ct/audiobookshelf.sh @@ -32,6 +32,7 @@ function update_script() { $STD apt-get update $STD apt-get -y upgrade msg_ok "Updated $APP LXC" + msg_ok "Updated successfully!" exit } diff --git a/ct/authelia.sh b/ct/authelia.sh index c51c00d10..24b1ab0b9 100644 --- a/ct/authelia.sh +++ b/ct/authelia.sh @@ -40,7 +40,7 @@ function update_script() { $STD apt-get -y autoremove $STD apt-get -y autoclean msg_ok "Cleanup Completed" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/autobrr.sh b/ct/autobrr.sh index 7bc8e628f..4db75102a 100644 --- a/ct/autobrr.sh +++ b/ct/autobrr.sh @@ -38,7 +38,7 @@ function update_script() { msg_info "Starting Service" systemctl start autobrr msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/autocaliweb.sh b/ct/autocaliweb.sh index 8b4fdf337..a018cbb93 100644 --- a/ct/autocaliweb.sh +++ b/ct/autocaliweb.sh @@ -68,7 +68,7 @@ function update_script() { systemctl start autocaliweb metadata-change-detector acw-ingest-service acw-auto-zipper msg_ok "Started Services" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/babybuddy.sh b/ct/babybuddy.sh index baf1c3c0f..5bbc75c7c 100644 --- a/ct/babybuddy.sh +++ b/ct/babybuddy.sh @@ -61,7 +61,7 @@ function update_script() { systemctl start uwsgi systemctl start nginx msg_ok "Services Started" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/backrest.sh b/ct/backrest.sh index abc71b0ca..f4b098055 100644 --- a/ct/backrest.sh +++ b/ct/backrest.sh @@ -49,7 +49,7 @@ function update_script() { msg_info "Cleaning up" rm -f "$temp_file" msg_ok "Cleaned up" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" else msg_ok "No update required. ${APP} is already at ${RELEASE}" fi diff --git a/ct/baikal.sh b/ct/baikal.sh index 05a8c41c6..5e0fab8c4 100644 --- a/ct/baikal.sh +++ b/ct/baikal.sh @@ -56,7 +56,7 @@ function update_script() { msg_info "Cleaning up" rm -rf /opt/baikal-backup msg_ok "Cleaned" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/bar-assistant.sh b/ct/bar-assistant.sh index dce83b331..858c4599f 100644 --- a/ct/bar-assistant.sh +++ b/ct/bar-assistant.sh @@ -102,7 +102,7 @@ function update_script() { msg_info "Starting Meilisearch" systemctl start meilisearch msg_ok "Started Meilisearch" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/barcode-buddy.sh b/ct/barcode-buddy.sh index e28491ce0..270d11121 100644 --- a/ct/barcode-buddy.sh +++ b/ct/barcode-buddy.sh @@ -54,7 +54,7 @@ function update_script() { msg_info "Cleaning up" rm -r /opt/barcodebuddy-backup msg_ok "Cleaned" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/bazarr.sh b/ct/bazarr.sh index 4dec01d5c..c7e540113 100755 --- a/ct/bazarr.sh +++ b/ct/bazarr.sh @@ -11,7 +11,7 @@ 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_version="${var_version:-13}" var_unprivileged="${var_unprivileged:-1}" header_info "$APP" @@ -28,16 +28,29 @@ function update_script() { exit fi if check_for_gh_release "bazarr" "morpheus65535/bazarr"; then - PYTHON_VERSION="3.13" setup_uv + msg_info "Stopping Service" + systemctl stop bazarr + msg_ok "Stopped Service" + + PYTHON_VERSION="3.12" setup_uv fetch_and_deploy_gh_release "bazarr" "morpheus65535/bazarr" "prebuild" "latest" "/opt/bazarr" "bazarr.zip" msg_info "Setup Bazarr" mkdir -p /var/lib/bazarr/ chmod 775 /opt/bazarr /var/lib/bazarr/ + if [[ ! -d /opt/bazarr/venv/ ]]; then + $STD uv venv /opt/bazarr/venv --python 3.12 + sed -i "s|ExecStart=/usr/bin/python3 /opt/bazarr/bazarr.py|ExecStart=/opt/bazarr/venv/bin/python3 /opt/bazarr/bazarr.py|g" /etc/systemd/system/bazarr.service + systemctl daemon-reload + fi sed -i.bak 's/--only-binary=Pillow//g' /opt/bazarr/requirements.txt - $STD uv pip install -r /opt/bazarr/requirements.txt --system + $STD uv pip install -r /opt/bazarr/requirements.txt --python /opt/bazarr/venv/bin/python3 msg_ok "Setup Bazarr" - msg_ok "Updated Successfully" + + msg_info "Starting Service" + systemctl start bazarr + msg_ok "Started Service" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/bentopdf.sh b/ct/bentopdf.sh new file mode 100644 index 000000000..f3dbbc470 --- /dev/null +++ b/ct/bentopdf.sh @@ -0,0 +1,62 @@ +#!/usr/bin/env bash +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +# Copyright (c) 2021-2025 community-scripts ORG +# Author: vhsdream +# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE +# Source: https://github.com/alam00000/bentopdf + +APP="BentoPDF" +var_tags="${var_tags:-pdf-editor}" +var_cpu="${var_cpu:-1}" +var_ram="${var_ram:-2048}" +var_disk="${var_disk:-4}" +var_os="${var_os:-debian}" +var_version="${var_version:-13}" +var_unprivileged="${var_unprivileged:-1}" + +header_info "$APP" +variables +color +catch_errors + +function update_script() { + header_info + check_container_storage + check_container_resources + if [[ ! -d /opt/bentopdf ]]; then + msg_error "No ${APP} Installation Found!" + exit + fi + + NODE_VERSION="24" setup_nodejs + + if check_for_gh_release "bentopdf" "alam00000/bentopdf"; then + msg_info "Stopping Service" + systemctl stop bentopdf + msg_ok "Stopped Service" + + CLEAN_INSTALL=1 fetch_and_deploy_gh_release "bentopdf" "alam00000/bentopdf" "tarball" "latest" "/opt/bentopdf" + + msg_info "Updating BentoPDF" + cd /opt/bentopdf + $STD npm ci --no-audit --no-fund + export SIMPLE_MODE=true + $STD npm run build -- --mode production + msg_ok "Updated BentoPDF" + + msg_info "Starting Service" + systemctl start bentopdf + msg_ok "Started Service" + msg_ok "Updated successfully!" + fi + exit +} + +start +build_container +description + +msg_ok "Completed Successfully!\n" +echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}" +echo -e "${INFO}${YW} Access it using the following URL:${CL}" +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8080${CL}" diff --git a/ct/beszel.sh b/ct/beszel.sh index f3d448429..e45d000f3 100644 --- a/ct/beszel.sh +++ b/ct/beszel.sh @@ -20,27 +20,27 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources - if [[ ! -d /opt/beszel ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - msg_info "Stopping $APP" - systemctl stop beszel-hub - msg_ok "Stopped $APP" - - msg_info "Updating $APP" - $STD /opt/beszel/beszel update - sleep 2 && chmod +x /opt/beszel/beszel - msg_ok "Updated $APP" - - msg_info "Starting $APP" - systemctl start beszel-hub - msg_ok "Successfully started $APP" - msg_ok "Update Successful" + header_info + check_container_storage + check_container_resources + if [[ ! -d /opt/beszel ]]; then + msg_error "No ${APP} Installation Found!" exit + fi + msg_info "Stopping Service" + systemctl stop beszel-hub + msg_info "Stopped Service" + + msg_info "Updating $APP" + $STD /opt/beszel/beszel update + sleep 2 && chmod +x /opt/beszel/beszel + msg_ok "Updated $APP" + + msg_info "Starting Service" + systemctl start beszel-hub + msg_ok "Successfully started $APP" + msg_ok "Updated successfully!" + exit } start diff --git a/ct/bitmagnet.sh b/ct/bitmagnet.sh index 765e3e278..b1dcf58c9 100644 --- a/ct/bitmagnet.sh +++ b/ct/bitmagnet.sh @@ -74,7 +74,7 @@ function update_script() { msg_info "Starting Service" systemctl start bitmagnet-web msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/blocky.sh b/ct/blocky.sh index d7184915b..ed6f637e5 100644 --- a/ct/blocky.sh +++ b/ct/blocky.sh @@ -49,7 +49,7 @@ function update_script() { msg_info "Starting Service" systemctl start blocky msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/booklore.sh b/ct/booklore.sh index cf2fef9fb..5ece76d3a 100644 --- a/ct/booklore.sh +++ b/ct/booklore.sh @@ -29,9 +29,9 @@ function update_script() { exit fi if check_for_gh_release "booklore" "booklore-app/BookLore"; then - msg_info "Stopping $APP" + msg_info "Stopping Service" systemctl stop booklore - msg_ok "Stopped $APP" + msg_info "Stopped Service" msg_info "backup old install" mv /opt/booklore /opt/booklore_bak @@ -56,17 +56,17 @@ function update_script() { JAR_PATH=$(find /opt/booklore/booklore-api/build/libs -maxdepth 1 -type f -name "booklore-api-*.jar" ! -name "*plain*" | head -n1) if [[ -z "$JAR_PATH" ]]; then msg_error "Backend JAR not found" - exit 1 + exit fi cp "$JAR_PATH" /opt/booklore/dist/app.jar msg_ok "Built Backend" - msg_info "Starting $APP" + msg_info "Starting Service" systemctl start booklore systemctl reload nginx rm -rf /opt/booklore_bak - msg_ok "Started $APP" - msg_ok "Updated Successfully" + msg_ok "Started Service" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/bookstack.sh b/ct/bookstack.sh index 990f30b26..dab902519 100644 --- a/ct/bookstack.sh +++ b/ct/bookstack.sh @@ -66,7 +66,7 @@ function update_script() { msg_info "Cleaning Up" rm -rf /opt/bookstack-backup msg_ok "Cleaned" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/bunkerweb.sh b/ct/bunkerweb.sh index c58d3680c..34b047be9 100644 --- a/ct/bunkerweb.sh +++ b/ct/bunkerweb.sh @@ -41,7 +41,7 @@ EOF apt-get install -y --allow-downgrades bunkerweb=${RELEASE} echo "${RELEASE}" >/opt/${APP}_version.txt msg_ok "Updated ${APP} to ${RELEASE}" - + msg_ok "Updated successfully!" else msg_ok "No update required. ${APP} is already at ${RELEASE}" fi diff --git a/ct/bytestash.sh b/ct/bytestash.sh index 55aebf29a..5687831aa 100644 --- a/ct/bytestash.sh +++ b/ct/bytestash.sh @@ -54,8 +54,9 @@ function update_script() { msg_error "PLEASE MAKE A BACKUP FIRST!" exit fi - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi + exit } start diff --git a/ct/caddy.sh b/ct/caddy.sh index 143630ea5..a9d0a1c14 100644 --- a/ct/caddy.sh +++ b/ct/caddy.sh @@ -20,31 +20,33 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources - if [[ ! -d /etc/caddy ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - msg_info "Updating $APP LXC" - $STD apt-get update - $STD apt-get -y upgrade - msg_ok "Updated $APP LXC" + header_info + check_container_storage + check_container_resources + if [[ ! -d /etc/caddy ]]; then + msg_error "No ${APP} Installation Found!" + exit + fi + msg_info "Updating $APP LXC" + $STD apt-get update + $STD apt-get -y upgrade + msg_ok "Updated successfully!" + msg_ok "Updated $APP LXC" - if command -v xcaddy >/dev/null 2>&1; then - setup_go - msg_info "Updating xCaddy" - cd /opt - RELEASE=$(curl -fsSL https://api.github.com/repos/caddyserver/xcaddy/releases/latest | grep "tag_name" | awk -F '"' '{print $4}') - VERSION="${RELEASE#v}" - curl -fsSL "https://github.com/caddyserver/xcaddy/releases/download/${RELEASE}/xcaddy_${VERSION}_linux_amd64.deb" -o "xcaddy_${VERSION}_linux_amd64.deb" - $STD dpkg -i "xcaddy_${VERSION}_linux_amd64.deb" - rm -f "xcaddy_${VERSION}_linux_amd64.deb" - $STD xcaddy build - msg_ok "Updated xCaddy" - fi - exit + if command -v xcaddy >/dev/null 2>&1; then + setup_go + msg_info "Updating xCaddy" + cd /opt + RELEASE=$(curl -fsSL https://api.github.com/repos/caddyserver/xcaddy/releases/latest | grep "tag_name" | awk -F '"' '{print $4}') + VERSION="${RELEASE#v}" + curl -fsSL "https://github.com/caddyserver/xcaddy/releases/download/${RELEASE}/xcaddy_${VERSION}_linux_amd64.deb" -o "xcaddy_${VERSION}_linux_amd64.deb" + $STD dpkg -i "xcaddy_${VERSION}_linux_amd64.deb" + rm -f "xcaddy_${VERSION}_linux_amd64.deb" + $STD xcaddy build + msg_ok "Updated xCaddy" + msg_ok "Updated successfully!" + fi + exit } start diff --git a/ct/calibre-web.sh b/ct/calibre-web.sh index d45f03bb6..478bce715 100644 --- a/ct/calibre-web.sh +++ b/ct/calibre-web.sh @@ -104,7 +104,7 @@ function update_script() { ;; *) echo "Unsupported item $CHOICE!" >&2 - exit 1 + exit ;; esac done @@ -124,7 +124,7 @@ function update_script() { msg_info "Starting Service" systemctl start cps msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" exit } diff --git a/ct/casaos.sh b/ct/casaos.sh index 5f7813075..34dad84f4 100644 --- a/ct/casaos.sh +++ b/ct/casaos.sh @@ -20,18 +20,19 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources - if [[ ! -d /var ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - msg_info "Updating ${APP} LXC" - $STD apt-get update - $STD apt-get -y upgrade - msg_ok "Updated ${APP} LXC" - exit + header_info + check_container_storage + check_container_resources + if [[ ! -d /var ]]; then + msg_error "No ${APP} Installation Found!" + exit + fi + msg_info "Updating ${APP} LXC" + $STD apt-get update + $STD apt-get -y upgrade + msg_ok "Updated ${APP} LXC" + msg_ok "Updated successfully!" + exit } start @@ -41,4 +42,4 @@ 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}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}" diff --git a/ct/changedetection.sh b/ct/changedetection.sh index 3fcc1665a..a573d6a02 100644 --- a/ct/changedetection.sh +++ b/ct/changedetection.sh @@ -68,7 +68,7 @@ function update_script() { fi systemctl restart changedetection - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" exit } diff --git a/ct/checkmk.sh b/ct/checkmk.sh index a9fe1b431..a8ce01044 100644 --- a/ct/checkmk.sh +++ b/ct/checkmk.sh @@ -27,7 +27,7 @@ function update_script() { msg_error "No ${APP} Installation Found!" exit fi - + RELEASE=$(curl -fsSL https://api.github.com/repos/checkmk/checkmk/tags | grep "name" | awk '{print substr($2, 3, length($2)-4) }' | tr ' ' '\n' | grep -Ev 'rc|b' | sort -V | tail -n 1) msg_info "Updating ${APP} to v${RELEASE}" $STD omd stop monitoring @@ -40,8 +40,8 @@ function update_script() { $STD omd cleanup rm -rf /opt/checkmk.deb msg_ok "Updated ${APP}" - msg_ok "Updated Successfully" - + msg_ok "Updated successfully!" + exit } diff --git a/ct/cleanuparr.sh b/ct/cleanuparr.sh index dbde789b0..273169c57 100755 --- a/ct/cleanuparr.sh +++ b/ct/cleanuparr.sh @@ -37,7 +37,7 @@ function update_script() { msg_info "Starting Service" systemctl start cleanuparr msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/cloudflared.sh b/ct/cloudflared.sh index 90c1842f4..ae411c389 100644 --- a/ct/cloudflared.sh +++ b/ct/cloudflared.sh @@ -31,6 +31,7 @@ function update_script() { $STD apt update $STD apt -y upgrade msg_ok "Updated $APP LXC" + msg_ok "Updated successfully!" exit } diff --git a/ct/cloudreve.sh b/ct/cloudreve.sh index c8e76287f..3cfec6915 100644 --- a/ct/cloudreve.sh +++ b/ct/cloudreve.sh @@ -29,16 +29,16 @@ function update_script() { exit fi if check_for_gh_release "cloudreve" "cloudreve/cloudreve"; then - msg_info "Stopping $APP" + msg_info "Stopping Service" systemctl stop cloudreve - msg_ok "Stopped $APP" + msg_info "Stopped Service" fetch_and_deploy_gh_release "cloudreve" "cloudreve/cloudreve" "prebuild" "latest" "/opt/cloudreve" "*linux_amd64.tar.gz" - msg_info "Starting $APP" + msg_info "Starting Service" systemctl start cloudreve - msg_ok "Started $APP" - msg_ok "Updated Successfully" + msg_ok "Started Service" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/cockpit.sh b/ct/cockpit.sh index 2ff32f7f1..c64492ec7 100644 --- a/ct/cockpit.sh +++ b/ct/cockpit.sh @@ -27,11 +27,12 @@ function update_script() { msg_error "No ${APP} Installation Found!" exit fi - + msg_info "Updating ${APP} LXC" $STD apt update $STD apt -y upgrade msg_ok "Updated ${APP} LXC" + msg_ok "Updated successfully!" exit } diff --git a/ct/comfyui.sh b/ct/comfyui.sh new file mode 100644 index 000000000..45f1b9288 --- /dev/null +++ b/ct/comfyui.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +# Copyright (c) 2021-2025 community-scripts ORG +# Author: jdacode +# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE +# Source: https://github.com/comfyanonymous/ComfyUI + +APP="ComfyUI" +var_tags="${var_tags:-ai}" +var_cpu="${var_cpu:-4}" +var_ram="${var_ram:-8192}" +var_disk="${var_disk:-25}" +var_os="${var_os:-debian}" +var_version="${var_version:-13}" +var_unprivileged="${var_unprivileged:-1}" + +header_info "$APP" +variables +color +catch_errors + +function update_script() { + header_info + check_container_storage + check_container_resources + + if [[ ! -f /opt/${APP} ]]; then + msg_error "No ${APP} Installation Found!" + exit + fi + msg_error "To update use the ${APP} Manager." + 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}:8188${CL}" diff --git a/ct/commafeed.sh b/ct/commafeed.sh index 79cab1b54..c9a1657e7 100644 --- a/ct/commafeed.sh +++ b/ct/commafeed.sh @@ -57,7 +57,7 @@ function update_script() { msg_info "Starting Service" systemctl start commafeed msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/configarr.sh b/ct/configarr.sh index 3368d5118..b0aaab259 100644 --- a/ct/configarr.sh +++ b/ct/configarr.sh @@ -41,7 +41,7 @@ function update_script() { msg_info "Starting Service" systemctl start configarr-task.timer msg_ok "Started Service" - msg_ok "Updated Successfully!" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/convertx.sh b/ct/convertx.sh index 1bfbae645..d1702e01e 100644 --- a/ct/convertx.sh +++ b/ct/convertx.sh @@ -28,9 +28,9 @@ function update_script() { exit fi if check_for_gh_release "ConvertX" "C4illin/ConvertX"; then - msg_info "Stopping $APP" + msg_info "Stopping Service" systemctl stop convertx - msg_ok "Stopped $APP" + msg_info "Stopped Service" msg_info "Move data-Folder" if [[ -d /opt/convertx/data ]]; then @@ -48,10 +48,10 @@ function update_script() { $STD bun install msg_ok "Updated $APP" - msg_info "Starting $APP" + msg_info "Starting Service" systemctl start convertx - msg_ok "Started $APP" - msg_ok "Updated Successfully" + msg_ok "Started Service" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/cosmos.sh b/ct/cosmos.sh index a25b64164..3b08ff7f8 100644 --- a/ct/cosmos.sh +++ b/ct/cosmos.sh @@ -28,6 +28,7 @@ function update_script() { exit fi msg_ok "${APP} updates itself automatically!" + exit } start @@ -37,4 +38,4 @@ 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}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}" diff --git a/ct/crafty-controller.sh b/ct/crafty-controller.sh index ca026a6f1..d393a32a8 100644 --- a/ct/crafty-controller.sh +++ b/ct/crafty-controller.sh @@ -67,7 +67,7 @@ function update_script() { systemctl start crafty-controller msg_ok "Started Crafty-Controller" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" else msg_ok "No update required. ${APP} is already at v${RELEASE}" fi diff --git a/ct/cronicle.sh b/ct/cronicle.sh index 844c22edf..ba042862a 100644 --- a/ct/cronicle.sh +++ b/ct/cronicle.sh @@ -62,7 +62,6 @@ function update_script() { sed -i "s/localhost:3012/${IP}:3012/g" /opt/cronicle/conf/config.json $STD /opt/cronicle/bin/control.sh start msg_ok "Installed Cronicle Worker" - echo -e "\n Add Masters secret key to /opt/cronicle/conf/config.json \n" exit fi diff --git a/ct/cross-seed.sh b/ct/cross-seed.sh index 0a73f0ae2..5e596ed66 100644 --- a/ct/cross-seed.sh +++ b/ct/cross-seed.sh @@ -31,7 +31,7 @@ function update_script() { msg_info "Updating ${APP} from version v${current_version} to v${latest_version}" $STD npm install -g cross-seed@latest systemctl restart cross-seed - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" else msg_ok "${APP} is already at v${current_version}" fi @@ -49,4 +49,4 @@ description msg_ok "Completed Successfully!\n" echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}" echo -e "${INFO}${YW} Access cross-seed API using the following URL:${CL}" -echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:2468${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:2468${CL}" diff --git a/ct/cryptpad.sh b/ct/cryptpad.sh index 80c741678..391b979fc 100644 --- a/ct/cryptpad.sh +++ b/ct/cryptpad.sh @@ -29,9 +29,9 @@ function update_script() { exit fi if check_for_gh_release "cryptpad" "cryptpad/cryptpad"; then - msg_info "Stopping $APP" + msg_info "Stopping Service" systemctl stop cryptpad - msg_ok "Stopped $APP" + msg_info "Stopped Service" msg_info "Backing up configuration" [ -f /opt/cryptpad/config/config.js ] && mv /opt/cryptpad/config/config.js /opt/ @@ -50,10 +50,10 @@ function update_script() { mv /opt/config.js /opt/cryptpad/config/ msg_ok "Configuration restored" - msg_info "Starting $APP" + msg_info "Starting Service" systemctl start cryptpad - msg_ok "Started $APP" - msg_ok "Updated Successfully" + msg_ok "Started Service" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/daemonsync.sh b/ct/daemonsync.sh index d5217c9cc..9e82843c0 100644 --- a/ct/daemonsync.sh +++ b/ct/daemonsync.sh @@ -20,18 +20,19 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources - if [[ ! -d /var ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - msg_info "Updating $APP LXC" - $STD apt-get update - $STD apt-get -y upgrade - msg_ok "Updated $APP LXC" + header_info + check_container_storage + check_container_resources + if [[ ! -d /var ]]; then + msg_error "No ${APP} Installation Found!" exit + fi + msg_info "Updating $APP LXC" + $STD apt-get update + $STD apt-get -y upgrade + msg_ok "Updated $APP LXC" + msg_ok "Updated successfully!" + exit } start @@ -41,4 +42,4 @@ 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}:8084${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8084${CL}" diff --git a/ct/dashy.sh b/ct/dashy.sh index da6fac44c..3c554a959 100644 --- a/ct/dashy.sh +++ b/ct/dashy.sh @@ -62,7 +62,7 @@ function update_script() { msg_info "Starting Dashy" systemctl start dashy msg_ok "Started Dashy" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/debian.sh b/ct/debian.sh index 5dde314af..c3bb3cb1b 100644 --- a/ct/debian.sh +++ b/ct/debian.sh @@ -31,6 +31,7 @@ function update_script() { $STD apt update $STD apt -y upgrade msg_ok "Updated $APP LXC" + msg_ok "Updated successfully!" exit } diff --git a/ct/deconz.sh b/ct/deconz.sh index 6ce3e4d42..f6fd38c15 100644 --- a/ct/deconz.sh +++ b/ct/deconz.sh @@ -31,6 +31,7 @@ function update_script() { $STD apt-get update $STD apt-get -y upgrade msg_ok "Updated $APP LXC" + msg_ok "Updated successfully!" exit } @@ -41,4 +42,4 @@ 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}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}" diff --git a/ct/deluge.sh b/ct/deluge.sh index 374efc777..95040817f 100644 --- a/ct/deluge.sh +++ b/ct/deluge.sh @@ -20,18 +20,19 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources - if [[ ! -f /etc/systemd/system/deluged.service ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - msg_info "Updating $APP LXC" - $STD apt-get update - pip3 install deluge[all] --upgrade - msg_ok "Updated $APP LXC" + header_info + check_container_storage + check_container_resources + if [[ ! -f /etc/systemd/system/deluged.service ]]; then + msg_error "No ${APP} Installation Found!" exit + fi + msg_info "Updating $APP LXC" + $STD apt-get update + pip3 install deluge[all] --upgrade + msg_ok "Updated $APP LXC" + msg_ok "Updated successfully!" + exit } start @@ -41,4 +42,4 @@ 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}:8112${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8112${CL}" diff --git a/ct/dispatcharr.sh b/ct/dispatcharr.sh new file mode 100644 index 000000000..14cc19a56 --- /dev/null +++ b/ct/dispatcharr.sh @@ -0,0 +1,136 @@ +#!/usr/bin/env bash +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +# Copyright (c) 2021-2025 community-scripts ORG +# Author: ekke85 | MickLesk +# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE +# Source: https://github.com/Dispatcharr/Dispatcharr + +APP="Dispatcharr" +var_tags="${var_tags:-media;arr}" +var_cpu="${var_cpu:-2}" +var_ram="${var_ram:-2048}" +var_disk="${var_disk:-8}" +var_os="${var_os:-debian}" +var_version="${var_version:-13}" +var_unprivileged="${var_unprivileged:-1}" + +header_info "$APP" +variables +color +catch_errors + +function update_script() { + header_info + check_container_storage + check_container_resources + if [[ ! -d "/opt/dispatcharr" ]]; then + msg_error "No ${APP} Installation Found!" + exit + fi + + setup_uv + NODE_VERSION="24" setup_nodejs + + if check_for_gh_release "Dispatcharr" "Dispatcharr/Dispatcharr"; then + msg_info "Stopping Services" + systemctl stop dispatcharr-celery + systemctl stop dispatcharr-celerybeat + systemctl stop dispatcharr-daphne + systemctl stop dispatcharr + msg_ok "Stopped Services" + + msg_info "Creating Backup" + BACKUP_FILE="/opt/dispatcharr_backup_$(date +%F_%H-%M-%S).tar.gz" + if [[ -f /opt/dispatcharr/.env ]]; then + cp /opt/dispatcharr/.env /tmp/dispatcharr.env.backup + fi + if [[ -f /opt/dispatcharr/start-gunicorn.sh ]]; then + cp /opt/dispatcharr/start-gunicorn.sh /tmp/start-gunicorn.sh.backup + fi + if [[ -f /opt/dispatcharr/start-celery.sh ]]; then + cp /opt/dispatcharr/start-celery.sh /tmp/start-celery.sh.backup + fi + if [[ -f /opt/dispatcharr/start-celerybeat.sh ]]; then + cp /opt/dispatcharr/start-celerybeat.sh /tmp/start-celerybeat.sh.backup + fi + if [[ -f /opt/dispatcharr/start-daphne.sh ]]; then + cp /opt/dispatcharr/start-daphne.sh /tmp/start-daphne.sh.backup + fi + if [[ -f /opt/dispatcharr/.env ]]; then + set -o allexport + source /opt/dispatcharr/.env + set +o allexport + if [[ -n "$POSTGRES_DB" ]] && [[ -n "$POSTGRES_USER" ]] && [[ -n "$POSTGRES_PASSWORD" ]]; then + PGPASSWORD=$POSTGRES_PASSWORD pg_dump -U $POSTGRES_USER -h ${POSTGRES_HOST:-localhost} $POSTGRES_DB >/tmp/dispatcharr_db_$(date +%F).sql + msg_info "Database backup created" + fi + fi + $STD tar -czf "$BACKUP_FILE" -C /opt dispatcharr /tmp/dispatcharr_db_*.sql + msg_ok "Backup created: $BACKUP_FILE" + + CLEAN_INSTALL=1 fetch_and_deploy_gh_release "dispatcharr" "Dispatcharr/Dispatcharr" + + msg_info "Updating Dispatcharr Backend" + if [[ -f /tmp/dispatcharr.env.backup ]]; then + mv /tmp/dispatcharr.env.backup /opt/dispatcharr/.env + fi + if [[ -f /tmp/start-gunicorn.sh.backup ]]; then + mv /tmp/start-gunicorn.sh.backup /opt/dispatcharr/start-gunicorn.sh + fi + if [[ -f /tmp/start-celery.sh.backup ]]; then + mv /tmp/start-celery.sh.backup /opt/dispatcharr/start-celery.sh + fi + if [[ -f /tmp/start-celerybeat.sh.backup ]]; then + mv /tmp/start-celerybeat.sh.backup /opt/dispatcharr/start-celerybeat.sh + fi + if [[ -f /tmp/start-daphne.sh.backup ]]; then + mv /tmp/start-daphne.sh.backup /opt/dispatcharr/start-daphne.sh + fi + + cd /opt/dispatcharr + rm -rf .venv + $STD uv venv + $STD uv pip install -r requirements.txt --index-strategy unsafe-best-match + $STD uv pip install gunicorn gevent celery redis daphne + msg_ok "Updated Dispatcharr Backend" + + msg_info "Building Frontend" + cd /opt/dispatcharr/frontend + $STD npm install --legacy-peer-deps + $STD npm run build + msg_ok "Built Frontend" + + msg_info "Running Django Migrations" + cd /opt/dispatcharr + if [[ -f .env ]]; then + set -o allexport + source .env + set +o allexport + fi + $STD uv run python manage.py migrate --noinput + $STD uv run python manage.py collectstatic --noinput + msg_ok "Migrations Complete" + + msg_info "Starting Services" + systemctl start dispatcharr + systemctl start dispatcharr-celery + systemctl start dispatcharr-celerybeat + systemctl start dispatcharr-daphne + msg_ok "Started Services" + + msg_info "Cleaning up" + rm -f /tmp/dispatcharr_db_*.sql + msg_ok "Cleanup completed" + msg_ok "Updated successfully!" + fi + exit +} + +start +build_container +description + +msg_ok "Completed Successfully!\n" +echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}" +echo -e "${INFO}${YW} Access it using the following URL:${CL}" +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}" diff --git a/ct/docker.sh b/ct/docker.sh index 99d1b3472..7a74fd8ed 100644 --- a/ct/docker.sh +++ b/ct/docker.sh @@ -81,6 +81,7 @@ function update_script() { $STD apt-get -y autoremove $STD apt-get -y autoclean msg_ok "Cleanup complete" + msg_ok "Updated successfully!" exit } diff --git a/ct/dockge.sh b/ct/dockge.sh index 02a3a3c14..d3e82a476 100644 --- a/ct/dockge.sh +++ b/ct/dockge.sh @@ -20,19 +20,20 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources - if [[ ! -d /opt/dockge ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - msg_info "Updating ${APP}" - cd /opt/dockge - docker compose pull - docker compose up -d - msg_ok "Updated ${APP}" + header_info + check_container_storage + check_container_resources + if [[ ! -d /opt/dockge ]]; then + msg_error "No ${APP} Installation Found!" exit + fi + msg_info "Updating ${APP}" + cd /opt/dockge + $STD docker compose pull + $STD docker compose up -d + msg_ok "Updated ${APP}" + msg_ok "Updated successfully!" + exit } start @@ -42,4 +43,4 @@ 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}:5001${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:5001${CL}" diff --git a/ct/docmost.sh b/ct/docmost.sh index d1d45462a..ea445bd57 100644 --- a/ct/docmost.sh +++ b/ct/docmost.sh @@ -55,7 +55,7 @@ function update_script() { msg_info "Starting Service" systemctl start docmost msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/documenso.sh b/ct/documenso.sh index 4742d6622..bd0eec6f8 100644 --- a/ct/documenso.sh +++ b/ct/documenso.sh @@ -60,7 +60,7 @@ function update_script() { msg_info "Cleaning Up" rm -rf /opt/v${RELEASE}.zip msg_ok "Cleaned" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" else msg_ok "No update required. ${APP} is already at ${RELEASE}" fi diff --git a/ct/donetick.sh b/ct/donetick.sh new file mode 100644 index 000000000..3582890d9 --- /dev/null +++ b/ct/donetick.sh @@ -0,0 +1,63 @@ +#!/usr/bin/env bash +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +# Copyright (c) 2021-2025 community-scripts ORG +# Author: fstof +# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE +# Source: https://github.com/donetick/donetick + +APP="Donetick" +var_tags="${var_tags:-productivity;tasks}" +var_cpu="${var_cpu:-1}" +var_ram="${var_ram:-512}" +var_disk="${var_disk:-2}" +var_os="${var_os:-debian}" +var_version="${var_version:-13}" +var_unprivileged="${var_unprivileged:-1}" + +header_info "$APP" +variables +color +catch_errors + +function update_script() { + header_info + check_container_storage + check_container_resources + + if [[ ! -d /opt/donetick ]]; then + msg_error "No ${APP} Installation Found!" + exit + fi + + if check_for_gh_release "donetick" "donetick/donetick"; then + msg_info "Stopping Service" + systemctl stop donetick + msg_ok "Stopped Service" + + msg_info "Backing Up Configurations" + mv /opt/donetick/config/selfhosted.yml /opt/donetick/donetick.db /opt + msg_ok "Backed Up Configurations" + + CLEAN_INSTALL=1 fetch_and_deploy_gh_release "donetick" "donetick/donetick" "prebuild" "latest" "/opt/donetick" "donetick_Linux_x86_64.tar.gz" + + msg_info "Restoring Configurations" + mv /opt/selfhosted.yml /opt/donetick/config + mv /opt/donetick.db /opt/donetick + msg_ok "Restored Configurations" + + msg_info "Starting Service" + systemctl start donetick + msg_ok "Started Service" + msg_ok "Updated successfully!" + fi + exit +} + +start +build_container +description + +msg_ok "Completed Successfully!\n" +echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}" +echo -e "${INFO}${YW} Access it using the following URL:${CL}" +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:2021${CL}" diff --git a/ct/dotnetaspwebapi.sh b/ct/dotnetaspwebapi.sh index a25b1bba5..94bdef91e 100644 --- a/ct/dotnetaspwebapi.sh +++ b/ct/dotnetaspwebapi.sh @@ -30,7 +30,7 @@ function update_script() { msg_info "Updating ${APP} LXC" $STD apt-get update $STD apt-get -y upgrade - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" exit } @@ -41,4 +41,4 @@ 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 IP:${CL}" -echo -e "${TAB}${GATEWAY}${BGN}${IP}:80${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}${IP}:80${CL}" diff --git a/ct/duplicati.sh b/ct/duplicati.sh index ed0baf69a..78979c893 100644 --- a/ct/duplicati.sh +++ b/ct/duplicati.sh @@ -29,16 +29,16 @@ function update_script() { fi if check_for_gh_release "duplicati" "duplicati/duplicati"; then - msg_info "Stopping $APP" + msg_info "Stopping Service" systemctl stop duplicati - msg_ok "Stopped $APP" + msg_info "Stopped Service" fetch_and_deploy_gh_release "duplicati" "duplicati/duplicati" "binary" "latest" "/opt/duplicati" "duplicati-*-linux-x64-gui.deb" - msg_info "Starting $APP" + msg_info "Starting Service" systemctl start duplicati - msg_ok "Started $APP" - msg_ok "Update Successful" + msg_ok "Started Service" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/elementsynapse.sh b/ct/elementsynapse.sh index 1a7689a80..998ab584b 100644 --- a/ct/elementsynapse.sh +++ b/ct/elementsynapse.sh @@ -61,8 +61,8 @@ function update_script() { $STD yarn global add serve $STD yarn install --ignore-engines $STD yarn build - mv ./dist ../ && \ - rm -rf * && \ + mv ./dist ../ && + rm -rf * && mv ../dist ./ if [[ -z $(grep "ExecStart=/usr/local/bin/serve" /etc/systemd/system/synapse-admin.service) ]]; then sed -i 's|^ExecStart=.*|ExecStart=/usr/local/bin/serve -s dist -l 5173|' /etc/systemd/system/synapse-admin.service @@ -71,7 +71,7 @@ function update_script() { systemctl start synapse-admin echo "${RELEASE}" >/opt/"${APP}"_version.txt rm -f "$temp_file" - msg_ok "Update Successful" + msg_ok "Updated successfully!" else msg_ok "No update required. ${APP} is already at v${RELEASE}" fi diff --git a/ct/emby.sh b/ct/emby.sh index b17a798ec..7c6dc0b98 100644 --- a/ct/emby.sh +++ b/ct/emby.sh @@ -38,7 +38,7 @@ function update_script() { msg_info "Starting Service" systemctl start emby-server msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/emqx.sh b/ct/emqx.sh index 9b0a0bd99..b274fe187 100644 --- a/ct/emqx.sh +++ b/ct/emqx.sh @@ -57,7 +57,7 @@ function update_script() { msg_info "Cleaning Up" rm -f "$DEB_FILE" msg_ok "Cleanup Completed" - msg_ok "Update Successful" + msg_ok "Updated successfully!" else msg_ok "No update required. EMQX is already at v${RELEASE}" fi diff --git a/ct/ersatztv.sh b/ct/ersatztv.sh index 7ccd2fb35..8169063ac 100644 --- a/ct/ersatztv.sh +++ b/ct/ersatztv.sh @@ -37,7 +37,7 @@ function update_script() { systemctl start ersatzTV msg_ok "Started ErsatzTV" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi if check_for_gh_release "ersatztv-ffmpeg" "ErsatzTV/ErsatzTV-ffmpeg"; then @@ -57,7 +57,7 @@ function update_script() { msg_info "Starting ErsatzTV" systemctl start ersatzTV msg_ok "Started ErsatzTV" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/esphome.sh b/ct/esphome.sh index f9d991017..ed1c44624 100644 --- a/ct/esphome.sh +++ b/ct/esphome.sh @@ -25,7 +25,7 @@ function update_script() { check_container_resources if [[ ! -f /etc/systemd/system/esphomeDashboard.service ]]; then msg_error "No ${APP} Installation Found!" - exit 1 + exit fi msg_info "Stopping Service" @@ -81,7 +81,7 @@ EOF msg_info "Starting Service" systemctl start esphomeDashboard msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" exit } diff --git a/ct/evcc.sh b/ct/evcc.sh index d38659222..3bd866bd0 100644 --- a/ct/evcc.sh +++ b/ct/evcc.sh @@ -30,7 +30,7 @@ function update_script() { msg_info "Updating evcc LXC" $STD apt update $STD apt --only-upgrade install -y evcc - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" exit } @@ -41,4 +41,4 @@ 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}:7070${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:7070${CL}" diff --git a/ct/excalidraw.sh b/ct/excalidraw.sh index 2fdc5f0cf..944f8d39d 100644 --- a/ct/excalidraw.sh +++ b/ct/excalidraw.sh @@ -29,9 +29,9 @@ function update_script() { exit fi if check_for_gh_release "excalidraw" "excalidraw/excalidraw"; then - msg_info "Stopping $APP" + msg_info "Stopping Service" systemctl stop excalidraw - msg_ok "Stopped $APP" + msg_info "Stopped Service" rm -rf /opt/excalidraw fetch_and_deploy_gh_release "excalidraw" "excalidraw/excalidraw" @@ -41,10 +41,10 @@ function update_script() { $STD yarn msg_ok "Updated $APP" - msg_info "Starting $APP" + msg_info "Starting Service" systemctl start excalidraw - msg_ok "Started $APP" - msg_ok "Updated Successfully" + msg_ok "Started Service" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/fenrus.sh b/ct/fenrus.sh index e96d9ffe8..909535343 100644 --- a/ct/fenrus.sh +++ b/ct/fenrus.sh @@ -49,6 +49,7 @@ function update_script() { echo "${gitVersionNumber}" >"/opt/${APP}_version.txt" rm -r /opt/fenrus-data-backup/ msg_ok "Updated $APP" + msg_ok "Updated successfully!" else msg_ok "No update required. ${APP} is already up to date" fi diff --git a/ct/fhem.sh b/ct/fhem.sh index f64c87e20..560288d1f 100644 --- a/ct/fhem.sh +++ b/ct/fhem.sh @@ -30,7 +30,7 @@ function update_script() { msg_info "Updating ${APP} LXC" $STD apt-get update $STD apt-get -y upgrade - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" exit } @@ -41,4 +41,4 @@ 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}:8083${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8083${CL}" diff --git a/ct/fileflows.sh b/ct/fileflows.sh index 714d93e8e..3417d5d65 100644 --- a/ct/fileflows.sh +++ b/ct/fileflows.sh @@ -35,9 +35,9 @@ function update_script() { update_available=$(curl -fsSL -X 'GET' "http://localhost:19200/api/status/update-available" -H 'accept: application/json' | jq .UpdateAvailable) if [[ "${update_available}" == "true" ]]; then - msg_info "Stopping $APP" + msg_info "Stopping Service" systemctl stop fileflows - msg_ok "Stopped $APP" + msg_info "Stopped Service" msg_info "Creating Backup" backup_filename="/opt/${APP}_backup_$(date +%F).tar.gz" @@ -50,16 +50,15 @@ function update_script() { $STD unzip -o -d /opt/fileflows "$temp_file" msg_ok "Updated $APP to latest version" - msg_info "Starting $APP" + msg_info "Starting Service" systemctl start fileflows - msg_ok "Started $APP" + msg_ok "Started Service" msg_info "Cleaning Up" rm -rf "$temp_file" rm -rf "$backup_filename" msg_ok "Cleanup Completed" - - msg_ok "Update Successful" + msg_ok "Updated successfully!" else msg_ok "No update required. ${APP} is already at latest version" fi diff --git a/ct/firefly.sh b/ct/firefly.sh index acfb29fcc..761a301e0 100644 --- a/ct/firefly.sh +++ b/ct/firefly.sh @@ -62,7 +62,7 @@ function update_script() { msg_info "Starting Apache2" systemctl start apache2 msg_ok "Started Apache2" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/flaresolverr.sh b/ct/flaresolverr.sh index bc5720f82..3b4c0d076 100644 --- a/ct/flaresolverr.sh +++ b/ct/flaresolverr.sh @@ -11,7 +11,7 @@ var_cpu="${var_cpu:-2}" var_ram="${var_ram:-2048}" var_disk="${var_disk:-4}" var_os="${var_os:-debian}" -var_version="${var_version:-12}" +var_version="${var_version:-13}" var_unprivileged="${var_unprivileged:-1}" header_info "$APP" @@ -28,17 +28,23 @@ function update_script() { msg_error "No ${APP} Installation Found!" exit fi - if check_for_gh_release "flaresolverr" "FlareSolverr/FlareSolverr" "3.3.25"; then + if [[ $(grep -E '^VERSION_ID=' /etc/os-release) == *"12"* ]]; then + msg_error "Wrong Debian version detected!" + msg_error "You must upgrade your LXC to Debian Trixie before updating." + exit + fi + if check_for_gh_release "flaresolverr" "FlareSolverr/FlareSolverr"; then msg_info "Stopping service" systemctl stop flaresolverr msg_ok "Stopped service" rm -rf /opt/flaresolverr - fetch_and_deploy_gh_release "flaresolverr" "FlareSolverr/FlareSolverr" "prebuild" "v3.3.25" "/opt/flaresolverr" "flaresolverr_linux_x64.tar.gz" + fetch_and_deploy_gh_release "flaresolverr" "FlareSolverr/FlareSolverr" "prebuild" "latest" "/opt/flaresolverr" "flaresolverr_linux_x64.tar.gz" msg_info "Starting service" systemctl start flaresolverr msg_ok "Started service" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/flowiseai.sh b/ct/flowiseai.sh index 7e93499a6..b073b6b06 100644 --- a/ct/flowiseai.sh +++ b/ct/flowiseai.sh @@ -20,19 +20,20 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources - if [[ ! -f /etc/systemd/system/flowise.service ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - msg_info "Updating ${APP}" - systemctl stop flowise - npm install -g flowise --upgrade - systemctl start flowise - msg_ok "Updated ${APP}" + header_info + check_container_storage + check_container_resources + if [[ ! -f /etc/systemd/system/flowise.service ]]; then + msg_error "No ${APP} Installation Found!" exit + fi + msg_info "Updating ${APP}" + systemctl stop flowise + npm install -g flowise --upgrade + systemctl start flowise + msg_ok "Updated ${APP}" + msg_ok "Updated successfully!" + exit } start @@ -42,4 +43,4 @@ 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}:3000${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:3000${CL}" diff --git a/ct/fluid-calendar.sh b/ct/fluid-calendar.sh index 42f4c3c83..d91e0e78b 100644 --- a/ct/fluid-calendar.sh +++ b/ct/fluid-calendar.sh @@ -29,9 +29,9 @@ function update_script() { exit fi if check_for_gh_release "fluid-calendar" "dotnetfactory/fluid-calendar"; then - msg_info "Stopping $APP" + msg_info "Stopping Service" systemctl stop fluid-calendar - msg_ok "Stopped $APP" + msg_info "Stopped Service" cp /opt/fluid-calendar/.env /opt/fluid.env rm -rf /opt/fluid-calendar @@ -47,10 +47,10 @@ function update_script() { $STD npm run build:os msg_ok "Updated $APP" - msg_info "Starting $APP" + msg_info "Starting Service" systemctl start fluid-calendar - msg_ok "Started $APP" - msg_ok "Update Successful" + msg_ok "Started Service" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/forgejo.sh b/ct/forgejo.sh index 1e28ac7df..305420e51 100644 --- a/ct/forgejo.sh +++ b/ct/forgejo.sh @@ -47,7 +47,7 @@ function update_script() { msg_info "Starting Service" systemctl start forgejo msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" exit } diff --git a/ct/freshrss.sh b/ct/freshrss.sh index 69acd16ce..0eb31e66f 100644 --- a/ct/freshrss.sh +++ b/ct/freshrss.sh @@ -20,23 +20,24 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources - if [[ ! -d /opt/freshrss ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi + header_info + check_container_storage + check_container_resources + if [[ ! -d /opt/freshrss ]]; then + msg_error "No ${APP} Installation Found!" + exit + fi - if [ ! -x /opt/freshrss/cli/sensitive-log.sh ]; then - msg_info "Fixing wrong permissions" - chmod +x /opt/freshrss/cli/sensitive-log.sh - systemctl restart apache2 - msg_ok "Fixed wrong permissions" - else - msg_error "FreshRSS should be updated via the user interface." - exit - fi + if [ ! -x /opt/freshrss/cli/sensitive-log.sh ]; then + msg_info "Fixing wrong permissions" + chmod +x /opt/freshrss/cli/sensitive-log.sh + systemctl restart apache2 + msg_ok "Fixed wrong permissions" + exit + else + msg_error "FreshRSS should be updated via the user interface." + exit + fi } start diff --git a/ct/fumadocs.sh b/ct/fumadocs.sh index fe5c57599..688624a5e 100644 --- a/ct/fumadocs.sh +++ b/ct/fumadocs.sh @@ -26,12 +26,12 @@ function update_script() { if [[ ! -d /opt/fumadocs ]]; then msg_error "No installation found in /opt/fumadocs!" - exit 1 + exit fi if [[ ! -f /opt/fumadocs/.projectname ]]; then msg_error "Project name file not found: /opt/fumadocs/.projectname!" - exit 1 + exit fi NODE_VERSION="22" NODE_MODULE="pnpm@latest" setup_nodejs @@ -41,7 +41,7 @@ function update_script() { if [[ ! -d "$PROJECT_DIR" ]]; then msg_error "Project directory does not exist: $PROJECT_DIR" - exit 1 + exit fi if ! command -v git &>/dev/null; then $STD apt-get install -y git @@ -60,8 +60,7 @@ function update_script() { msg_info "Starting service $SERVICE_NAME" systemctl start "$SERVICE_NAME" msg_ok "Started service $SERVICE_NAME" - - msg_ok "Fumadocs successfully updated" + msg_ok "Updated successfully!" exit } diff --git a/ct/garage.sh b/ct/garage.sh new file mode 100644 index 000000000..8a5391861 --- /dev/null +++ b/ct/garage.sh @@ -0,0 +1,64 @@ +#!/usr/bin/env bash +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/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://garagehq.deuxfleurs.fr/ + +APP="Garage" +var_tags="${var_tags:-object-storage}" +var_cpu="${var_cpu:-1}" +var_ram="${var_ram:-1024}" +var_disk="${var_disk:-5}" +var_os="${var_os:-debian}" +var_version="${var_version:-13}" +var_unprivileged="${var_unprivileged:-1}" + +header_info "$APP" +variables +color +catch_errors + +function update_script() { + header_info + check_container_storage + check_container_resources + if [[ ! -f /usr/local/bin/garage ]]; then + msg_error "No ${APP} Installation Found!" + exit + fi + GITEA_RELEASE=$(curl -fsSL https://api.github.com/repos/deuxfleurs-org/garage/tags | jq -r '.[0].name') + if [[ "${GITEA_RELEASE}" != "$(cat ~/.garage 2>/dev/null)" ]] || [[ ! -f ~/.garage ]]; then + msg_info "Stopping Service" + systemctl stop garage + msg_ok "Stopped Service" + + msg_info "Backing Up Data" + cp /usr/local/bin/garage /usr/local/bin/garage.old 2>/dev/null || true + cp /etc/garage.toml /etc/garage.toml.bak 2>/dev/null || true + msg_ok "Backed Up Data" + + msg_info "Updating Garage" + curl -fsSL "https://garagehq.deuxfleurs.fr/_releases/${GITEA_RELEASE}/x86_64-unknown-linux-musl/garage" -o /usr/local/bin/garage + chmod +x /usr/local/bin/garage + echo "${GITEA_RELEASE}" >~/.garage + msg_ok "Updated Garage" + + msg_info "Starting Service" + systemctl start garage + msg_ok "Started Service" + msg_ok "Updated successfully!" + else + msg_ok "No update required. Garage is already at ${GITEA_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}${CL}" diff --git a/ct/gatus.sh b/ct/gatus.sh index 31ce85cab..c253f5f34 100644 --- a/ct/gatus.sh +++ b/ct/gatus.sh @@ -29,9 +29,9 @@ function update_script() { exit fi if check_for_gh_release "gatus" "TwiN/gatus"; then - msg_info "Stopping $APP" + msg_info "Stopping Service" systemctl stop gatus - msg_ok "Stopped $APP" + msg_ok "Stopped Service" if [[ :$PATH: != *":/usr/local/bin:"* ]]; then echo 'export PATH="/usr/local/bin:$PATH"' >>~/.bashrc @@ -42,18 +42,18 @@ function update_script() { rm -rf /opt/gatus fetch_and_deploy_gh_release "gatus" "TwiN/gatus" - msg_info "Updating $APP" + msg_info "Updating Gatus" cd /opt/gatus $STD go mod tidy CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o gatus . setcap CAP_NET_RAW+ep gatus mv /opt/config.yaml config - msg_ok "Updated $APP" + msg_ok "Updated Gatus" - msg_info "Starting $APP" + msg_info "Starting Service" systemctl start gatus - msg_ok "Started $APP" - msg_ok "Update Successful" + msg_ok "Started Service" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/ghost.sh b/ct/ghost.sh index 8b37605c6..e698661fc 100644 --- a/ct/ghost.sh +++ b/ct/ghost.sh @@ -24,19 +24,16 @@ function update_script() { check_container_storage check_container_resources - if ! dpkg-query -W -f='${Status}' mariadb-server 2>/dev/null | grep -q "install ok installed"; then - setup_mysql - fi NODE_VERSION="22" setup_nodejs - msg_info "Updating ${APP} LXC" + msg_info "Updating Ghost" if command -v ghost &>/dev/null; then current_version=$(ghost version | grep 'Ghost-CLI version' | awk '{print $3}') latest_version=$(npm show ghost-cli version) if [ "$current_version" != "$latest_version" ]; then msg_info "Updating ${APP} from version v${current_version} to v${latest_version}" $STD npm install -g ghost-cli@latest - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" else msg_ok "${APP} is already at v${current_version}" fi diff --git a/ct/ghostfolio.sh b/ct/ghostfolio.sh index 9b3b0f18c..56a8445e0 100644 --- a/ct/ghostfolio.sh +++ b/ct/ghostfolio.sh @@ -20,38 +20,38 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources + header_info + check_container_storage + check_container_resources - if [[ ! -f /opt/ghostfolio/dist/apps/api/main.js ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi + if [[ ! -f /opt/ghostfolio/dist/apps/api/main.js ]]; then + msg_error "No ${APP} Installation Found!" + exit + fi - if check_for_gh_release "ghostfolio" "ghostfolio/ghostfolio"; then - msg_info "Stopping Service" - systemctl stop ghostfolio - msg_ok "Stopped Service" + if check_for_gh_release "ghostfolio" "ghostfolio/ghostfolio"; then + msg_info "Stopping Service" + systemctl stop ghostfolio + msg_ok "Stopped Service" - msg_info "Creating Backup" - tar -czf "/opt/ghostfolio_backup_$(date +%F).tar.gz" \ - -C /opt \ - --exclude="ghostfolio/node_modules" \ - --exclude="ghostfolio/dist" \ - ghostfolio - mv /opt/ghostfolio/.env /opt/env.backup - msg_ok "Backup Created" + msg_info "Creating Backup" + tar -czf "/opt/ghostfolio_backup_$(date +%F).tar.gz" \ + -C /opt \ + --exclude="ghostfolio/node_modules" \ + --exclude="ghostfolio/dist" \ + ghostfolio + mv /opt/ghostfolio/.env /opt/env.backup + msg_ok "Backup Created" - CLEAN_INSTALL=1 fetch_and_deploy_gh_release "ghostfolio" "ghostfolio/ghostfolio" "tarball" "latest" "/opt/ghostfolio" + CLEAN_INSTALL=1 fetch_and_deploy_gh_release "ghostfolio" "ghostfolio/ghostfolio" "tarball" "latest" "/opt/ghostfolio" - msg_info "Updating Ghostfolio" - mv /opt/env.backup /opt/ghostfolio/.env - cd /opt/ghostfolio - $STD npm ci - $STD npm run build:production - $STD npx prisma migrate deploy - msg_ok "Updated Ghostfolio" + msg_info "Updating Ghostfolio" + mv /opt/env.backup /opt/ghostfolio/.env + cd /opt/ghostfolio + $STD npm ci + $STD npm run build:production + $STD npx prisma migrate deploy + msg_ok "Updated Ghostfolio" msg_info "Starting Service" systemctl start ghostfolio @@ -60,9 +60,9 @@ function update_script() { msg_info "Cleaning Up" $STD npm cache clean --force msg_ok "Cleanup Completed" - msg_ok "Updated Successfully" - fi - exit + msg_ok "Updated successfully!" + fi + exit } start diff --git a/ct/gitea-mirror.sh b/ct/gitea-mirror.sh index 5722f16a7..f53406eda 100644 --- a/ct/gitea-mirror.sh +++ b/ct/gitea-mirror.sh @@ -47,10 +47,10 @@ function update_script() { fi if [[ ! -f /opt/gitea-mirror.env ]]; then - msg_info "Detected old Enviroment, updating files" - APP_SECRET=$(openssl rand -base64 32) - HOST_IP=$(hostname -I | awk '{print $1}') - cat </opt/gitea-mirror.env + msg_info "Detected old Enviroment, updating files" + APP_SECRET=$(openssl rand -base64 32) + HOST_IP=$(hostname -I | awk '{print $1}') + cat </opt/gitea-mirror.env # See here for config options: https://github.com/RayLabsHQ/gitea-mirror/blob/main/docs/ENVIRONMENT_VARIABLES.md NODE_ENV=production HOST=0.0.0.0 @@ -77,7 +77,7 @@ WantedBy=multi-user.target EOF systemctl daemon-reload msg_ok "Old Enviroment fixed" -fi + fi if check_for_gh_release "gitea-mirror" "RayLabsHQ/gitea-mirror"; then msg_info "Stopping Services" @@ -115,7 +115,7 @@ fi msg_info "Starting Service" systemctl start gitea-mirror msg_ok "Service Started" - msg_ok "Update Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/gitea.sh b/ct/gitea.sh index e7d2acbc0..695b15b61 100644 --- a/ct/gitea.sh +++ b/ct/gitea.sh @@ -40,7 +40,7 @@ function update_script() { msg_info "Starting service" systemctl start gitea msg_ok "Started service" - msg_ok "Update Successful" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/glance.sh b/ct/glance.sh index 8f2f582bb..340e7dfd7 100644 --- a/ct/glance.sh +++ b/ct/glance.sh @@ -39,7 +39,7 @@ function update_script() { msg_info "Starting Service" systemctl start glance msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/globaleaks.sh b/ct/globaleaks.sh index 9e37447b8..c8602b9fb 100644 --- a/ct/globaleaks.sh +++ b/ct/globaleaks.sh @@ -31,6 +31,7 @@ function update_script() { $STD apt update $STD apt -y upgrade msg_ok "Updated $APP LXC" + msg_ok "Updated successfully!" } start diff --git a/ct/go2rtc.sh b/ct/go2rtc.sh index fbc9b2606..73b14f7fb 100644 --- a/ct/go2rtc.sh +++ b/ct/go2rtc.sh @@ -38,7 +38,7 @@ function update_script() { msg_info "Starting service" systemctl start go2rtc msg_ok "Started service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/goaway.sh b/ct/goaway.sh index 26df280c2..f650b63ea 100644 --- a/ct/goaway.sh +++ b/ct/goaway.sh @@ -39,7 +39,7 @@ function update_script() { systemctl start goaway msg_ok "Started Services" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/gokapi.sh b/ct/gokapi.sh index 63fd95632..576688a3d 100644 --- a/ct/gokapi.sh +++ b/ct/gokapi.sh @@ -37,7 +37,7 @@ function update_script() { msg_info "Starting Service" systemctl start gokapi msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/gotify.sh b/ct/gotify.sh index 97a8379a3..7ecf4fb12 100644 --- a/ct/gotify.sh +++ b/ct/gotify.sh @@ -38,7 +38,7 @@ function update_script() { msg_info "Starting Service" systemctl start gotify msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/grafana.sh b/ct/grafana.sh index d8bf30318..dc1eb14db 100644 --- a/ct/grafana.sh +++ b/ct/grafana.sh @@ -27,11 +27,11 @@ function update_script() { msg_error "No ${APP} Installation Found!" exit fi - + msg_info "Updating ${APP}" $STD apt-get update $STD apt-get -y upgrade - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" exit } diff --git a/ct/graylog.sh b/ct/graylog.sh index 0f12f6429..1ed618e8f 100644 --- a/ct/graylog.sh +++ b/ct/graylog.sh @@ -20,31 +20,30 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources + header_info + check_container_storage + check_container_resources - if [[ ! -d /etc/graylog ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - msg_info "Stopping $APP" - systemctl stop graylog-datanode - systemctl stop graylog-server - msg_ok "Stopped $APP" - - msg_info "Updating $APP" - $STD apt-get update - $STD apt-get upgrade -y - msg_ok "Updated $APP" - - msg_info "Starting $APP" - systemctl start graylog-datanode - systemctl start graylog-server - msg_ok "Started $APP" - - msg_ok "Update Successful" + if [[ ! -d /etc/graylog ]]; then + msg_error "No ${APP} Installation Found!" exit + fi + msg_info "Stopping Service" + systemctl stop graylog-datanode + systemctl stop graylog-server + msg_info "Stopped Service" + + msg_info "Updating $APP" + $STD apt-get update + $STD apt-get upgrade -y + msg_ok "Updated $APP" + + msg_info "Starting Service" + systemctl start graylog-datanode + systemctl start graylog-server + msg_ok "Started Service" + msg_ok "Updated successfully!" + exit } start diff --git a/ct/grist.sh b/ct/grist.sh index 5c6ce8157..dc8f28639 100644 --- a/ct/grist.sh +++ b/ct/grist.sh @@ -36,13 +36,13 @@ function update_script() { msg_info "Creating backup" rm -rf /opt/grist_bak - mv grist grist_bak + mv /opt/grist /opt/grist_bak msg_ok "Backup created" fetch_and_deploy_gh_release "grist" "gristlabs/grist-core" "tarball" msg_info "Updating ${APP}" - mkdir -p grist/docs + mkdir -p /opt/grist/docs cp -n /opt/grist_bak/.env /opt/grist/.env cp -r /opt/grist_bak/docs/* /opt/grist/docs/ cp /opt/grist_bak/grist-sessions.db /opt/grist/grist-sessions.db @@ -56,7 +56,7 @@ function update_script() { systemctl start grist msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/grocy.sh b/ct/grocy.sh index 397693390..19294229d 100644 --- a/ct/grocy.sh +++ b/ct/grocy.sh @@ -34,7 +34,7 @@ function update_script() { if check_for_gh_release "grocy" "grocy/grocy"; then msg_info "Updating ${APP}" bash /var/www/html/update.sh - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/guardian.sh b/ct/guardian.sh index 60f4a4ea3..8f3cd1ee4 100755 --- a/ct/guardian.sh +++ b/ct/guardian.sh @@ -20,54 +20,54 @@ color catch_errors function update_script() { -header_info -check_container_storage -check_container_resources + header_info + check_container_storage + check_container_resources -if [[ ! -d "/opt/guardian" ]] ; then - msg_error "No ${APP} Installation Found!" + if [[ ! -d "/opt/guardian" ]]; then + msg_error "No ${APP} Installation Found!" + exit + fi + + if check_for_gh_release "guardian" "HydroshieldMKII/Guardian"; then + msg_info "Stopping Services" + systemctl stop guardian-backend guardian-frontend + msg_ok "Stopped Services" + + if [[ -f "/opt/guardian/backend/plex-guard.db" ]]; then + msg_info "Backing up Database" + cp "/opt/guardian/backend/plex-guard.db" "/tmp/plex-guard.db.backup" + msg_ok "Backed up Database" + fi + + [[ -f "/opt/guardian/.env" ]] && cp "/opt/guardian/.env" "/opt" + CLEAN_INSTALL=1 fetch_and_deploy_gh_release "guardian" "HydroshieldMKII/Guardian" "tarball" "latest" "/opt/guardian" + [[ -f "/opt/.env" ]] && mv "/opt/.env" "/opt/guardian" + + if [[ -f "/tmp/plex-guard.db.backup" ]]; then + msg_info "Restoring Database" + cp "/tmp/plex-guard.db.backup" "/opt/guardian/backend/plex-guard.db" + rm "/tmp/plex-guard.db.backup" + msg_ok "Restored Database" + fi + + msg_info "Updating Guardian" + cd /opt/guardian/backend + $STD npm ci + $STD npm run build + + cd /opt/guardian/frontend + $STD npm ci + export DEPLOYMENT_MODE=standalone + $STD npm run build + msg_ok "Updated Guardian" + + msg_info "Starting Services" + systemctl start guardian-backend guardian-frontend + msg_ok "Started Services" + msg_ok "Updated successfully!" + fi exit -fi - -if check_for_gh_release "guardian" "HydroshieldMKII/Guardian" ; then - msg_info "Stopping Services" - systemctl stop guardian-backend guardian-frontend - msg_ok "Stopped Services" - - if [[ -f "/opt/guardian/backend/plex-guard.db" ]] ; then - msg_info "Backing up Database" - cp "/opt/guardian/backend/plex-guard.db" "/tmp/plex-guard.db.backup" - msg_ok "Backed up Database" - fi - - [[ -f "/opt/guardian/.env" ]] && cp "/opt/guardian/.env" "/opt" - CLEAN_INSTALL=1 fetch_and_deploy_gh_release "guardian" "HydroshieldMKII/Guardian" "tarball" "latest" "/opt/guardian" - [[ -f "/opt/.env" ]] && mv "/opt/.env" "/opt/guardian" - - if [[ -f "/tmp/plex-guard.db.backup" ]] ; then - msg_info "Restoring Database" - cp "/tmp/plex-guard.db.backup" "/opt/guardian/backend/plex-guard.db" - rm "/tmp/plex-guard.db.backup" - msg_ok "Restored Database" - fi - - msg_info "Updating Guardian" - cd /opt/guardian/backend - $STD npm ci - $STD npm run build - - cd /opt/guardian/frontend - $STD npm ci - export DEPLOYMENT_MODE=standalone - $STD npm run build - msg_ok "Updated Guardian" - - msg_info "Starting Services" - systemctl start guardian-backend guardian-frontend - msg_ok "Started Services" - msg_ok "Updated Successfully" -fi -exit } start diff --git a/ct/habitica.sh b/ct/habitica.sh index 499b8a901..035470269 100644 --- a/ct/habitica.sh +++ b/ct/habitica.sh @@ -30,11 +30,11 @@ function update_script() { fi NODE_VERSION="20" NODE_MODULE="gulp-cli,mocha" setup_nodejs if check_for_gh_release "habitica" "HabitRPG/habitica"; then - msg_info "Stopping $APP" + msg_info "Stopping Service" systemctl stop habitica-mongodb systemctl stop habitica systemctl stop habitica-client - msg_ok "Stopped $APP" + msg_info "Stopped Service" msg_info "Save configuration" if [[ -f /opt/habitica/config.json ]]; then @@ -62,12 +62,12 @@ function update_script() { msg_warn "No configuration file found to restore" fi - msg_info "Starting $APP" + msg_info "Starting Service" systemctl start habitica-mongodb systemctl start habitica systemctl start habitica-client - msg_ok "Started $APP" - msg_ok "Update Successful" + msg_ok "Started Service" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/headers/alpine-garage b/ct/headers/alpine-garage new file mode 100644 index 000000000..c14c5aaa0 --- /dev/null +++ b/ct/headers/alpine-garage @@ -0,0 +1,6 @@ + ___ __ _ ______ + / | / /___ (_)___ ___ / ____/___ __________ _____ ____ + / /| | / / __ \/ / __ \/ _ \______/ / __/ __ `/ ___/ __ `/ __ `/ _ \ + / ___ |/ / /_/ / / / / / __/_____/ /_/ / /_/ / / / /_/ / /_/ / __/ +/_/ |_/_/ .___/_/_/ /_/\___/ \____/\__,_/_/ \__,_/\__, /\___/ + /_/ /____/ diff --git a/ct/headers/bentopdf b/ct/headers/bentopdf new file mode 100644 index 000000000..692eff64b --- /dev/null +++ b/ct/headers/bentopdf @@ -0,0 +1,6 @@ + ____ __ ____ ____ ______ + / __ )___ ____ / /_____ / __ \/ __ \/ ____/ + / __ / _ \/ __ \/ __/ __ \/ /_/ / / / / /_ + / /_/ / __/ / / / /_/ /_/ / ____/ /_/ / __/ +/_____/\___/_/ /_/\__/\____/_/ /_____/_/ + diff --git a/ct/headers/comfyui b/ct/headers/comfyui new file mode 100644 index 000000000..5f3bfd60a --- /dev/null +++ b/ct/headers/comfyui @@ -0,0 +1,6 @@ + ______ ____ __ ______ + / ____/___ ____ ___ / __/_ __/ / / / _/ + / / / __ \/ __ `__ \/ /_/ / / / / / // / +/ /___/ /_/ / / / / / / __/ /_/ / /_/ // / +\____/\____/_/ /_/ /_/_/ \__, /\____/___/ + /____/ diff --git a/ct/headers/dispatcharr b/ct/headers/dispatcharr new file mode 100644 index 000000000..a8ad53965 --- /dev/null +++ b/ct/headers/dispatcharr @@ -0,0 +1,6 @@ + ____ _ __ __ + / __ \(_)________ ____ _/ /______/ /_ ____ ___________ + / / / / / ___/ __ \/ __ `/ __/ ___/ __ \/ __ `/ ___/ ___/ + / /_/ / (__ ) /_/ / /_/ / /_/ /__/ / / / /_/ / / / / +/_____/_/____/ .___/\__,_/\__/\___/_/ /_/\__,_/_/ /_/ + /_/ diff --git a/ct/headers/donetick b/ct/headers/donetick new file mode 100644 index 000000000..c44014bb4 --- /dev/null +++ b/ct/headers/donetick @@ -0,0 +1,6 @@ + ____ __ _ __ + / __ \____ ____ ___ / /_(_)____/ /__ + / / / / __ \/ __ \/ _ \/ __/ / ___/ //_/ + / /_/ / /_/ / / / / __/ /_/ / /__/ ,< +/_____/\____/_/ /_/\___/\__/_/\___/_/|_| + diff --git a/ct/headers/garage b/ct/headers/garage new file mode 100644 index 000000000..fb0adb2cd --- /dev/null +++ b/ct/headers/garage @@ -0,0 +1,6 @@ + ______ + / ____/___ __________ _____ ____ + / / __/ __ `/ ___/ __ `/ __ `/ _ \ +/ /_/ / /_/ / / / /_/ / /_/ / __/ +\____/\__,_/_/ \__,_/\__, /\___/ + /____/ diff --git a/ct/headers/livebook b/ct/headers/livebook new file mode 100644 index 000000000..6ff6b47ef --- /dev/null +++ b/ct/headers/livebook @@ -0,0 +1,6 @@ + __ _ __ __ + / / (_) _____ / /_ ____ ____ / /__ + / / / / | / / _ \/ __ \/ __ \/ __ \/ //_/ + / /___/ /| |/ / __/ /_/ / /_/ / /_/ / ,< +/_____/_/ |___/\___/_.___/\____/\____/_/|_| + diff --git a/ct/headers/metube b/ct/headers/metube deleted file mode 100644 index af025d740..000000000 --- a/ct/headers/metube +++ /dev/null @@ -1,6 +0,0 @@ - __ ___ ______ __ - / |/ /__/_ __/_ __/ /_ ___ - / /|_/ / _ \/ / / / / / __ \/ _ \ - / / / / __/ / / /_/ / /_/ / __/ -/_/ /_/\___/_/ \__,_/_.___/\___/ - diff --git a/ct/headers/pangolin b/ct/headers/pangolin new file mode 100644 index 000000000..0a2d42304 --- /dev/null +++ b/ct/headers/pangolin @@ -0,0 +1,6 @@ + ____ ___ + / __ \____ _____ ____ _____ / (_)___ + / /_/ / __ `/ __ \/ __ `/ __ \/ / / __ \ + / ____/ /_/ / / / / /_/ / /_/ / / / / / / +/_/ \__,_/_/ /_/\__, /\____/_/_/_/ /_/ + /____/ diff --git a/ct/headers/patchmon b/ct/headers/patchmon new file mode 100644 index 000000000..87d928deb --- /dev/null +++ b/ct/headers/patchmon @@ -0,0 +1,6 @@ + ____ __ __ __ ___ + / __ \____ _/ /______/ /_ / |/ /___ ____ + / /_/ / __ `/ __/ ___/ __ \/ /|_/ / __ \/ __ \ + / ____/ /_/ / /_/ /__/ / / / / / / /_/ / / / / +/_/ \__,_/\__/\___/_/ /_/_/ /_/\____/_/ /_/ + diff --git a/ct/headers/reitti b/ct/headers/reitti new file mode 100644 index 000000000..8e7627609 --- /dev/null +++ b/ct/headers/reitti @@ -0,0 +1,6 @@ + ____ _ __ __ _ + / __ \___ (_) /_/ /_(_) + / /_/ / _ \/ / __/ __/ / + / _, _/ __/ / /_/ /_/ / +/_/ |_|\___/_/\__/\__/_/ + diff --git a/ct/headscale.sh b/ct/headscale.sh index a58a9bff4..dbacfd6fa 100644 --- a/ct/headscale.sh +++ b/ct/headscale.sh @@ -42,7 +42,7 @@ function update_script() { msg_info "Starting Service" systemctl enable -q --now headscale msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/healthchecks.sh b/ct/healthchecks.sh index 373cc6eae..30e67654d 100644 --- a/ct/healthchecks.sh +++ b/ct/healthchecks.sh @@ -29,14 +29,14 @@ function update_script() { exit fi if check_for_gh_release "healthchecks" "healthchecks/healthchecks"; then - msg_info "Stopping $APP" + msg_info "Stopping Services" systemctl stop healthchecks - msg_ok "Stopped $APP" + msg_ok "Stopped Services" setup_uv fetch_and_deploy_gh_release "healthchecks" "healthchecks/healthchecks" - msg_info "Updating $APP" + msg_info "Updating healthchecks" cd /opt/healthchecks mkdir -p /opt/healthchecks/static-collected/ $STD uv pip install wheel gunicorn -r requirements.txt --system @@ -44,13 +44,13 @@ function update_script() { $STD uv run -- python manage.py migrate --noinput $STD uv run -- python manage.py collectstatic --noinput $STD uv run -- python manage.py compress - msg_ok "Updated $APP" + msg_ok "Updated healthchecks" - msg_info "Starting $APP" + msg_info "Starting Services" systemctl start healthchecks systemctl restart caddy - msg_ok "Started $APP" - msg_ok "Update Successful" + msg_ok "Started Services" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/heimdall-dashboard.sh b/ct/heimdall-dashboard.sh index 4cbd8f1f1..774152b16 100644 --- a/ct/heimdall-dashboard.sh +++ b/ct/heimdall-dashboard.sh @@ -63,7 +63,7 @@ function update_script() { systemctl start heimdall.service sleep 2 msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" else msg_ok "No update required. ${APP} is already at ${RELEASE}." fi diff --git a/ct/hev-socks5-server.sh b/ct/hev-socks5-server.sh index c81412535..3cf996333 100644 --- a/ct/hev-socks5-server.sh +++ b/ct/hev-socks5-server.sh @@ -20,37 +20,37 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources + header_info + check_container_storage + check_container_resources - if [[ ! -f /opt/${APP} ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - - RELEASE=$(curl -fsSL https://api.github.com/repos/heiher/${APP}/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }') - if [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]] || [[ ! -f /opt/${APP}_version.txt ]]; then - msg_info "Stopping $APP" - systemctl stop $APP - msg_ok "Stopped $APP" - - msg_info "Updating $APP to v${RELEASE}" - curl -L -o "${APP}" "https://github.com/heiher/${APP}/releases/download/${RELEASE}/hev-socks5-server-linux-x86_64" - mv ${APP} /opt/${APP} - chmod +x /opt/${APP} - msg_ok "Updated $APP to v${RELEASE}" - - msg_info "Starting $APP" - systemctl start $APP - msg_ok "Started $APP" - - echo "${RELEASE}" >/opt/${APP}_version.txt - msg_ok "Update Successful" - else - msg_ok "No update required. ${APP} is already at v${RELEASE}" - fi + if [[ ! -f /opt/${APP} ]]; then + msg_error "No ${APP} Installation Found!" exit + fi + + RELEASE=$(curl -fsSL https://api.github.com/repos/heiher/${APP}/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }') + if [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]] || [[ ! -f /opt/${APP}_version.txt ]]; then + msg_info "Stopping Service" + systemctl stop hev-socks5-server + msg_ok "Stopped Service" + + msg_info "Updating $APP to v${RELEASE}" + curl -L -o "${APP}" "https://github.com/heiher/${APP}/releases/download/${RELEASE}/hev-socks5-server-linux-x86_64" + mv ${APP} /opt/${APP} + chmod +x /opt/${APP} + msg_ok "Updated hev-socks5-server to v${RELEASE}" + + msg_info "Starting Service" + systemctl start hev-socks5-server + msg_ok "Started Service" + + echo "${RELEASE}" >/opt/${APP}_version.txt + msg_ok "Updated successfully!" + else + msg_ok "No update required. ${APP} is already at v${RELEASE}" + fi + exit } start diff --git a/ct/homarr.sh b/ct/homarr.sh index 55b5b1583..6a19924c1 100644 --- a/ct/homarr.sh +++ b/ct/homarr.sh @@ -33,7 +33,7 @@ function update_script() { msg_error "Update not supported. Refer to:" msg_error " - https://github.com/community-scripts/ProxmoxVE/discussions/1551" msg_error " - https://homarr.dev/docs/getting-started/after-the-installation/#importing-a-zip-from-version-before-100" - exit 1 + exit fi if [[ ! -f /opt/run_homarr.sh ]]; then msg_info "Detected outdated and missing service files" @@ -156,7 +156,7 @@ EOF msg_info "Starting Services" systemctl start homarr msg_ok "Started Services" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" read -p "${TAB3}It's recommended to reboot the LXC after an update, would you like to reboot the LXC now ? (y/n): " choice if [[ "$choice" =~ ^[Yy]$ ]]; then reboot diff --git a/ct/homebox.sh b/ct/homebox.sh index 2ef3597a3..f09276712 100644 --- a/ct/homebox.sh +++ b/ct/homebox.sh @@ -49,7 +49,7 @@ function update_script() { msg_info "Starting Service" systemctl start homebox msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/homebridge.sh b/ct/homebridge.sh index b6019c408..1a01cc4c0 100644 --- a/ct/homebridge.sh +++ b/ct/homebridge.sh @@ -30,7 +30,7 @@ function update_script() { msg_info "Updating ${APP} LXC" $STD apt-get update $STD apt-get install -y homebridge - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" exit } @@ -41,4 +41,4 @@ 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}:8581${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8581${CL}" diff --git a/ct/homepage.sh b/ct/homepage.sh index 504cce7cc..19a49726d 100644 --- a/ct/homepage.sh +++ b/ct/homepage.sh @@ -29,8 +29,6 @@ function update_script() { fi NODE_VERSION="22" NODE_MODULE="pnpm@latest" setup_nodejs - - # ensure that jq is installed if ! command -v jq &>/dev/null; then $STD msg_info "Installing jq..." $STD apt-get update -qq &>/dev/null @@ -62,7 +60,7 @@ function update_script() { fi systemctl start homepage echo "${RELEASE}" >/opt/${APP}_version.txt - msg_ok "Updated Homepage to v${RELEASE}" + msg_ok "Updated successfully!" else msg_ok "No update required. ${APP} is already at v${RELEASE}" fi diff --git a/ct/homer.sh b/ct/homer.sh index 8cc9df667..9caeb773d 100644 --- a/ct/homer.sh +++ b/ct/homer.sh @@ -56,7 +56,7 @@ function update_script() { msg_info "Starting Service" systemctl start homer msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" exit } diff --git a/ct/hortusfox.sh b/ct/hortusfox.sh index 448d3e9d5..69a888a2e 100644 --- a/ct/hortusfox.sh +++ b/ct/hortusfox.sh @@ -56,7 +56,7 @@ function update_script() { msg_info "Cleaning up" rm -r /opt/hortusfox-backup msg_ok "Cleaned" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/huntarr.sh b/ct/huntarr.sh index cad58861f..06e9248a0 100644 --- a/ct/huntarr.sh +++ b/ct/huntarr.sh @@ -32,21 +32,21 @@ function update_script() { setup_uv if check_for_gh_release "huntarr" "plexguide/Huntarr.io"; then - msg_info "Stopping huntarr" + msg_info "Stopping Service" systemctl stop huntarr - msg_ok "Stopped huntarr" + msg_ok "Stopped Service" fetch_and_deploy_gh_release "huntarr" "plexguide/Huntarr.io" - msg_info "Configuring $APP" + msg_info "Updating Huntarr" cd /opt/huntarr $STD uv pip install -r requirements.txt --python /opt/huntarr/.venv/bin/python - msg_ok "Configured $APP" + msg_ok "Updated Huntarr" - msg_info "Starting $APP" + msg_info "Starting Service" systemctl start huntarr - msg_ok "Started $APP" - msg_ok "Updated $APP" + msg_ok "Started Service" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/hyperhdr.sh b/ct/hyperhdr.sh index 98a151702..3c3af7ae5 100644 --- a/ct/hyperhdr.sh +++ b/ct/hyperhdr.sh @@ -31,6 +31,7 @@ function update_script() { $STD apt-get update $STD apt-get -y upgrade msg_ok "Updated $APP LXC" + msg_ok "Updated successfully!" exit } @@ -41,4 +42,4 @@ 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}:8090${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8090${CL}" diff --git a/ct/hyperion.sh b/ct/hyperion.sh index 3507b84cc..15c838c80 100644 --- a/ct/hyperion.sh +++ b/ct/hyperion.sh @@ -20,18 +20,18 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources - if [[ ! -f /etc/apt/sources.list.d/hyperion.list ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - msg_info "Updating ${APP} LXC" - $STD apt-get update - $STD apt-get install -y hyperion - msg_ok "Updated Successfully" - exit + header_info + check_container_storage + check_container_resources + if [[ ! -f /etc/apt/sources.list.d/hyperion.list ]]; then + msg_error "No ${APP} Installation Found!" + exit + fi + msg_info "Updating ${APP} LXC" + $STD apt-get update + $STD apt-get install -y hyperion + msg_ok "Updated successfully!" + exit } start @@ -41,4 +41,4 @@ 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}:8090${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8090${CL}" diff --git a/ct/immich.sh b/ct/immich.sh index e2fe92fff..314a2b5cc 100644 --- a/ct/immich.sh +++ b/ct/immich.sh @@ -37,7 +37,7 @@ function update_script() { setup_uv PNPM_VERSION="$(curl -fsSL "https://raw.githubusercontent.com/immich-app/immich/refs/heads/main/package.json" | jq -r '.packageManager | split("@")[1]')" - NODE_VERSION="22" NODE_MODULE="pnpm@${PNPM_VERSION}" setup_nodejs + NODE_VERSION="24" NODE_MODULE="pnpm@${PNPM_VERSION}" setup_nodejs if [[ ! -f /etc/apt/preferences.d/preferences ]]; then msg_info "Adding Debian Testing repo" @@ -93,7 +93,7 @@ EOF msg_ok "Image-processing libraries up to date" fi - RELEASE="2.1.0" + RELEASE="2.2.3" if check_for_gh_release "immich" "immich-app/immich" "${RELEASE}"; then msg_info "Stopping Services" systemctl stop immich-web @@ -113,6 +113,9 @@ EOF rm ./vchord.deb msg_ok "Upgraded VectorChord to v${VCHORD_RELEASE}" fi + if ! dpkg -l | grep -q ccache; then + $STD apt-get install -yqq ccache + fi INSTALL_DIR="/opt/${APP}" UPLOAD_DIR="$(sed -n '/^IMMICH_MEDIA_LOCATION/s/[^=]*=//p' /opt/immich/.env)" diff --git a/ct/influxdb.sh b/ct/influxdb.sh index 29039d161..205b55926 100644 --- a/ct/influxdb.sh +++ b/ct/influxdb.sh @@ -30,7 +30,7 @@ function update_script() { msg_info "Updating ${APP}" $STD apt-get update $STD apt-get -y upgrade - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" exit } @@ -41,4 +41,4 @@ 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} and Port 8888 for v1 or Port 8086 (v2)${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP} and Port 8888 for v1 or Port 8086 (v2)${CL}" diff --git a/ct/inspircd.sh b/ct/inspircd.sh index b4a016fbf..92ca27caa 100644 --- a/ct/inspircd.sh +++ b/ct/inspircd.sh @@ -37,7 +37,7 @@ function update_script() { msg_info "Starting Service" systemctl start inspircd msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/inventree.sh b/ct/inventree.sh index f66e18a40..21e479e1e 100644 --- a/ct/inventree.sh +++ b/ct/inventree.sh @@ -20,19 +20,20 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources + header_info + check_container_storage + check_container_resources - if [[ ! -d "/opt/inventree" ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - msg_info "Updating $APP" - $STD apt-get update - $STD apt-get install --only-upgrade inventree -y - msg_ok "Updated $APP" + if [[ ! -d "/opt/inventree" ]]; then + msg_error "No ${APP} Installation Found!" exit + fi + msg_info "Updating $APP" + $STD apt-get update + $STD apt-get install --only-upgrade inventree -y + msg_ok "Updated $APP" + msg_ok "Updated successfully!" + exit } start @@ -42,4 +43,4 @@ 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}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}" diff --git a/ct/jellyfin.sh b/ct/jellyfin.sh index 418242071..64c48919b 100644 --- a/ct/jellyfin.sh +++ b/ct/jellyfin.sh @@ -30,13 +30,14 @@ function update_script() { if ! grep -qEi 'ubuntu' /etc/os-release; then msg_info "Updating Intel Dependencies" + rm -f ~/.intel-* || true fetch_and_deploy_gh_release "intel-igc-core-2" "intel/intel-graphics-compiler" "binary" "latest" "" "intel-igc-core-2_*_amd64.deb" fetch_and_deploy_gh_release "intel-igc-opencl-2" "intel/intel-graphics-compiler" "binary" "latest" "" "intel-igc-opencl-2_*_amd64.deb" fetch_and_deploy_gh_release "intel-libgdgmm12" "intel/compute-runtime" "binary" "latest" "" "libigdgmm12_*_amd64.deb" fetch_and_deploy_gh_release "intel-opencl-icd" "intel/compute-runtime" "binary" "latest" "" "intel-opencl-icd_*_amd64.deb" msg_ok "Updated Intel Dependencies" fi - + msg_info "Updating Jellyfin" if ! dpkg -s libjemalloc2 >/dev/null 2>&1; then $STD apt install -y libjemalloc2 @@ -48,7 +49,7 @@ function update_script() { $STD apt -y upgrade $STD apt -y --with-new-pkgs upgrade jellyfin jellyfin-server msg_ok "Updated Jellyfin" - msg_ok "Update Successfully!" + msg_ok "Updated successfully!" exit } diff --git a/ct/jotty.sh b/ct/jotty.sh index 45f09f8ef..f1814de63 100644 --- a/ct/jotty.sh +++ b/ct/jotty.sh @@ -8,7 +8,7 @@ source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/m APP="jotty" var_tags="${var_tags:-tasks;notes}" var_cpu="${var_cpu:-2}" -var_ram="${var_ram:-3072}" +var_ram="${var_ram:-4096}" var_disk="${var_disk:-6}" var_os="${var_os:-debian}" var_version="${var_version:-13}" @@ -43,23 +43,23 @@ function update_script() { NODE_VERSION="22" NODE_MODULE="yarn" setup_nodejs CLEAN_INSTALL=1 fetch_and_deploy_gh_release "jotty" "fccview/jotty" "tarball" "latest" "/opt/jotty" - msg_info "Updating app" + msg_info "Updating jotty" cd /opt/jotty $STD yarn --frozen-lockfile $STD yarn next telemetry disable $STD yarn build - msg_ok "Updated app" + msg_ok "Updated jotty" msg_info "Restoring configuration & data" mv /opt/app.env /opt/jotty/.env $STD tar -xf /opt/data_config.tar msg_ok "Restored configuration & data" - msg_info "Restarting ${APP} service" + msg_info "Starting Service" systemctl start jotty - msg_ok "Restarted ${APP} service" + msg_ok "Started Service" rm /opt/data_config.tar - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/jupyternotebook.sh b/ct/jupyternotebook.sh index 2b6aef427..fd1e10e81 100644 --- a/ct/jupyternotebook.sh +++ b/ct/jupyternotebook.sh @@ -63,9 +63,8 @@ WantedBy=multi-user.target EOF systemctl daemon-reexec systemctl restart jupyternotebook - msg_ok "Service updated and restarted" + msg_ok "Updated successfully!" fi - exit } diff --git a/ct/kavita.sh b/ct/kavita.sh index 5011c9e56..43c3944b1 100644 --- a/ct/kavita.sh +++ b/ct/kavita.sh @@ -39,7 +39,7 @@ function update_script() { msg_info "Starting Service" systemctl start kavita msg_ok "Service Started" - msg_ok "Update Successfully!" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/keycloak.sh b/ct/keycloak.sh index 921b72060..a4907bab5 100644 --- a/ct/keycloak.sh +++ b/ct/keycloak.sh @@ -58,7 +58,7 @@ function update_script() { msg_info "Cleaning up" rm -rf keycloak.old msg_ok "Cleanup complete" - msg_ok "Update Successful" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/lazylibrarian.sh b/ct/lazylibrarian.sh index 1c7bf673d..0a540e098 100644 --- a/ct/lazylibrarian.sh +++ b/ct/lazylibrarian.sh @@ -39,7 +39,7 @@ function update_script() { systemctl start lazylibrarian msg_ok "Started LazyLibrarian" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" exit } @@ -50,4 +50,4 @@ 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}:5299${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:5299${CL}" diff --git a/ct/leantime.sh b/ct/leantime.sh index 534f7db1e..51d7a9438 100644 --- a/ct/leantime.sh +++ b/ct/leantime.sh @@ -47,7 +47,7 @@ function update_script() { msg_info "Removing Backup" rm -rf /opt/leantime_bak msg_ok "Removed Backup" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/librespeed-rust.sh b/ct/librespeed-rust.sh index 51e3f0c6b..c9170493b 100644 --- a/ct/librespeed-rust.sh +++ b/ct/librespeed-rust.sh @@ -38,7 +38,7 @@ function update_script() { msg_info "Starting Service" systemctl start librespeed_rs msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/libretranslate.sh b/ct/libretranslate.sh index 9e41024fe..6785a53e1 100644 --- a/ct/libretranslate.sh +++ b/ct/libretranslate.sh @@ -28,21 +28,24 @@ function update_script() { msg_error "No ${APP} Installation Found!" exit fi - if check_for_gh_release "libretranslate" "LibreTranslate/LibreTranslate"; then - msg_info "Stopping $APP" - systemctl stop libretranslate - msg_ok "Stopped $APP" - msg_info "Updating $APP" + setup_uv + + if check_for_gh_release "libretranslate" "LibreTranslate/LibreTranslate"; then + msg_info "Stopping Service" + systemctl stop libretranslate + msg_ok "Stopped Service" + + msg_info "Updating LibreTranslate" cd /opt/libretranslate source .venv/bin/activate $STD pip install -U libretranslate - msg_ok "Updated $APP" + msg_ok "Updated LibreTranslate" - msg_info "Starting $APP" + msg_info "Starting Service" systemctl start libretranslate - msg_ok "Started $APP" - msg_ok "Update Successful" + msg_ok "Started Service" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/lidarr.sh b/ct/lidarr.sh index e1ce84fd3..ee6a56fe6 100644 --- a/ct/lidarr.sh +++ b/ct/lidarr.sh @@ -40,7 +40,7 @@ function update_script() { msg_info "Starting service" systemctl start lidarr msg_ok "Service started" - msg_ok "Updated successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/linkwarden.sh b/ct/linkwarden.sh index 97276e586..d53138c7e 100644 --- a/ct/linkwarden.sh +++ b/ct/linkwarden.sh @@ -63,7 +63,7 @@ function update_script() { rm -rf /root/.cache/yarn rm -rf /opt/linkwarden/.next/cache msg_ok "Cleaned" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/listmonk.sh b/ct/listmonk.sh index ac2c664b1..64869e000 100644 --- a/ct/listmonk.sh +++ b/ct/listmonk.sh @@ -51,7 +51,7 @@ function update_script() { msg_info "Cleaning up" rm -rf /opt/listmonk-backup/ msg_ok "Cleaned" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/litellm.sh b/ct/litellm.sh index 9c311ee68..7c84bd893 100644 --- a/ct/litellm.sh +++ b/ct/litellm.sh @@ -47,7 +47,7 @@ function update_script() { msg_info "Starting Service" systemctl start litellm msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" exit } diff --git a/ct/livebook.sh b/ct/livebook.sh new file mode 100755 index 000000000..9ce782cc0 --- /dev/null +++ b/ct/livebook.sh @@ -0,0 +1,64 @@ +#!/usr/bin/env bash +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/refs/heads/main/misc/build.func) +# Copyright (c) 2021-2025 community-scripts ORG +# Author: dkuku +# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE +# Source: https://github.com/livebook-dev/livebook + +APP="Livebook" +var_tags="${var_tags:-development}" +var_disk="${var_disk:-4}" +var_cpu="${var_cpu:-2}" +var_ram="${var_ram:-1024}" +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 [[ ! -f /opt/livebook/.mix/escripts/livebook ]]; then + msg_error "No ${APP} Installation Found!" + exit + fi + + if check_for_gh_release "livebook" "livebook-dev/livebook"; then + msg_info "Stopping Service" + systemctl stop livebook + msg_info "Stopped Service" + + msg_info "Updating Container" + $STD apt update + $STD apt upgrade -y + msg_ok "Updated Container" + + msg_info "Updating Livebook" + source /opt/livebook/.env + cd /opt/livebook + $STD mix escript.install hex livebook --force + + chown -R livebook:livebook /opt/livebook /data + + msg_info "Starting Service" + systemctl start livebook + msg_info "Started Service" + + msg_ok "Updated successfully!" + fi + exit +} + +start +build_container +description + +echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}" +echo -e "${INFO}${YW} Access it using the following URL:${CL}" +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8080${CL}" diff --git a/ct/lldap.sh b/ct/lldap.sh index 7739ecd3a..bb5d7ce67 100644 --- a/ct/lldap.sh +++ b/ct/lldap.sh @@ -20,18 +20,19 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources - if [[ ! -f /lib/systemd/system/lldap.service ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - msg_info "Updating $APP" - apt update - apt upgrade -y lldap - msg_ok "Updated $APP" + header_info + check_container_storage + check_container_resources + if [[ ! -f /lib/systemd/system/lldap.service ]]; then + msg_error "No ${APP} Installation Found!" exit + fi + msg_info "Updating $APP" + $STD apt update + $STD apt upgrade -y lldap + msg_ok "Updated $APP" + msg_ok "Updated successfully!" + exit } start diff --git a/ct/lubelogger.sh b/ct/lubelogger.sh index ca866e3cf..d6076e0e9 100644 --- a/ct/lubelogger.sh +++ b/ct/lubelogger.sh @@ -62,7 +62,7 @@ function update_script() { msg_info "Cleaning up" rm -rf /tmp/lubeloggerData msg_ok "Cleaned" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/lyrionmusicserver.sh b/ct/lyrionmusicserver.sh index 211850464..e074bd38a 100644 --- a/ct/lyrionmusicserver.sh +++ b/ct/lyrionmusicserver.sh @@ -47,9 +47,11 @@ function update_script() { $STD apt -y autoclean $STD apt -y clean msg_ok "Cleaned" + msg_ok "Updated successfully!" else msg_ok "$APP is already up to date (${RELEASE})" fi + exit } start diff --git a/ct/mafl.sh b/ct/mafl.sh index d03c7e935..50cb5c592 100644 --- a/ct/mafl.sh +++ b/ct/mafl.sh @@ -50,7 +50,7 @@ function update_script() { msg_info "Starting Service" systemctl start mafl msg_ok "Service started" - msg_ok "Update successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/magicmirror.sh b/ct/magicmirror.sh index 7ccac374d..7490fa1d2 100644 --- a/ct/magicmirror.sh +++ b/ct/magicmirror.sh @@ -57,7 +57,7 @@ function update_script() { msg_info "Starting Service" systemctl start magicmirror msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/managemydamnlife.sh b/ct/managemydamnlife.sh index 8f76021a3..66d49d2ff 100644 --- a/ct/managemydamnlife.sh +++ b/ct/managemydamnlife.sh @@ -52,7 +52,7 @@ function update_script() { msg_info "Starting service" systemctl start mmdl msg_ok "Started service" - msg_ok "Update Successful" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/mariadb.sh b/ct/mariadb.sh index b3c927fdc..8b4fd335f 100644 --- a/ct/mariadb.sh +++ b/ct/mariadb.sh @@ -30,7 +30,7 @@ function update_script() { msg_info "Updating ${APP} LXC" $STD apt update $STD apt -y upgrade - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" exit } @@ -41,4 +41,4 @@ 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 IP:${CL}" -echo -e "${TAB}${GATEWAY}${BGN}${IP}:3306${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}${IP}:3306${CL}" diff --git a/ct/matterbridge.sh b/ct/matterbridge.sh index 132f0cb13..e64b5bf04 100644 --- a/ct/matterbridge.sh +++ b/ct/matterbridge.sh @@ -30,6 +30,7 @@ function update_script() { $STD apt update $STD apt upgrade -y NODE_VERSION="22" NODE_MODULE="matterbridge" setup_nodejs + msg_ok "Updated successfully!" exit } diff --git a/ct/mattermost.sh b/ct/mattermost.sh index f07577614..5d47bd0be 100644 --- a/ct/mattermost.sh +++ b/ct/mattermost.sh @@ -30,7 +30,7 @@ function update_script() { msg_info "Updating ${APP} LXC" $STD apt update $STD apt -y upgrade - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" exit } @@ -41,4 +41,4 @@ 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}:8065${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8065${CL}" diff --git a/ct/mealie.sh b/ct/mealie.sh index 387a1e069..43eccbf52 100644 --- a/ct/mealie.sh +++ b/ct/mealie.sh @@ -32,9 +32,9 @@ function update_script() { PYTHON_VERSION="3.12" setup_uv NODE_MODULE="yarn" NODE_VERSION="20" setup_nodejs - msg_info "Stopping $APP" + msg_info "Stopping Service" systemctl stop mealie - msg_ok "Stopped $APP" + msg_info "Stopped Service" msg_info "Backing up .env and start.sh" cp -f /opt/mealie/mealie.env /opt/mealie/mealie.env.bak @@ -73,9 +73,9 @@ function update_script() { chmod +x /opt/mealie/start.sh msg_ok "Configuration restored" - msg_info "Starting $APP" + msg_info "Starting Service" systemctl start mealie - msg_ok "Started $APP" + msg_ok "Started Service" msg_ok "Update Successful" fi exit diff --git a/ct/mediamanager.sh b/ct/mediamanager.sh index edf4e8b54..1a9b63ab9 100644 --- a/ct/mediamanager.sh +++ b/ct/mediamanager.sh @@ -42,14 +42,12 @@ function update_script() { export FRONTEND_FILES_DIR="${MM_DIR}/web/build" export BASE_PATH="" export PUBLIC_VERSION="" - export PUBLIC_API_URL="${BASE_PATH}/api/v1" - export BASE_PATH="${BASE_PATH}/web" + export PUBLIC_API_URL="" cd /opt/mediamanager/web $STD npm ci $STD npm run build rm -rf "$FRONTEND_FILES_DIR"/build cp -r build "$FRONTEND_FILES_DIR" - export BASE_PATH="" export VIRTUAL_ENV="/opt/${MM_DIR}/venv" cd /opt/mediamanager rm -rf "$MM_DIR"/{media_manager,alembic*} @@ -60,7 +58,7 @@ function update_script() { msg_info "Starting Service" systemctl start mediamanager msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/mediamtx.sh b/ct/mediamtx.sh index 929e63df6..715ea6bab 100644 --- a/ct/mediamtx.sh +++ b/ct/mediamtx.sh @@ -38,7 +38,7 @@ function update_script() { msg_info "Starting service" systemctl start mediamtx msg_ok "Service started" - msg_ok "Updated successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/medusa.sh b/ct/medusa.sh index 259b5cc9b..639370d4a 100644 --- a/ct/medusa.sh +++ b/ct/medusa.sh @@ -38,7 +38,7 @@ function update_script() { msg_ok "$APP is already up to date." exit fi - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" msg_info "Starting Service" systemctl start medusa diff --git a/ct/meilisearch.sh b/ct/meilisearch.sh index 445e77647..3a8adbf4e 100644 --- a/ct/meilisearch.sh +++ b/ct/meilisearch.sh @@ -40,7 +40,7 @@ function update_script() { msg_info "Starting Meilisearch" systemctl start meilisearch msg_ok "Started Meilisearch" - msg_ok "Update Successfully" + msg_ok "Updated successfully!" fi exit fi @@ -69,7 +69,7 @@ function update_script() { msg_info "Starting Meilisearch-UI" systemctl start meilisearch-ui msg_ok "Started Meilisearch-UI" - msg_ok "Update Successfully" + msg_ok "Updated successfully!" fi exit fi diff --git a/ct/memos.sh b/ct/memos.sh index 19e1c2739..2d2ab267a 100644 --- a/ct/memos.sh +++ b/ct/memos.sh @@ -37,7 +37,7 @@ function update_script() { msg_info "Starting service" systemctl start memos msg_ok "Service started" - msg_ok "Updated successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/meshcentral.sh b/ct/meshcentral.sh index fb886cdb1..599c7d099 100644 --- a/ct/meshcentral.sh +++ b/ct/meshcentral.sh @@ -30,7 +30,7 @@ function update_script() { msg_info "Updating ${APP} LXC" $STD apt update $STD apt -y upgrade - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" exit } @@ -41,4 +41,4 @@ 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}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}" diff --git a/ct/metube.sh b/ct/metube.sh deleted file mode 100644 index bea5be626..000000000 --- a/ct/metube.sh +++ /dev/null @@ -1,123 +0,0 @@ -#!/usr/bin/env bash -source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) -# Copyright (c) 2021-2025 tteck -# Author: MickLesk (Canbiz) -# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE -# Source: https://github.com/alexta69/metube - -APP="MeTube" -var_tags="${var_tags:-media;youtube}" -var_cpu="${var_cpu:-1}" -var_ram="${var_ram:-2048}" -var_disk="${var_disk:-10}" -var_os="${var_os:-debian}" -var_version="${var_version:-13}" -var_unprivileged="${var_unprivileged:-1}" - -header_info "$APP" -variables -color -catch_errors - -function update_script() { - header_info - check_container_storage - check_container_resources - - if [[ ! -d /opt/metube ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - - if [[ $(echo ":$PATH:" != *":/usr/local/bin:"*) ]]; then - echo -e "\nexport PATH=\"/usr/local/bin:\$PATH\"" >>~/.bashrc - source ~/.bashrc - if ! command -v deno &>/dev/null; then - export DENO_INSTALL="/usr/local" - curl -fsSL https://deno.land/install.sh | $STD sh -s -- -y - else - $STD deno upgrade - fi - fi - - if check_for_gh_release "metube" "alexta69/metube"; then - msg_info "Stopping Service" - systemctl stop metube - msg_ok "Stopped Service" - - msg_info "Backing up Old Installation" - if [[ -d /opt/metube_bak ]]; then - rm -rf /opt/metube_bak - fi - mv /opt/metube /opt/metube_bak - msg_ok "Backup created" - - fetch_and_deploy_gh_release "metube" "alexta69/metube" "tarball" "latest" - - msg_info "Building Frontend" - cd /opt/metube/ui - $STD npm install - $STD node_modules/.bin/ng build - msg_ok "Built Frontend" - - PYTHON_VERSION="3.13" setup_uv - - msg_info "Installing Backend Requirements" - cd /opt/metube - $STD uv sync - msg_ok "Installed Backend" - - msg_info "Restoring Environment File" - if [[ -f /opt/metube_bak/.env ]]; then - cp /opt/metube_bak/.env /opt/metube/.env - fi - msg_ok "Restored .env" - - if grep -q 'pipenv' /etc/systemd/system/metube.service; then - msg_info "Patching systemd Service" - cat </etc/systemd/system/metube.service -[Unit] -Description=Metube - YouTube Downloader -After=network.target - -[Service] -Type=simple -WorkingDirectory=/opt/metube -EnvironmentFile=/opt/metube/.env -ExecStart=/opt/metube/.venv/bin/python3 app/main.py -Restart=always -User=root - -[Install] -WantedBy=multi-user.target -EOF - msg_ok "Patched systemd Service" - fi - $STD systemctl daemon-reload - msg_ok "Service Updated" - - msg_info "Cleaning up" - rm -rf /opt/metube_bak - $STD apt -y autoremove - $STD apt -y autoclean - $STD apt -y clean - msg_ok "Cleaned Up" - - msg_info "Starting Service" - systemctl start metube - sleep 1 - msg_ok "Started Service" - - msg_ok "Updated Successfully!" - fi - exit -} - -start -build_container -description - -msg_ok "Completed Successfully!\n" -echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}" -echo -e "${INFO}${YW} Access it using the following URL:${CL}" -echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8081${CL}" diff --git a/ct/minarca.sh b/ct/minarca.sh index 08d80417e..a9115aac0 100644 --- a/ct/minarca.sh +++ b/ct/minarca.sh @@ -41,6 +41,7 @@ function update_script() { msg_info "Starting Service" systemctl start minarca-server msg_ok "Started Service" + msg_ok "Updated successfully!" exit } diff --git a/ct/minio.sh b/ct/minio.sh index 501d18f89..5fb460164 100644 --- a/ct/minio.sh +++ b/ct/minio.sh @@ -66,7 +66,7 @@ function update_script() { rm -f /usr/local/bin/minio_bak msg_ok "Cleaned" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" else msg_ok "No update required. ${APP} is already at ${RELEASE}" fi diff --git a/ct/mongodb.sh b/ct/mongodb.sh index 5243e34e9..2de56fb29 100644 --- a/ct/mongodb.sh +++ b/ct/mongodb.sh @@ -30,7 +30,7 @@ function update_script() { msg_info "Updating ${APP} LXC" $STD apt update $STD apt -y upgrade - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" exit } @@ -39,4 +39,4 @@ build_container description msg_ok "Completed Successfully!\n" -echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}" \ No newline at end of file +echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}" diff --git a/ct/monica.sh b/ct/monica.sh index fbb4f2286..86e7f08c3 100644 --- a/ct/monica.sh +++ b/ct/monica.sh @@ -61,7 +61,7 @@ function update_script() { msg_info "Cleaning up" rm -r /opt/monica-backup msg_ok "Cleaned" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/motioneye.sh b/ct/motioneye.sh index c09823680..439e9eee2 100644 --- a/ct/motioneye.sh +++ b/ct/motioneye.sh @@ -29,7 +29,7 @@ function update_script() { fi msg_info "Updating ${APP} LXC" $STD pip install motioneye --upgrade - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" exit } @@ -40,4 +40,4 @@ 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}:8765${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8765${CL}" diff --git a/ct/mqtt.sh b/ct/mqtt.sh index f77c194ee..2a70c9149 100644 --- a/ct/mqtt.sh +++ b/ct/mqtt.sh @@ -30,7 +30,7 @@ function update_script() { msg_info "Updating ${APP} LXC" $STD apt update $STD apt -y upgrade - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" exit } @@ -41,4 +41,4 @@ 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 IP:${CL}" -echo -e "${TAB}${GATEWAY}${BGN}${IP}:1883${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}${IP}:1883${CL}" diff --git a/ct/myip.sh b/ct/myip.sh index a17e69e57..8c4cfef14 100644 --- a/ct/myip.sh +++ b/ct/myip.sh @@ -40,7 +40,7 @@ function update_script() { msg_info "Starting Services" systemctl start myip msg_ok "Started Services" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/mylar3.sh b/ct/mylar3.sh index 55983b62f..6d1c3049a 100644 --- a/ct/mylar3.sh +++ b/ct/mylar3.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) # Copyright (c) 2021-2025 community-scripts ORG -# Author: davalanche +# Author: davalanche | Co-Author: Slaviša Arežina (tremor021) # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE # Source: https://github.com/mylar3/mylar3 @@ -25,16 +25,11 @@ function update_script() { msg_error "No ${APP} Installation Found!" exit fi - RELEASE=$(curl -fsSL https://api.github.com/repos/mylar3/mylar3/releases/latest | jq -r '.tag_name') - if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then - msg_info "Updating ${APP} to ${RELEASE}" - rm -rf /opt/mylar3/* /opt/mylar3/.* -curl -fsSL "https://github.com/mylar3/mylar3/archive/refs/tags/${RELEASE}.tar.gz" | tar -xz --strip-components=1 -C /opt/mylar3 + + if check_for_gh_release "mylar3" "mylar3/mylar3"; then + fetch_and_deploy_gh_release "mylar3" "mylar3/mylar3" "tarball" systemctl restart mylar3 - echo "${RELEASE}" >/opt/${APP}_version.txt - msg_ok "Updated ${APP} to ${RELEASE}" - else - msg_ok "No update required. ${APP} is already at ${RELEASE}" + msg_ok "Updated successfully!" fi exit } @@ -46,4 +41,4 @@ 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}:8090${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8090${CL}" diff --git a/ct/myspeed.sh b/ct/myspeed.sh index 1ebab50eb..cd4f7dc55 100644 --- a/ct/myspeed.sh +++ b/ct/myspeed.sh @@ -52,7 +52,7 @@ function update_script() { msg_info "Starting Service" systemctl start myspeed msg_ok "Started Service" - msg_ok "Updated Successfully!\n" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/mysql.sh b/ct/mysql.sh index 66224e0e2..10d460130 100644 --- a/ct/mysql.sh +++ b/ct/mysql.sh @@ -11,7 +11,7 @@ var_cpu="${var_cpu:-1}" var_ram="${var_ram:-1024}" var_disk="${var_disk:-4}" var_os="${var_os:-debian}" -var_version="${var_version:-13}" +var_version="${var_version:-12}" var_unprivileged="${var_unprivileged:-1}" header_info "$APP" @@ -20,18 +20,18 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources - if [[ ! -f /usr/share/keyrings/mysql.gpg ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - msg_info "Updating ${APP} LXC" - $STD apt update - $STD apt -y upgrade - msg_ok "Updated Successfully" + header_info + check_container_storage + check_container_resources + if [[ ! -f /usr/share/keyrings/mysql.gpg ]]; then + msg_error "No ${APP} Installation Found!" exit + fi + msg_info "Updating ${APP} LXC" + $STD apt update + $STD apt -y upgrade + msg_ok "Updated successfully!" + exit } start @@ -41,4 +41,4 @@ 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 IP:${CL}" -echo -e "${TAB}${GATEWAY}${BGN}${IP}:3306${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}${IP}:3306${CL}" diff --git a/ct/n8n.sh b/ct/n8n.sh index 7d8983005..1f3f45725 100644 --- a/ct/n8n.sh +++ b/ct/n8n.sh @@ -44,7 +44,7 @@ EOF rm -rf /usr/lib/node_modules/.n8n-* /usr/lib/node_modules/n8n $STD npm install -g n8n --force systemctl restart n8n - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" exit } diff --git a/ct/navidrome.sh b/ct/navidrome.sh index 36983d3d5..f3a35b99c 100644 --- a/ct/navidrome.sh +++ b/ct/navidrome.sh @@ -38,7 +38,7 @@ function update_script() { msg_info "Starting Services" systemctl start navidrome msg_ok "Started Services" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/neo4j.sh b/ct/neo4j.sh index 5355e87bb..4dd2a0aca 100644 --- a/ct/neo4j.sh +++ b/ct/neo4j.sh @@ -33,7 +33,7 @@ function update_script() { msg_info "Updating ${APP}" $STD apt update $STD apt -y upgrade - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" exit } diff --git a/ct/netbox.sh b/ct/netbox.sh index 3f0d4546d..da65be321 100644 --- a/ct/netbox.sh +++ b/ct/netbox.sh @@ -68,7 +68,7 @@ function update_script() { rm -r "/opt/v${RELEASE}.zip" rm -r /opt/netbox-backup msg_ok "Cleaned" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" else msg_ok "No update required. ${APP} is already at v${RELEASE}" fi diff --git a/ct/nextcloudpi.sh b/ct/nextcloudpi.sh index 233f302ce..bb53a52ce 100644 --- a/ct/nextcloudpi.sh +++ b/ct/nextcloudpi.sh @@ -30,7 +30,7 @@ function update_script() { msg_info "Updating ${APP} LXC" $STD apt update $STD apt -y upgrade - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" exit } @@ -41,4 +41,4 @@ 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}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}" diff --git a/ct/nextpvr.sh b/ct/nextpvr.sh index ffb16bb01..43f3c9d35 100644 --- a/ct/nextpvr.sh +++ b/ct/nextpvr.sh @@ -50,7 +50,7 @@ function update_script() { msg_info "Cleaning Up" rm -rf /opt/nextpvr-helper.deb msg_ok "Cleaned" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" exit } diff --git a/ct/nginxproxymanager.sh b/ct/nginxproxymanager.sh index d639f1fa7..c384a48e8 100644 --- a/ct/nginxproxymanager.sh +++ b/ct/nginxproxymanager.sh @@ -1,15 +1,15 @@ #!/usr/bin/env bash source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) -# Copyright (c) 2021-2025 tteck -# Author: tteck (tteckster) +# Copyright (c) 2021-2025 Community-Script ORG +# Author: tteck (tteckster) | Co-Author: CrazyWolf13 # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE # Source: https://nginxproxymanager.com/ APP="Nginx Proxy Manager" var_tags="${var_tags:-proxy}" var_cpu="${var_cpu:-2}" -var_ram="${var_ram:-1024}" -var_disk="${var_disk:-4}" +var_ram="${var_ram:-2048}" +var_disk="${var_disk:-8}" var_os="${var_os:-debian}" var_version="${var_version:-13}" var_unprivileged="${var_unprivileged:-1}" @@ -27,8 +27,14 @@ function update_script() { msg_error "No ${APP} Installation Found!" exit fi - - if command -v node &> /dev/null; then + + if [[ $(grep -E '^VERSION_ID=' /etc/os-release) == *"12"* ]]; then + msg_error "Wrong Debian version detected!" + msg_error "Please create a snapshot first. You must upgrade your LXC to Debian Trixie before updating. Visit: https://github.com/community-scripts/ProxmoxVE/discussions/7489" + exit + fi + + if command -v node &>/dev/null; then CURRENT_NODE_VERSION=$(node --version | cut -d'v' -f2 | cut -d'.' -f1) if [[ "$CURRENT_NODE_VERSION" != "22" ]]; then systemctl stop openresty @@ -42,60 +48,47 @@ function update_script() { fi NODE_VERSION="22" NODE_MODULE="yarn" setup_nodejs - export NODE_OPTIONS="--openssl-legacy-provider" RELEASE=$(curl -fsSL https://api.github.com/repos/NginxProxyManager/nginx-proxy-manager/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }') - msg_info "Downloading NPM v${RELEASE}" - curl -fsSL "https://codeload.github.com/NginxProxyManager/nginx-proxy-manager/tar.gz/v${RELEASE}" | tar -xz - cd nginx-proxy-manager-"${RELEASE}" || exit - msg_ok "Downloaded NPM v${RELEASE}" - - msg_info "Building Frontend" - ( - sed -i "s|\"version\": \"0.0.0\"|\"version\": \"$RELEASE\"|" backend/package.json - sed -i "s|\"version\": \"0.0.0\"|\"version\": \"$RELEASE\"|" frontend/package.json - cd ./frontend || exit - # Replace node-sass with sass in package.json before installation - sed -i 's/"node-sass".*$/"sass": "^1.92.1",/g' package.json - $STD yarn install --network-timeout 600000 - $STD yarn build - ) - msg_ok "Built Frontend" + fetch_and_deploy_gh_release "nginxproxymanager" "NginxProxyManager/nginx-proxy-manager" msg_info "Stopping Services" systemctl stop openresty systemctl stop npm msg_ok "Stopped Services" - msg_info "Cleaning Old Files" - rm -rf /app \ + msg_info "Cleaning old files" + $STD rm -rf /app \ /var/www/html \ /etc/nginx \ /var/log/nginx \ /var/lib/nginx \ - "$STD" /var/cache/nginx - msg_ok "Cleaned Old Files" + /var/cache/nginx + msg_ok "Cleaned old files" msg_info "Setting up Environment" ln -sf /usr/bin/python3 /usr/bin/python - ln -sf /opt/certbot/bin/certbot /usr/local/bin/certbot ln -sf /usr/local/openresty/nginx/sbin/nginx /usr/sbin/nginx ln -sf /usr/local/openresty/nginx/ /etc/nginx - sed -i 's+^daemon+#daemon+g' docker/rootfs/etc/nginx/nginx.conf - NGINX_CONFS=$(find "$(pwd)" -type f -name "*.conf") + sed -i "s|\"version\": \"2.0.0\"|\"version\": \"$RELEASE\"|" /opt/nginxproxymanager/backend/package.json + sed -i "s|\"version\": \"2.0.0\"|\"version\": \"$RELEASE\"|" /opt/nginxproxymanager/frontend/package.json + sed -i 's+^daemon+#daemon+g' /opt/nginxproxymanager/docker/rootfs/etc/nginx/nginx.conf + NGINX_CONFS=$(find /opt/nginxproxymanager -type f -name "*.conf") for NGINX_CONF in $NGINX_CONFS; do sed -i 's+include conf.d+include /etc/nginx/conf.d+g' "$NGINX_CONF" done + mkdir -p /var/www/html /etc/nginx/logs - cp -r docker/rootfs/var/www/html/* /var/www/html/ - cp -r docker/rootfs/etc/nginx/* /etc/nginx/ - cp docker/rootfs/etc/letsencrypt.ini /etc/letsencrypt.ini - cp docker/rootfs/etc/logrotate.d/nginx-proxy-manager /etc/logrotate.d/nginx-proxy-manager + cp -r /opt/nginxproxymanager/docker/rootfs/var/www/html/* /var/www/html/ + cp -r /opt/nginxproxymanager/docker/rootfs/etc/nginx/* /etc/nginx/ + cp /opt/nginxproxymanager/docker/rootfs/etc/letsencrypt.ini /etc/letsencrypt.ini + cp /opt/nginxproxymanager/docker/rootfs/etc/logrotate.d/nginx-proxy-manager /etc/logrotate.d/nginx-proxy-manager ln -sf /etc/nginx/nginx.conf /etc/nginx/conf/nginx.conf rm -f /etc/nginx/conf.d/dev.conf + mkdir -p /tmp/nginx/body \ /run/nginx \ /data/nginx \ @@ -112,27 +105,33 @@ function update_script() { /var/lib/nginx/cache/public \ /var/lib/nginx/cache/private \ /var/cache/nginx/proxy_temp + chmod -R 777 /var/cache/nginx chown root /tmp/nginx + echo resolver "$(awk 'BEGIN{ORS=" "} $1=="nameserver" {print ($2 ~ ":")? "["$2"]": $2}' /etc/resolv.conf);" >/etc/nginx/conf.d/include/resolvers.conf + if [ ! -f /data/nginx/dummycert.pem ] || [ ! -f /data/nginx/dummykey.pem ]; then $STD openssl req -new -newkey rsa:2048 -days 3650 -nodes -x509 -subj "/O=Nginx Proxy Manager/OU=Dummy Certificate/CN=localhost" -keyout /data/nginx/dummykey.pem -out /data/nginx/dummycert.pem fi - mkdir -p /app/global /app/frontend/images - cp -r frontend/dist/* /app/frontend - cp -r frontend/app-images/* /app/frontend/images - cp -r backend/* /app - cp -r global/* /app/global - # Update Certbot and plugins in virtual environment - if [ -d /opt/certbot ]; then - $STD /opt/certbot/bin/pip install --upgrade pip setuptools wheel - $STD /opt/certbot/bin/pip install --upgrade certbot certbot-dns-cloudflare - fi - msg_ok "Setup Environment" + mkdir -p /app/frontend/images + cp -r /opt/nginxproxymanager/backend/* /app + msg_ok "Set up Environment" + + msg_info "Building Frontend" + export NODE_OPTIONS="--max_old_space_size=2048 --openssl-legacy-provider" + cd /opt/nginxproxymanager/frontend + # Replace node-sass with sass in package.json before installation + sed -E -i 's/"node-sass" *: *"([^"]*)"/"sass": "\1"/g' package.json + $STD yarn install --network-timeout 600000 + $STD yarn build + cp -r /opt/nginxproxymanager/frontend/dist/* /app/frontend + cp -r /opt/nginxproxymanager/frontend/public/images/* /app/frontend/images + msg_ok "Built Frontend" msg_info "Initializing Backend" - $STD rm -rf /app/config/default.json + rm -rf /app/config/default.json if [ ! -f /app/config/production.json ]; then cat <<'EOF' >/app/config/production.json { @@ -148,24 +147,38 @@ function update_script() { } EOF fi - cd /app || exit - export NODE_OPTIONS="--openssl-legacy-provider" + cd /app $STD yarn install --network-timeout 600000 msg_ok "Initialized Backend" + msg_info "Updating Certbot" + [ -f /etc/apt/trusted.gpg.d/openresty-archive-keyring.gpg ] && rm -f /etc/apt/trusted.gpg.d/openresty-archive-keyring.gpg + [ -f /etc/apt/sources.list.d/openresty.list ] && rm -f /etc/apt/sources.list.d/openresty.list + [ ! -f /etc/apt/trusted.gpg.d/openresty.gpg ] && curl -fsSL https://openresty.org/package/pubkey.gpg | gpg --dearmor --yes -o /etc/apt/trusted.gpg.d/openresty.gpg + [ ! -f /etc/apt/sources.list.d/openresty.sources ] && cat <<'EOF' >/etc/apt/sources.list.d/openresty.sources +Types: deb +URIs: http://openresty.org/package/debian/ +Suites: bookworm +Components: openresty +Signed-By: /etc/apt/trusted.gpg.d/openresty.gpg +EOF + $STD apt update + $STD apt -y install openresty + if [ -d /opt/certbot ]; then + $STD /opt/certbot/bin/pip install --upgrade pip setuptools wheel + $STD /opt/certbot/bin/pip install --upgrade certbot certbot-dns-cloudflare + fi + msg_ok "Updated Certbot" + msg_info "Starting Services" sed -i 's/user npm/user root/g; s/^pid/#pid/g' /usr/local/openresty/nginx/conf/nginx.conf - sed -i 's/su npm npm/su root root/g' /etc/logrotate.d/nginx-proxy-manager - sed -i 's/include-system-site-packages = false/include-system-site-packages = true/g' /opt/certbot/pyvenv.cfg + sed -r -i 's/^([[:space:]]*)su npm npm/\1#su npm npm/g;' /etc/logrotate.d/nginx-proxy-manager systemctl enable -q --now openresty systemctl enable -q --now npm + systemctl restart openresty msg_ok "Started Services" - msg_info "Cleaning up" - rm -rf ~/nginx-proxy-manager-* - msg_ok "Cleaned" - - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" exit } diff --git a/ct/nocodb.sh b/ct/nocodb.sh index 44956cfe6..32f92e6ac 100644 --- a/ct/nocodb.sh +++ b/ct/nocodb.sh @@ -37,7 +37,7 @@ function update_script() { msg_info "Starting Service" systemctl start nocodb msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/node-red.sh b/ct/node-red.sh index 3fb298fc1..e2fa69d26 100644 --- a/ct/node-red.sh +++ b/ct/node-red.sh @@ -45,7 +45,7 @@ function update_script() { msg_info "Starting Service" systemctl start nodered msg_ok "Started Service" - msg_ok "Update Successfully!" + msg_ok "Updated successfully!" exit fi if [ "$UPD" == "2" ]; then diff --git a/ct/nodebb.sh b/ct/nodebb.sh index e0a5b8025..b2c1f91d8 100644 --- a/ct/nodebb.sh +++ b/ct/nodebb.sh @@ -44,7 +44,7 @@ function update_script() { msg_info "Starting Service" systemctl start nodebb msg_ok "Started Service" - msg_ok "Updated Successfully\n" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/notifiarr.sh b/ct/notifiarr.sh index cd6ac5e3a..4090ec175 100644 --- a/ct/notifiarr.sh +++ b/ct/notifiarr.sh @@ -20,18 +20,19 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources - if [[ ! -f /etc/apt/sources.list.d/golift.list ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - msg_info "Updating $APP" - $STD apt update - $STD apt -y upgrade - msg_ok "Updated $APP" + header_info + check_container_storage + check_container_resources + if [[ ! -f /etc/apt/sources.list.d/golift.list ]]; then + msg_error "No ${APP} Installation Found!" exit + fi + msg_info "Updating $APP" + $STD apt update + $STD apt -y upgrade + msg_ok "Updated $APP" + msg_ok "Updated successfully!" + exit } start @@ -41,4 +42,4 @@ 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}:5454${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:5454${CL}" diff --git a/ct/npmplus.sh b/ct/npmplus.sh index 571df170c..459a5ab39 100644 --- a/ct/npmplus.sh +++ b/ct/npmplus.sh @@ -41,7 +41,7 @@ function update_script() { $STD docker compose pull msg_info "Recreating container" $STD docker compose up -d - msg_ok "NPMplus container updated" + msg_ok "Updated successfully!" exit ;; esac diff --git a/ct/ntfy.sh b/ct/ntfy.sh index 6dfb2c844..99d9484bc 100644 --- a/ct/ntfy.sh +++ b/ct/ntfy.sh @@ -20,36 +20,37 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources - if [[ ! -d /etc/ntfy ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi + header_info + check_container_storage + check_container_resources + if [[ ! -d /etc/ntfy ]]; then + msg_error "No ${APP} Installation Found!" + exit + fi - if [ -f /etc/apt/keyrings/archive.heckel.io.gpg ]; then - msg_info "Correcting old Ntfy Repository" - rm -f /etc/apt/keyrings/archive.heckel.io.gpg - rm -f /etc/apt/sources.list.d/archive.heckel.io.list - rm -f /etc/apt/sources.list.d/archive.heckel.io.list.bak - rm -f /etc/apt/sources.list.d/archive.heckel.io.sources - curl -fsSL -o /etc/apt/keyrings/ntfy.gpg https://archive.ntfy.sh/apt/keyring.gpg - cat <<'EOF' >/etc/apt/sources.list.d/ntfy.sources + if [ -f /etc/apt/keyrings/archive.heckel.io.gpg ]; then + msg_info "Correcting old Ntfy Repository" + rm -f /etc/apt/keyrings/archive.heckel.io.gpg + rm -f /etc/apt/sources.list.d/archive.heckel.io.list + rm -f /etc/apt/sources.list.d/archive.heckel.io.list.bak + rm -f /etc/apt/sources.list.d/archive.heckel.io.sources + curl -fsSL -o /etc/apt/keyrings/ntfy.gpg https://archive.ntfy.sh/apt/keyring.gpg + cat <<'EOF' >/etc/apt/sources.list.d/ntfy.sources Types: deb URIs: https://archive.ntfy.sh/apt/ Suites: stable Components: main Signed-By: /etc/apt/keyrings/ntfy.gpg EOF - msg_ok "Corrected old Ntfy Repository" - fi - - msg_info "Updating $APP LXC" - $STD apt update - $STD apt -y upgrade - msg_ok "Updated $APP LXC" - exit + msg_ok "Corrected old Ntfy Repository" + fi + + msg_info "Updating $APP LXC" + $STD apt update + $STD apt -y upgrade + msg_ok "Updated $APP LXC" + msg_ok "Updated successfully!" + exit } start diff --git a/ct/nxwitness.sh b/ct/nxwitness.sh index 32e7dfaa3..25a011a4b 100644 --- a/ct/nxwitness.sh +++ b/ct/nxwitness.sh @@ -53,7 +53,7 @@ function update_script() { rm -f /tmp/nxwitness-server-$RELEASE-linux_x64.deb msg_ok "Cleaned" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" else msg_ok "No update required. ${APP} is already at ${RELEASE}" fi diff --git a/ct/nzbget.sh b/ct/nzbget.sh index 39b96cc3a..7d102eb88 100644 --- a/ct/nzbget.sh +++ b/ct/nzbget.sh @@ -20,18 +20,19 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources - if [[ ! -f /lib/systemd/system/nzbget.service ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - msg_info "Updating $APP LXC" - $STD apt update - $STD apt -y upgrade - msg_ok "Updated $APP LXC" + header_info + check_container_storage + check_container_resources + if [[ ! -f /lib/systemd/system/nzbget.service ]]; then + msg_error "No ${APP} Installation Found!" exit + fi + msg_info "Updating $APP LXC" + $STD apt update + $STD apt -y upgrade + msg_ok "Updated $APP LXC" + msg_ok "Updated successfully!" + exit } start @@ -41,4 +42,4 @@ 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}:6789${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:6789${CL}" diff --git a/ct/oauth2-proxy.sh b/ct/oauth2-proxy.sh index 33ca28393..242b3e396 100644 --- a/ct/oauth2-proxy.sh +++ b/ct/oauth2-proxy.sh @@ -38,8 +38,9 @@ function update_script() { msg_info "Starting Service" systemctl start oauth2-proxy msg_ok "Started Service" - msg_ok "Updated successfully!\n" + msg_ok "Updated successfully!" fi + exit } start diff --git a/ct/octoprint.sh b/ct/octoprint.sh index 9b9acbd4a..577a48cbf 100644 --- a/ct/octoprint.sh +++ b/ct/octoprint.sh @@ -39,7 +39,7 @@ function update_script() { msg_info "Starting OctoPrint" systemctl start octoprint msg_ok "Started OctoPrint" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" exit } @@ -50,4 +50,4 @@ 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}:5000${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:5000${CL}" diff --git a/ct/odoo.sh b/ct/odoo.sh index 16e820295..ef6b9eee0 100644 --- a/ct/odoo.sh +++ b/ct/odoo.sh @@ -26,7 +26,7 @@ function update_script() { if [[ ! -f /etc/odoo/odoo.conf ]]; then msg_error "No ${APP} Installation Found!" - exit 1 + exit fi if ! [[ $(dpkg -s python3-lxml-html-clean 2>/dev/null) ]]; then $STD apt install python3-lxml @@ -61,7 +61,7 @@ function update_script() { rm -f /opt/odoo.deb msg_ok "Cleaned" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" else msg_ok "No update required. ${APP} is already at ${LATEST_VERSION}" fi diff --git a/ct/ollama.sh b/ct/ollama.sh index 4e443ed0e..aada56e48 100644 --- a/ct/ollama.sh +++ b/ct/ollama.sh @@ -53,7 +53,7 @@ function update_script() { msg_info "Cleaning Up" rm -f "${TMP_TAR}" msg_ok "Cleaned" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" else msg_ok "No update required. Ollama is already at ${RELEASE}" fi diff --git a/ct/omada.sh b/ct/omada.sh index c8e92a380..e2a005d7c 100644 --- a/ct/omada.sh +++ b/ct/omada.sh @@ -29,19 +29,13 @@ function update_script() { fi msg_info "Updating MongoDB" - MONGODB_VERSION="7.0" - if ! lscpu | grep -q 'avx'; then - MONGODB_VERSION="4.4" - msg_error "No AVX detected: TP-Link Canceled Support for Old MongoDB for Debian 12\n https://www.tp-link.com/baltic/support/faq/4160/" - exit 1 + if lscpu | grep -q 'avx'; then + MONGO_VERSION="8.0" setup_mongodb + else + msg_warn "No AVX detected: Using older MongoDB 4.4" + MONGO_VERSION="4.4" setup_mongodb fi - curl -fsSL "https://www.mongodb.org/static/pgp/server-${MONGODB_VERSION}.asc" | gpg --dearmor >/usr/share/keyrings/mongodb-server-${MONGODB_VERSION}.gpg - echo "deb [signed-by=/usr/share/keyrings/mongodb-server-${MONGODB_VERSION}.gpg] http://repo.mongodb.org/apt/debian $(grep '^VERSION_CODENAME=' /etc/os-release | cut -d'=' -f2)/mongodb-org/${MONGODB_VERSION} main" >/etc/apt/sources.list.d/mongodb-org-${MONGODB_VERSION}.list - $STD apt update - $STD apt install -y --only-upgrade mongodb-org - msg_ok "Updated MongoDB to $MONGODB_VERSION" - msg_info "Checking if right Azul Zulu Java is installed" java_version=$(java -version 2>&1 | awk -F[\"_] '/version/ {print $2}') if [[ "$java_version" =~ ^1\.8\.* ]]; then @@ -59,14 +53,14 @@ function update_script() { OMADA_PKG=$(basename "$OMADA_URL") if [ -z "$OMADA_PKG" ]; then msg_error "Could not retrieve Omada package – server may be down." - exit 1 + exit fi curl -fsSL "$OMADA_URL" -o "$OMADA_PKG" export DEBIAN_FRONTEND=noninteractive $STD dpkg -i "$OMADA_PKG" rm -f "$OMADA_PKG" - msg_ok "Updated Omada Controller" - exit 0 + msg_ok "Updated successfully!" + exit } start diff --git a/ct/ombi.sh b/ct/ombi.sh index b63c15578..dbc96ce19 100644 --- a/ct/ombi.sh +++ b/ct/ombi.sh @@ -47,7 +47,7 @@ function update_script() { msg_info "Starting Service" systemctl start ombi msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/omv.sh b/ct/omv.sh index 29f1cd87f..807876b7d 100644 --- a/ct/omv.sh +++ b/ct/omv.sh @@ -11,7 +11,7 @@ var_cpu="${var_cpu:-2}" var_ram="${var_ram:-1024}" var_disk="${var_disk:-4}" var_os="${var_os:-debian}" -var_version="${var_version:-13}" +var_version="${var_version:-12}" var_unprivileged="${var_unprivileged:-1}" header_info "$APP" @@ -20,18 +20,18 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources - if [[ ! -f /etc/apt/sources.list.d/openmediavault.list ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - msg_info "Updating ${APP} LXC" - $STD apt update - $STD apt -y upgrade - msg_ok "Updated Successfully" + header_info + check_container_storage + check_container_resources + if [[ ! -f /etc/apt/sources.list.d/openmediavault.list ]]; then + msg_error "No ${APP} Installation Found!" exit + fi + msg_info "Updating ${APP} LXC" + $STD apt update + $STD apt -y upgrade + msg_ok "Updated successfully!" + exit } start @@ -41,4 +41,4 @@ 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}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}" diff --git a/ct/onedev.sh b/ct/onedev.sh index cef42a251..b42219a4a 100644 --- a/ct/onedev.sh +++ b/ct/onedev.sh @@ -50,7 +50,7 @@ function update_script() { rm -rf /opt/onedev-latest rm -rf /opt/onedev-latest.tar.gz msg_ok "Cleaned" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" else msg_ok "No update required. ${APP} is already at v${RELEASE}." fi diff --git a/ct/onlyoffice.sh b/ct/onlyoffice.sh index 14caa258d..8aadbc1af 100644 --- a/ct/onlyoffice.sh +++ b/ct/onlyoffice.sh @@ -26,7 +26,7 @@ function update_script() { if [[ ! -d /var/www/onlyoffice ]]; then msg_error "No valid ${APP} installation found!" - exit 1 + exit fi msg_info "Updating $APP" @@ -39,6 +39,7 @@ function update_script() { $STD systemctl restart onlyoffice-documentserver msg_ok "$APP restarted" fi + msg_ok "Updated successfully!" exit } diff --git a/ct/open-archiver.sh b/ct/open-archiver.sh index 146a95ae0..1ddf02da2 100644 --- a/ct/open-archiver.sh +++ b/ct/open-archiver.sh @@ -38,15 +38,21 @@ function update_script() { mv /opt/openarchiver.env /opt/openarchiver/.env msg_info "Updating Open Archiver" + cd /opt/openarchiver $STD pnpm install --shamefully-hoist --frozen-lockfile --prod=false - $STD pnpm build + $STD pnpm run build:oss $STD pnpm db:migrate msg_ok "Updated Open Archiver" + if grep -q '^ExecStart=/usr/bin/pnpm docker-start$' /etc/systemd/system/openarchiver.service; then + sed -i 's|^ExecStart=/usr/bin/pnpm docker-start$|ExecStart=/usr/bin/pnpm docker-start:oss|' /etc/systemd/system/openarchiver.service + systemctl daemon-reload + fi + msg_info "Starting Services" systemctl start openarchiver msg_ok "Started Services" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/opengist.sh b/ct/opengist.sh index 0a92efc25..5c4f683e3 100644 --- a/ct/opengist.sh +++ b/ct/opengist.sh @@ -45,7 +45,7 @@ function update_script() { msg_info "Starting Service" systemctl start opengist msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/openhab.sh b/ct/openhab.sh index 8c14f66cc..f1711574e 100644 --- a/ct/openhab.sh +++ b/ct/openhab.sh @@ -30,7 +30,7 @@ function update_script() { msg_info "Updating ${APP} LXC" $STD apt update $STD apt -y upgrade - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" exit } diff --git a/ct/openobserve.sh b/ct/openobserve.sh index 18dfdedba..3507d6726 100644 --- a/ct/openobserve.sh +++ b/ct/openobserve.sh @@ -20,20 +20,21 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources - if [[ ! -d /opt/openobserve/ ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - msg_info "Updating $APP" - systemctl stop openobserve - LATEST=$(curl -fsSL https://api.github.com/repos/openobserve/openobserve/releases/latest | grep '"tag_name":' | cut -d'"' -f4) - $STD tar zxvf <(curl -fsSL https://downloads.openobserve.ai/releases/openobserve/$LATEST/openobserve-$LATEST-linux-amd64.tar.gz) -C /opt/openobserve - systemctl start openobserve - msg_ok "Updated $APP" + header_info + check_container_storage + check_container_resources + if [[ ! -d /opt/openobserve/ ]]; then + msg_error "No ${APP} Installation Found!" exit + fi + msg_info "Updating $APP" + systemctl stop openobserve + LATEST=$(curl -fsSL https://api.github.com/repos/openobserve/openobserve/releases/latest | grep '"tag_name":' | cut -d'"' -f4) + $STD tar zxvf <(curl -fsSL https://downloads.openobserve.ai/releases/openobserve/$LATEST/openobserve-$LATEST-linux-amd64.tar.gz) -C /opt/openobserve + systemctl start openobserve + msg_ok "Updated $APP" + msg_ok "Updated successfully!" + exit } start diff --git a/ct/openproject.sh b/ct/openproject.sh index 1ace33f44..af13d59b6 100644 --- a/ct/openproject.sh +++ b/ct/openproject.sh @@ -31,7 +31,8 @@ function update_script() { $STD apt update $STD apt install --only-upgrade -y openproject msg_ok "Updated ${APP}" - exit 0 + msg_ok "Updated successfully!" + exit } start diff --git a/ct/openwebui.sh b/ct/openwebui.sh index f3a8cb42a..ec1122dbe 100644 --- a/ct/openwebui.sh +++ b/ct/openwebui.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) # Copyright (c) 2021-2025 tteck -# Author: havardthom +# Author: tteck | Co-Author: havardthom | Co-Author: Slaviša Arežina (tremor021) # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE # Source: https://openwebui.com/ @@ -11,7 +11,7 @@ var_cpu="${var_cpu:-4}" var_ram="${var_ram:-8192}" var_disk="${var_disk:-25}" var_os="${var_os:-debian}" -var_version="${var_version:-12}" +var_version="${var_version:-13}" var_unprivileged="${var_unprivileged:-1}" header_info "$APP" @@ -23,7 +23,7 @@ function update_script() { header_info check_container_storage check_container_resources - if [[ ! -d /opt/open-webui ]]; then + if [[ ! -d /root/.open-webui ]]; then msg_error "No ${APP} Installation Found!" exit fi @@ -50,30 +50,9 @@ function update_script() { fi fi - msg_info "Updating ${APP} (Patience)" - cd /opt/open-webui - mkdir -p /opt/open-webui-backup - cp -rf /opt/open-webui/backend/data /opt/open-webui-backup - git add -A - $STD git stash - $STD git reset --hard - output=$(git pull --no-rebase) - if echo "$output" | grep -q "Already up to date."; then - msg_ok "$APP is already up to date." - exit - fi - systemctl stop open-webui.service - $STD npm install --force - export NODE_OPTIONS="--max-old-space-size=6000" - $STD npm run build - cd ./backend - $STD pip install -r requirements.txt -U - cp -rf /opt/open-webui-backup/* /opt/open-webui/backend - if git stash list | grep -q 'stash@{'; then - $STD git stash pop - fi - systemctl start open-webui.service - msg_ok "Updated Successfully" + msg_info "Restarting Open WebUI to initiate update" + systemctl restart open-webui + msg_ok "Updated successfully!" exit } diff --git a/ct/openziti-controller.sh b/ct/openziti-controller.sh index 438c77607..98ea6b6ed 100644 --- a/ct/openziti-controller.sh +++ b/ct/openziti-controller.sh @@ -31,6 +31,7 @@ function update_script() { $STD apt update $STD apt -y upgrade msg_ok "Updated $APP LXC" + msg_ok "Updated successfully!" exit } diff --git a/ct/openziti-tunnel.sh b/ct/openziti-tunnel.sh index 4d768a8bb..5d84c747b 100644 --- a/ct/openziti-tunnel.sh +++ b/ct/openziti-tunnel.sh @@ -20,18 +20,19 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources - if [[ ! -d /opt/openziti ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - msg_info "Updating $APP LXC" - $STD apt update - $STD apt -y upgrade - msg_ok "Updated $APP LXC" - exit + header_info + check_container_storage + check_container_resources + if [[ ! -d /opt/openziti ]]; then + msg_error "No ${APP} Installation Found!" + exit + fi + msg_info "Updating $APP LXC" + $STD apt update + $STD apt -y upgrade + msg_ok "Updated $APP LXC" + msg_ok "Updated successfully!" + exit } start @@ -41,4 +42,4 @@ description msg_ok "Completed Successfully!\n" echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}" echo -e "${INFO}${YW} Application was assigned the following IP:${CL}" -echo -e "${TAB}${GATEWAY}${BGN}Address: ${IP}${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}Address: ${IP}${CL}" diff --git a/ct/ots.sh b/ct/ots.sh index 3275fa49d..5ec650f6c 100644 --- a/ct/ots.sh +++ b/ct/ots.sh @@ -39,7 +39,7 @@ function update_script() { systemctl start ots systemctl start nginx msg_ok "Started Services" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/outline.sh b/ct/outline.sh index 8649b5999..1d43d6a89 100644 --- a/ct/outline.sh +++ b/ct/outline.sh @@ -54,7 +54,7 @@ function update_script() { msg_info "Starting Services" systemctl start outline msg_ok "Started Services" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/owncast.sh b/ct/owncast.sh index 2b70aaa04..108f948a4 100644 --- a/ct/owncast.sh +++ b/ct/owncast.sh @@ -37,7 +37,7 @@ function update_script() { msg_info "Starting Service" systemctl start owncast msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/pairdrop.sh b/ct/pairdrop.sh index c8ae6625f..175bcf088 100644 --- a/ct/pairdrop.sh +++ b/ct/pairdrop.sh @@ -42,7 +42,7 @@ function update_script() { msg_info "Starting Service" systemctl start pairdrop msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/palmr.sh b/ct/palmr.sh index 2ef184912..ced39303a 100644 --- a/ct/palmr.sh +++ b/ct/palmr.sh @@ -60,7 +60,7 @@ function update_script() { msg_info "Starting Services" systemctl start palmr-backend palmr-frontend msg_ok "Started Services" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/pangolin.sh b/ct/pangolin.sh new file mode 100644 index 000000000..faa10e818 --- /dev/null +++ b/ct/pangolin.sh @@ -0,0 +1,79 @@ +#!/usr/bin/env bash +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/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://pangolin.net/ + +APP="Pangolin" +var_tags="${var_tags:-proxy}" +var_cpu="${var_cpu:-2}" +var_ram="${var_ram:-4096}" +var_disk="${var_disk:-5}" +var_os="${var_os:-debian}" +var_version="${var_version:-13}" +var_unprivileged="${var_unprivileged:-1}" +var_tun="${var_tun:-1}" + +header_info "$APP" +variables +color +catch_errors + +function update_script() { + header_info + check_container_storage + check_container_resources + if [[ ! -d /opt/pangolin ]]; then + msg_error "No ${APP} Installation Found!" + exit + fi + + if check_for_gh_release "pangolin" "fosrl/pangolin"; then + msg_info "Stopping Service" + systemctl stop pangolin + systemctl stop gerbil + msg_info "Service stopped" + + msg_info "Creating backup" + tar -czf /opt/pangolin_config_backup.tar.gz -C /opt/pangolin config + msg_ok "Created backup" + + CLEAN_INSTALL=1 fetch_and_deploy_gh_release "pangolin" "fosrl/pangolin" "tarball" + CLEAN_INSTALL=1 fetch_and_deploy_gh_release "gerbil" "fosrl/gerbil" "singlefile" "latest" "/usr/bin" "gerbil_linux_amd64" + + msg_info "Updating Pangolin" + cd /opt/pangolin + $STD npm ci + $STD npm run set:sqlite + $STD npm run set:oss + rm -rf server/private + $STD npm run build:sqlite + $STD npm run build:cli + cp -R .next/standalone ./ + chmod +x ./dist/cli.mjs + cp server/db/names.json ./dist/names.json + msg_ok "Updated Pangolin" + + msg_info "Restoring config" + tar -xzf /opt/pangolin_config_backup.tar.gz -C /opt/pangolin --overwrite + rm -f /opt/pangolin_config_backup.tar.gz + msg_ok "Restored config" + + msg_info "Starting Services" + systemctl start pangolin + systemctl start gerbil + msg_ok "Started Services" + msg_ok "Updated successfully!" + fi + exit +} + +start +build_container +description + +msg_ok "Completed Successfully!\n" +echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}" +echo -e "${INFO}${YW} Access it using the following URL:${CL}" +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:3002${CL}" diff --git a/ct/paperless-ai.sh b/ct/paperless-ai.sh index 6ff461a3d..7ccdf9458 100644 --- a/ct/paperless-ai.sh +++ b/ct/paperless-ai.sh @@ -32,9 +32,9 @@ function update_script() { fi RELEASE=$(curl -fsSL https://api.github.com/repos/clusterzx/paperless-ai/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }') if [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]] || [[ ! -f /opt/${APP}_version.txt ]]; then - msg_info "Stopping $APP" + msg_info "Stopping Service" systemctl stop paperless-ai - msg_ok "Stopped $APP" + msg_info "Stopped Service" msg_info "Updating $APP to v${RELEASE}" cd /opt @@ -68,15 +68,15 @@ EOF echo "${RELEASE}" >/opt/${APP}_version.txt msg_ok "Updated $APP to v${RELEASE}" - msg_info "Starting $APP" + msg_info "Starting Service" systemctl start paperless-ai - msg_ok "Started $APP" + msg_ok "Started Service" msg_info "Cleaning Up" rm -rf /opt/v${RELEASE}.zip rm -rf /opt/paperless-ai_bak msg_ok "Cleanup Completed" - msg_ok "Update Successful" + msg_ok "Updated successfully!" else msg_ok "No update required. ${APP} is already at v${RELEASE}" fi diff --git a/ct/paperless-gpt.sh b/ct/paperless-gpt.sh index ad396de75..2f882b305 100644 --- a/ct/paperless-gpt.sh +++ b/ct/paperless-gpt.sh @@ -25,7 +25,7 @@ function update_script() { check_container_resources if [[ ! -d /opt/paperless-gpt ]]; then msg_error "No Paperless-GPT installation found!" - exit 1 + exit fi RELEASE=$(curl -fsSL https://api.github.com/repos/icereed/paperless-gpt/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }') if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then @@ -35,7 +35,7 @@ function update_script() { msg_info "Updating Paperless-GPT to ${RELEASE}" temp_file=$(mktemp) -curl -fsSL "https://github.com/icereed/paperless-gpt/archive/refs/tags/v${RELEASE}.tar.gz" -o "$temp_file" + curl -fsSL "https://github.com/icereed/paperless-gpt/archive/refs/tags/v${RELEASE}.tar.gz" -o "$temp_file" tar zxf $temp_file rm -rf /opt/paperless-gpt mv paperless-gpt-${RELEASE} /opt/paperless-gpt @@ -57,7 +57,7 @@ curl -fsSL "https://github.com/icereed/paperless-gpt/archive/refs/tags/v${RELEAS msg_info "Cleaning Up" rm -f $temp_file msg_ok "Cleanup Completed" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" else msg_ok "No update required. ${APP} is already at ${RELEASE}" fi @@ -71,4 +71,4 @@ description msg_ok "Completed Successfully!\n" echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}" echo -e "${INFO}${YW} Access it using the following URL:${CL}" -echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8080${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8080${CL}" diff --git a/ct/paperless-ngx.sh b/ct/paperless-ngx.sh index 42b09263d..a5a33ca21 100644 --- a/ct/paperless-ngx.sh +++ b/ct/paperless-ngx.sh @@ -63,7 +63,7 @@ function update_script() { read -rp "Have you created a snapshot? [y/N]: " confirm if [[ ! "$confirm" =~ ^([yY]|[yY][eE][sS])$ ]]; then msg_error "Migration aborted. Please create a snapshot first." - exit 1 + exit fi msg_info "Migrating old Paperless-ngx installation to uv" rm -rf /opt/paperless/venv @@ -120,7 +120,7 @@ function update_script() { systemctl start paperless-consumer paperless-webserver paperless-scheduler paperless-task-queue sleep 1 msg_ok "Started all Paperless-ngx Services" - msg_ok "Updated Successfully!\n" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/part-db.sh b/ct/part-db.sh index 2a54fd12c..9c2b96546 100644 --- a/ct/part-db.sh +++ b/ct/part-db.sh @@ -63,7 +63,7 @@ function update_script() { rm -r "/opt/v${RELEASE}.zip" rm -r /opt/partdb-backup msg_ok "Cleaned" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" else msg_ok "No update required. ${APP} is already at v${RELEASE}" fi diff --git a/ct/patchmon.sh b/ct/patchmon.sh new file mode 100644 index 000000000..514c804f2 --- /dev/null +++ b/ct/patchmon.sh @@ -0,0 +1,76 @@ +#!/usr/bin/env bash +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +# Copyright (c) 2021-2025 community-scripts ORG +# Author: vhsdream +# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE +# Source: https://github.com/PatchMon/PatchMon + +APP="PatchMon" +var_tags="${var_tags:-monitoring}" +var_cpu="${var_cpu:-2}" +var_ram="${var_ram:-2048}" +var_disk="${var_disk:-4}" +var_os="${var_os:-debian}" +var_version="${var_version:-13}" +var_unprivileged="${var_unprivileged:-1}" + +header_info "$APP" +variables +color +catch_errors + +function update_script() { + header_info + check_container_storage + check_container_resources + + if [[ ! -d "/opt/patchmon" ]]; then + msg_error "No ${APP} Installation Found!" + exit + fi + + NODE_VERSION="24" setup_nodejs + if check_for_gh_release "PatchMon" "PatchMon/PatchMon"; then + msg_info "Stopping Service" + systemctl stop patchmon-server + msg_ok "Stopped Service" + + msg_info "Creating Backup" + cp /opt/patchmon/backend/.env /opt/backend.env + cp /opt/patchmon/frontend/.env /opt/frontend.env + msg_ok "Backup Created" + + CLEAN_INSTALL=1 fetch_and_deploy_gh_release "PatchMon" "PatchMon/PatchMon" "tarball" "latest" "/opt/patchmon" + + msg_info "Updating PatchMon" + cd /opt/patchmon + export NODE_ENV=production + $STD npm install --no-audit --no-fund --no-save --ignore-scripts + cd /opt/patchmon/backend + $STD npm install --no-audit --no-fund --no-save --ignore-scripts + cd /opt/patchmon/frontend + $STD npm install --include=dev --no-audit --no-fund --no-save --ignore-scripts + $STD npm run build + cd /opt/patchmon/backend + mv /opt/backend.env /opt/patchmon/backend/.env + mv /opt/frontend.env /opt/patchmon/frontend/.env + $STD npx prisma migrate deploy + $STD npx prisma generate + msg_ok "Updated PatchMon" + + msg_info "Starting Service" + systemctl start patchmon-server + msg_ok "Started Service" + msg_ok "Updated successfully!" + fi + exit +} + +start +build_container +description + +msg_ok "Completed Successfully!\n" +echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}" +echo -e "${INFO}${YW} Access it using the following URL:${CL}" +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}" diff --git a/ct/paymenter.sh b/ct/paymenter.sh index 6316cf38c..0e701cae0 100644 --- a/ct/paymenter.sh +++ b/ct/paymenter.sh @@ -41,7 +41,7 @@ function update_script() { cd /opt/paymenter $STD php artisan app:upgrade --no-interaction echo "${CHECK_UPDATE_RELEASE}" >~/.paymenter - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/peanut.sh b/ct/peanut.sh index f2b74158a..181e1c750 100644 --- a/ct/peanut.sh +++ b/ct/peanut.sh @@ -31,9 +31,9 @@ function update_script() { NODE_VERSION="22" NODE_MODULE="pnpm" setup_nodejs if check_for_gh_release "peanut" "Brandawg93/PeaNUT"; then - msg_info "Stopping $APP" + msg_info "Stopping Service" systemctl stop peanut - msg_ok "Stopped $APP" + msg_info "Stopped Service" fetch_and_deploy_gh_release "peanut" "Brandawg93/PeaNUT" "tarball" "latest" "/opt/peanut" @@ -46,10 +46,10 @@ function update_script() { ln -sf /etc/peanut/settings.yml /opt/peanut/.next/standalone/config/settings.yml msg_ok "Updated $APP" - msg_info "Starting $APP" + msg_info "Starting Service" systemctl start peanut - msg_ok "Started $APP" - msg_ok "Updated Successfully" + msg_ok "Started Service" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/pelican-panel.sh b/ct/pelican-panel.sh index 961616d32..996416baa 100644 --- a/ct/pelican-panel.sh +++ b/ct/pelican-panel.sh @@ -52,7 +52,7 @@ function update_script() { msg_info "Updating ${APP} to v${RELEASE}" cp -r /opt/pelican-panel/.env /opt/ - SQLITE_INSTALL=$(ls /opt/pelican-panel/database/*.sqlite 1> /dev/null 2>&1 && echo "true" || echo "false") + SQLITE_INSTALL=$(ls /opt/pelican-panel/database/*.sqlite 1>/dev/null 2>&1 && echo "true" || echo "false") $SQLITE_INSTALL && cp -r /opt/pelican-panel/database/*.sqlite /opt/ rm -rf * .* curl -fsSL "https://github.com/pelican-dev/panel/releases/download/v${RELEASE}/panel.tar.gz" -o $(basename "https://github.com/pelican-dev/panel/releases/download/v${RELEASE}/panel.tar.gz") @@ -78,7 +78,7 @@ function update_script() { msg_info "Cleaning up" rm -rf "/opt/pelican-panel/panel.tar.gz" msg_ok "Cleaned" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" else msg_ok "No update required. ${APP} is already at v${RELEASE}" fi diff --git a/ct/pelican-wings.sh b/ct/pelican-wings.sh index 3f0f6d374..2e1df598e 100644 --- a/ct/pelican-wings.sh +++ b/ct/pelican-wings.sh @@ -35,7 +35,7 @@ function update_script() { msg_info "Updating ${APP} to v${RELEASE}" rm /usr/local/bin/wings -curl -fsSL "https://github.com/pelican-dev/wings/releases/download/v${RELEASE}/wings_linux_amd64" -o "/usr/local/bin/wings" + curl -fsSL "https://github.com/pelican-dev/wings/releases/download/v${RELEASE}/wings_linux_amd64" -o "/usr/local/bin/wings" chmod u+x /usr/local/bin/wings echo "${RELEASE}" >/opt/${APP}_version.txt msg_ok "Updated $APP to v${RELEASE}" @@ -43,7 +43,7 @@ curl -fsSL "https://github.com/pelican-dev/wings/releases/download/v${RELEASE}/w msg_info "Starting Service" systemctl start wings msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" else msg_ok "No update required. ${APP} is already at v${RELEASE}" fi @@ -55,4 +55,4 @@ build_container description msg_ok "Completed Successfully!\n" -echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}" \ No newline at end of file +echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}" diff --git a/ct/pf2etools.sh b/ct/pf2etools.sh index f7f0d342d..79f56998c 100644 --- a/ct/pf2etools.sh +++ b/ct/pf2etools.sh @@ -44,7 +44,7 @@ function update_script() { chown -R www-data: "/opt/${APP}" chmod -R 755 "/opt/${APP}" msg_ok "Updated ${APP}" - msg_ok "Updated successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/photoprism.sh b/ct/photoprism.sh index 27fd2fe0c..cfb30dba8 100644 --- a/ct/photoprism.sh +++ b/ct/photoprism.sh @@ -48,7 +48,7 @@ function update_script() { msg_info "Starting PhotoPrism" systemctl start photoprism msg_ok "Started PhotoPrism" - msg_ok "Update Successful" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/phpipam.sh b/ct/phpipam.sh index 7e0e4c375..a639e32e2 100644 --- a/ct/phpipam.sh +++ b/ct/phpipam.sh @@ -44,7 +44,7 @@ function update_script() { msg_info "Cleaning up" rm -r /opt/phpipam-backup msg_ok "Cleaned" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/pialert.sh b/ct/pialert.sh index f41707b37..7d2f94231 100644 --- a/ct/pialert.sh +++ b/ct/pialert.sh @@ -20,16 +20,17 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources - if [[ ! -d /opt/pialert ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - bash -c "$(curl -fsSL https://github.com/leiweibau/Pi.Alert/raw/main/install/pialert_update.sh)" -s --lxc - msg_ok "Updated $APP" + header_info + check_container_storage + check_container_resources + if [[ ! -d /opt/pialert ]]; then + msg_error "No ${APP} Installation Found!" exit + fi + bash -c "$(curl -fsSL https://github.com/leiweibau/Pi.Alert/raw/main/install/pialert_update.sh)" -s --lxc + msg_ok "Updated $APP" + msg_ok "Updated successfully!" + exit } start diff --git a/ct/pihole.sh b/ct/pihole.sh index 0a461f724..c635abfaa 100644 --- a/ct/pihole.sh +++ b/ct/pihole.sh @@ -11,7 +11,7 @@ var_cpu="${var_cpu:-1}" var_ram="${var_ram:-512}" var_disk="${var_disk:-2}" var_os="${var_os:-debian}" -var_version="${var_version:-13}" +var_version="${var_version:-12}" var_unprivileged="${var_unprivileged:-1}" header_info "$APP" @@ -27,12 +27,13 @@ function update_script() { msg_error "No ${APP} Installation Found!" exit fi - msg_info "Updating ${APP}" + msg_info "Updating PiHole" set +e $STD apt update $STD apt upgrade -y /usr/local/bin/pihole -up - msg_ok "Updated ${APP}" + msg_ok "Updated PiHole" + msg_ok "Updated successfully!" exit } diff --git a/ct/planka.sh b/ct/planka.sh index 04f344acd..f5a6b7d60 100644 --- a/ct/planka.sh +++ b/ct/planka.sh @@ -29,9 +29,9 @@ function update_script() { exit fi if check_for_gh_release "planka" "plankanban/planka"; then - msg_info "Stopping $APP" + msg_info "Stopping Service" systemctl stop planka - msg_ok "Stopped $APP" + msg_info "Stopped Service" msg_info "Backing up data" BK="/opt/planka-backup" @@ -61,10 +61,10 @@ function update_script() { rm -rf "$BK" msg_ok "Restored data" - msg_info "Starting $APP" + msg_info "Starting Service" systemctl start planka - msg_ok "Started $APP" - msg_ok "Update Successful" + msg_ok "Started Service" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/plant-it.sh b/ct/plant-it.sh index 879076cf2..4610fd41f 100644 --- a/ct/plant-it.sh +++ b/ct/plant-it.sh @@ -28,19 +28,19 @@ function update_script() { exit fi if check_for_gh_release "plant-it" "MDeLuise/plant-it"; then - msg_info "Stopping $APP" + msg_info "Stopping Service" systemctl stop plant-it - msg_ok "Stopped $APP" + msg_info "Stopped Service" USE_ORIGINAL_FILENAME="true" fetch_and_deploy_gh_release "plant-it" "MDeLuise/plant-it" "singlefile" "0.10.0" "/opt/plant-it/backend" "server.jar" fetch_and_deploy_gh_release "plant-it-front" "MDeLuise/plant-it" "prebuild" "0.10.0" "/opt/plant-it/frontend" "client.tar.gz" msg_warn "Application is updated to latest Web version (v0.10.0). There will be no more updates available." msg_warn "Please read: https://github.com/MDeLuise/plant-it/releases/tag/1.0.0" - msg_info "Starting $APP" + msg_info "Starting Service" systemctl start plant-it - msg_ok "Started $APP" - msg_ok "Update Successful" + msg_ok "Started Service" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/plex.sh b/ct/plex.sh index 3879839f1..3ad82df74 100644 --- a/ct/plex.sh +++ b/ct/plex.sh @@ -36,11 +36,13 @@ function update_script() { $STD apt update $STD apt -y upgrade msg_ok "Updated ${APP} LXC" + msg_ok "Updated successfully!" exit fi if [ "$UPD" == "2" ]; then set +e bash -c "$(curl -fsSL https://raw.githubusercontent.com/mrworf/plexupdate/master/extras/installer.sh)" + msg_ok "Updated successfully!" exit fi } diff --git a/ct/pocketbase.sh b/ct/pocketbase.sh index 1e4037063..274431142 100644 --- a/ct/pocketbase.sh +++ b/ct/pocketbase.sh @@ -40,7 +40,7 @@ function update_script() { msg_info "Starting Service" systemctl start pocketbase msg_ok "Started Service" - msg_ok "Update Successful" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/pocketid.sh b/ct/pocketid.sh index 6f582af6c..b56bbbf9f 100755 --- a/ct/pocketid.sh +++ b/ct/pocketid.sh @@ -67,10 +67,10 @@ function update_script() { fetch_and_deploy_gh_release "pocket-id" "pocket-id/pocket-id" "singlefile" "latest" "/opt/pocket-id/" "pocket-id-linux-amd64" mv /opt/env /opt/pocket-id/.env - msg_info "Starting $APP" + msg_info "Starting Service" systemctl start pocketid - msg_ok "Started $APP" - msg_ok "Update Successful" + msg_ok "Started Service" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/podman-homeassistant.sh b/ct/podman-homeassistant.sh index 48e56e0f8..888250441 100644 --- a/ct/podman-homeassistant.sh +++ b/ct/podman-homeassistant.sh @@ -38,7 +38,7 @@ function update_script() { msg_info "Updating ${APP} LXC" $STD apt update $STD apt -y upgrade - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" msg_info "Updating All Containers\n" CONTAINER_LIST="${1:-$(podman ps -q)}" diff --git a/ct/podman.sh b/ct/podman.sh index c29029b03..6e35f6901 100644 --- a/ct/podman.sh +++ b/ct/podman.sh @@ -30,7 +30,7 @@ function update_script() { msg_info "Updating ${APP} LXC" $STD apt update $STD apt -y upgrade - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" exit } @@ -39,4 +39,4 @@ build_container description msg_ok "Completed Successfully!\n" -echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}" \ No newline at end of file +echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}" diff --git a/ct/postgresql.sh b/ct/postgresql.sh index 513cb48c5..09ffeb203 100644 --- a/ct/postgresql.sh +++ b/ct/postgresql.sh @@ -30,7 +30,7 @@ function update_script() { msg_info "Updating ${APP} LXC" $STD apt update $STD apt -y upgrade - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" exit } @@ -41,4 +41,4 @@ 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 IP:${CL}" -echo -e "${TAB}${GATEWAY}${BGN}${IP}:5432${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}${IP}:5432${CL}" diff --git a/ct/privatebin.sh b/ct/privatebin.sh index 35e4a1833..574797a10 100644 --- a/ct/privatebin.sh +++ b/ct/privatebin.sh @@ -42,7 +42,7 @@ function update_script() { chmod -R 0755 /opt/privatebin/data} systemctl reload nginx php8.2-fpm msg_ok "Configured ${APP}" - msg_ok "Successfully updated" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/projectsend.sh b/ct/projectsend.sh index d3af77c9c..81435e41d 100644 --- a/ct/projectsend.sh +++ b/ct/projectsend.sh @@ -48,7 +48,7 @@ function update_script() { systemctl start apache2 msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/prometheus-alertmanager.sh b/ct/prometheus-alertmanager.sh index 1e98d6586..8f111cc3b 100755 --- a/ct/prometheus-alertmanager.sh +++ b/ct/prometheus-alertmanager.sh @@ -37,7 +37,7 @@ function update_script() { msg_info "Starting Service" systemctl start prometheus-alertmanager msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/prometheus-blackbox-exporter.sh b/ct/prometheus-blackbox-exporter.sh index 55295c1d9..4a7353493 100644 --- a/ct/prometheus-blackbox-exporter.sh +++ b/ct/prometheus-blackbox-exporter.sh @@ -43,11 +43,11 @@ function update_script() { cp -r /opt/blackbox.yml /opt/blackbox-exporter rm -f /opt/blackbox.yml msg_ok "Backup restored" - + msg_info "Starting Service" systemctl start blackbox-exporter msg_ok "Started Service" - msg_ok "Update Successfully!" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/prometheus-paperless-ngx-exporter.sh b/ct/prometheus-paperless-ngx-exporter.sh index b2a022831..9925a1e63 100755 --- a/ct/prometheus-paperless-ngx-exporter.sh +++ b/ct/prometheus-paperless-ngx-exporter.sh @@ -37,7 +37,7 @@ function update_script() { msg_info "Starting Service" systemctl start prometheus-paperless-ngx-exporter msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/prometheus-pve-exporter.sh b/ct/prometheus-pve-exporter.sh index 906974de4..dd8728608 100644 --- a/ct/prometheus-pve-exporter.sh +++ b/ct/prometheus-pve-exporter.sh @@ -25,7 +25,7 @@ function update_script() { check_container_resources if [[ ! -f /etc/systemd/system/prometheus-pve-exporter.service ]]; then msg_error "No ${APP} Installation Found!" - exit 1 + exit fi msg_info "Stopping Service" @@ -81,7 +81,7 @@ EOF systemctl start prometheus-pve-exporter msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" exit 0 } diff --git a/ct/prometheus.sh b/ct/prometheus.sh index 2b32edd50..2883e0e52 100644 --- a/ct/prometheus.sh +++ b/ct/prometheus.sh @@ -39,7 +39,7 @@ function update_script() { systemctl start prometheus msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/prowlarr.sh b/ct/prowlarr.sh index 72da3fe43..6c72c061c 100644 --- a/ct/prowlarr.sh +++ b/ct/prowlarr.sh @@ -39,7 +39,7 @@ function update_script() { msg_info "Starting Service" systemctl start prowlarr msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/proxmox-backup-server.sh b/ct/proxmox-backup-server.sh index d096a811f..94322dce6 100644 --- a/ct/proxmox-backup-server.sh +++ b/ct/proxmox-backup-server.sh @@ -20,18 +20,19 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources - if [[ ! -e /usr/sbin/proxmox-backup-manager ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - msg_info "Updating $APP LXC" - $STD apt update - $STD apt -y upgrade - msg_ok "Updated $APP LXC" + header_info + check_container_storage + check_container_resources + if [[ ! -e /usr/sbin/proxmox-backup-manager ]]; then + msg_error "No ${APP} Installation Found!" exit + fi + msg_info "Updating $APP LXC" + $STD apt update + $STD apt -y upgrade + msg_ok "Updated $APP LXC" + msg_ok "Updated successfully!" + exit } start @@ -41,4 +42,4 @@ 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}:8007${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}https://${IP}:8007${CL}" diff --git a/ct/proxmox-datacenter-manager.sh b/ct/proxmox-datacenter-manager.sh index dc3728f13..6acadcd35 100644 --- a/ct/proxmox-datacenter-manager.sh +++ b/ct/proxmox-datacenter-manager.sh @@ -20,28 +20,29 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources - if [[ ! -e /usr/sbin/proxmox-datacenter-manager-admin ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - - if grep -q 'Debian GNU/Linux 12' /etc/os-release && [ -f /etc/apt/sources.list.d/proxmox-release-bookworm.list ] && [ -f /etc/apt/sources.list.d/pdm-test.list ]; then - msg_info "Updating outdated outdated source formats" - echo "deb [signed-by=/usr/share/keyrings/proxmox-archive-keyring.gpg] http://download.proxmox.com/debian/pdm bookworm pdm-test" > /etc/apt/sources.list.d/pdm-test.list - curl -fsSL https://enterprise.proxmox.com/debian/proxmox-archive-keyring-trixie.gpg -o /usr/share/keyrings/proxmox-archive-keyring.gpg - rm -f /etc/apt/keyrings/proxmox-release-bookworm.gpg /etc/apt/sources.list.d/proxmox-release-bookworm.list - $STD apt update - msg_ok "Updated old sources" - fi - - msg_info "Updating $APP LXC" - $STD apt update - $STD apt -y upgrade - msg_ok "Updated $APP LXC" + header_info + check_container_storage + check_container_resources + if [[ ! -e /usr/sbin/proxmox-datacenter-manager-admin ]]; then + msg_error "No ${APP} Installation Found!" exit + fi + + if grep -q 'Debian GNU/Linux 12' /etc/os-release && [ -f /etc/apt/sources.list.d/proxmox-release-bookworm.list ] && [ -f /etc/apt/sources.list.d/pdm-test.list ]; then + msg_info "Updating outdated outdated source formats" + echo "deb [signed-by=/usr/share/keyrings/proxmox-archive-keyring.gpg] http://download.proxmox.com/debian/pdm bookworm pdm-test" >/etc/apt/sources.list.d/pdm-test.list + curl -fsSL https://enterprise.proxmox.com/debian/proxmox-archive-keyring-trixie.gpg -o /usr/share/keyrings/proxmox-archive-keyring.gpg + rm -f /etc/apt/keyrings/proxmox-release-bookworm.gpg /etc/apt/sources.list.d/proxmox-release-bookworm.list + $STD apt update + msg_ok "Updated old sources" + fi + + msg_info "Updating $APP LXC" + $STD apt update + $STD apt -y upgrade + msg_ok "Updated $APP LXC" + msg_ok "Updated successfully!" + exit } start diff --git a/ct/proxmox-mail-gateway.sh b/ct/proxmox-mail-gateway.sh index e86169eec..c8bd56772 100644 --- a/ct/proxmox-mail-gateway.sh +++ b/ct/proxmox-mail-gateway.sh @@ -31,6 +31,7 @@ function update_script() { $STD apt update $STD apt -y upgrade msg_ok "Updated ${APP}" + msg_ok "Updated successfully!" exit } @@ -41,4 +42,4 @@ 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}:8006/${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}https://${IP}:8006/${CL}" diff --git a/ct/ps5-mqtt.sh b/ct/ps5-mqtt.sh index f9a45d1f7..8ef0fefd6 100644 --- a/ct/ps5-mqtt.sh +++ b/ct/ps5-mqtt.sh @@ -43,7 +43,7 @@ function update_script() { msg_info "Starting service" systemctl start ps5-mqtt msg_ok "Started service" - msg_ok "Updated successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/pterodactyl-panel.sh b/ct/pterodactyl-panel.sh index ce04963f0..6bf9eefa0 100644 --- a/ct/pterodactyl-panel.sh +++ b/ct/pterodactyl-panel.sh @@ -81,7 +81,7 @@ EOF msg_info "Cleaning up" rm -rf "/opt/pterodactyl-panel/panel.tar.gz" msg_ok "Cleaned" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" else msg_ok "No update required. ${APP} is already at v${RELEASE}" fi diff --git a/ct/pterodactyl-wings.sh b/ct/pterodactyl-wings.sh index 2dbcee922..86b481f74 100644 --- a/ct/pterodactyl-wings.sh +++ b/ct/pterodactyl-wings.sh @@ -43,7 +43,7 @@ function update_script() { msg_info "Starting Service" systemctl start wings msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" else msg_ok "No update required. ${APP} is already at v${RELEASE}" fi diff --git a/ct/pulse.sh b/ct/pulse.sh index e99b9d890..8810840ed 100644 --- a/ct/pulse.sh +++ b/ct/pulse.sh @@ -57,7 +57,7 @@ function update_script() { msg_info "Starting Services" systemctl start pulse msg_ok "Started Services" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/pve-scripts-local.sh b/ct/pve-scripts-local.sh index 904484190..9747b6cab 100644 --- a/ct/pve-scripts-local.sh +++ b/ct/pve-scripts-local.sh @@ -60,7 +60,7 @@ function update_script() { msg_info "Starting Services" systemctl start pvescriptslocal msg_ok "Started Services" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/qbittorrent.sh b/ct/qbittorrent.sh index 6f03cedd6..85bf5c007 100644 --- a/ct/qbittorrent.sh +++ b/ct/qbittorrent.sh @@ -43,7 +43,7 @@ function update_script() { msg_info "Starting Service" systemctl start qbittorrent-nox msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/rabbitmq.sh b/ct/rabbitmq.sh index bde470adc..1c6734e3c 100644 --- a/ct/rabbitmq.sh +++ b/ct/rabbitmq.sh @@ -47,12 +47,12 @@ EOF msg_info "Updating..." $STD apt install --only-upgrade rabbitmq-server - msg_ok "Update Successfully" + msg_ok "Updated successfully!" msg_info "Starting Service" systemctl start rabbitmq-server msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" exit } diff --git a/ct/radarr.sh b/ct/radarr.sh index ec0ec00f7..f5ceb0451 100644 --- a/ct/radarr.sh +++ b/ct/radarr.sh @@ -41,7 +41,7 @@ function update_script() { msg_info "Starting Service" systemctl start radarr msg_ok "Started Service" - msg_ok "Updated successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/radicale.sh b/ct/radicale.sh index 559e2e613..400e61b34 100644 --- a/ct/radicale.sh +++ b/ct/radicale.sh @@ -20,25 +20,25 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources - if [[ ! -d /opt/radicale ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - - msg_info "Updating ${APP}" - python3 -m venv /opt/radicale - source /opt/radicale/bin/activate - python3 -m pip install --upgrade https://github.com/Kozea/Radicale/archive/master.tar.gz - msg_ok "Updated ${APP}" - - msg_info "Starting Service" - systemctl enable -q --now radicale - msg_ok "Started Service" - + header_info + check_container_storage + check_container_resources + if [[ ! -d /opt/radicale ]]; then + msg_error "No ${APP} Installation Found!" exit + fi + + msg_info "Updating ${APP}" + $STD python3 -m venv /opt/radicale + source /opt/radicale/bin/activate + $STD python3 -m pip install --upgrade https://github.com/Kozea/Radicale/archive/master.tar.gz + msg_ok "Updated ${APP}" + + msg_info "Starting Service" + systemctl enable -q --now radicale + msg_ok "Started Service" + msg_ok "Updated successfully!" + exit } start diff --git a/ct/rclone.sh b/ct/rclone.sh index 117a468ae..927c64f7f 100644 --- a/ct/rclone.sh +++ b/ct/rclone.sh @@ -38,7 +38,7 @@ function update_script() { msg_info "Starting Service" systemctl start rclone-web msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/rdtclient.sh b/ct/rdtclient.sh index 033d2693a..687f14945 100755 --- a/ct/rdtclient.sh +++ b/ct/rdtclient.sh @@ -51,7 +51,7 @@ function update_script() { msg_info "Cleaning Up" rm -rf /opt/rdtc-backup msg_ok "Cleaned" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/reactive-resume.sh b/ct/reactive-resume.sh index 521b8de02..68ea99299 100644 --- a/ct/reactive-resume.sh +++ b/ct/reactive-resume.sh @@ -66,6 +66,8 @@ function update_script() { $STD unzip "$brwsr_tmp" mv browserless-"$TAG"/ /opt/browserless cd /opt/browserless + $STD npm install typescript + $STD npm install esbuild $STD npm install rm -rf src/routes/{chrome,edge,firefox,webkit} $STD node_modules/playwright-core/cli.js install --with-deps chromium @@ -83,7 +85,7 @@ function update_script() { rm -f /tmp/minio.deb rm -f "$brwsr_tmp" msg_ok "Cleanup Completed" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/readarr.sh b/ct/readarr.sh index 2f59db1ec..8c4d0c1cd 100644 --- a/ct/readarr.sh +++ b/ct/readarr.sh @@ -20,18 +20,19 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources - if [[ ! -d /var/lib/readarr/ ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - msg_info "Updating $APP LXC" - $STD apt update - $STD apt -y upgrade - msg_ok "Updated $APP LXC" + header_info + check_container_storage + check_container_resources + if [[ ! -d /var/lib/readarr/ ]]; then + msg_error "No ${APP} Installation Found!" exit + fi + msg_info "Updating $APP LXC" + $STD apt update + $STD apt -y upgrade + msg_ok "Updated $APP LXC" + msg_ok "Updated successfully!" + exit } start diff --git a/ct/readeck.sh b/ct/readeck.sh index f76f4515f..1ad824ab0 100644 --- a/ct/readeck.sh +++ b/ct/readeck.sh @@ -27,15 +27,22 @@ function update_script() { msg_error "No ${APP} Installation Found!" exit fi - msg_info "Updating ${APP}" + msg_info "Stopping Service" + systemctl stop readeck + msg_ok "Stopped Service" + + msg_info "Updating Readeck" LATEST=$(curl -fsSL https://codeberg.org/readeck/readeck/releases/ | grep -oP '/releases/tag/\K\d+\.\d+\.\d+' | head -1) - systemctl stop readeck.service rm -rf /opt/readeck/readeck cd /opt/readeck curl -fsSL "https://codeberg.org/readeck/readeck/releases/download/${LATEST}/readeck-${LATEST}-linux-amd64" -o "readeck" chmod a+x readeck - systemctl start readeck.service - msg_ok "Updated ${APP}" + msg_ok "Updated Readeck" + + msg_info "Starting Service" + systemctl start readeck + msg_ok "Started Service" + msg_ok "Updated successfully!" exit } diff --git a/ct/recyclarr.sh b/ct/recyclarr.sh index ef090f9f4..b0d9d7ea7 100644 --- a/ct/recyclarr.sh +++ b/ct/recyclarr.sh @@ -38,7 +38,7 @@ function update_script() { msg_info "Starting Service" systemctl start recyclarr msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/redis.sh b/ct/redis.sh index e69e50105..25b4bdfa8 100644 --- a/ct/redis.sh +++ b/ct/redis.sh @@ -20,15 +20,19 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources - if [[ ! -f /lib/systemd/system/redis-server.service ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - msg_error "Currently we don't provide an update function for this ${APP}." + header_info + check_container_storage + check_container_resources + if [[ ! -f /lib/systemd/system/redis-server.service ]]; then + msg_error "No ${APP} Installation Found!" exit + fi + msg_info "Updating $APP LXC" + $STD apt update + $STD apt -y upgrade + msg_ok "Updated $APP LXC" + msg_ok "Updated successfully!" + exit } start diff --git a/ct/reitti.sh b/ct/reitti.sh new file mode 100644 index 000000000..9407e7b7f --- /dev/null +++ b/ct/reitti.sh @@ -0,0 +1,68 @@ +#!/usr/bin/env bash +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/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/dedicatedcode/reitti + +APP="Reitti" +var_tags="${var_tags:-location-tracker}" +var_cpu="${var_cpu:-2}" +var_ram="${var_ram:-4096}" +var_disk="${var_disk:-15}" +var_os="${var_os:-debian}" +var_version="${var_version:-13}" +var_unprivileged="${var_unprivileged:-1}" + +header_info "$APP" +variables +color +catch_errors + +function update_script() { + header_info + check_container_storage + check_container_resources + if [[ ! -f /opt/reitti/reitti.jar ]]; then + msg_error "No ${APP} Installation Found!" + exit + fi + if check_for_gh_release "reitti" "dedicatedcode/reitti"; then + msg_info "Stopping Service" + systemctl stop reitti + msg_ok "Stopped Service" + + rm -f /opt/reitti/reitti.jar + USE_ORIGINAL_FILENAME="true" fetch_and_deploy_gh_release "reitti" "dedicatedcode/reitti" "singlefile" "latest" "/opt/reitti" "reitti-app.jar" + mv /opt/reitti/reitti-*.jar /opt/reitti/reitti.jar + + msg_info "Starting Service" + systemctl start reitti + msg_ok "Started Service" + msg_ok "Updated successfully!" + fi + if check_for_gh_release "photon" "komoot/photon"; then + msg_info "Stopping Service" + systemctl stop photon + msg_ok "Stopped Service" + + rm -f /opt/photon/photon.jar + USE_ORIGINAL_FILENAME="true" fetch_and_deploy_gh_release "photon" "komoot/photon" "singlefile" "latest" "/opt/photon" "photon-0*.jar" + mv /opt/photon/photon-*.jar /opt/photon/photon.jar + + msg_info "Starting Service" + systemctl start photon + msg_ok "Started Service" + msg_ok "Updated successfully!" + fi + exit +} + +start +build_container +description + +msg_ok "Completed Successfully!\n" +echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}" +echo -e "${INFO}${YW} Access it using the following URL:${CL}" +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8080${CL}" diff --git a/ct/resiliosync.sh b/ct/resiliosync.sh index 89ec1261f..d5cd511b4 100644 --- a/ct/resiliosync.sh +++ b/ct/resiliosync.sh @@ -30,7 +30,7 @@ function update_script() { msg_info "Updating ${APP} LXC" $STD apt update $STD apt -y upgrade - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" exit } diff --git a/ct/revealjs.sh b/ct/revealjs.sh index 9c38f799b..7cd03ead5 100644 --- a/ct/revealjs.sh +++ b/ct/revealjs.sh @@ -29,9 +29,9 @@ function update_script() { fi if check_for_gh_release "revealjs" "hakimel/reveal.js"; then - msg_info "Stopping $APP" + msg_info "Stopping Service" systemctl stop revealjs - msg_ok "Stopped $APP" + msg_info "Stopped Service" cp /opt/revealjs/index.html /opt fetch_and_deploy_gh_release "revealjs" "hakimel/reveal.js" "tarball" @@ -43,14 +43,14 @@ function update_script() { sed -i '25s/localhost/0.0.0.0/g' /opt/revealjs/gulpfile.js msg_ok "Updated $APP" - msg_info "Starting $APP" + msg_info "Starting Service" systemctl start revealjs - msg_ok "Started $APP" + msg_ok "Started Service" msg_info "Cleaning Up" rm -f /opt/index.html msg_ok "Cleanup Completed" - msg_ok "Update Successful" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/runtipi.sh b/ct/runtipi.sh index 7c95519af..55e31ccf6 100644 --- a/ct/runtipi.sh +++ b/ct/runtipi.sh @@ -20,15 +20,16 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources - if [[ ! -d /opt/runtipi ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - cd /opt/runtipi && ./runtipi-cli update latest + header_info + check_container_storage + check_container_resources + if [[ ! -d /opt/runtipi ]]; then + msg_error "No ${APP} Installation Found!" exit + fi + cd /opt/runtipi && ./runtipi-cli update latest + msg_ok "Updated successfully!" + exit } start diff --git a/ct/rustdeskserver.sh b/ct/rustdeskserver.sh index e705e8d97..58a959d64 100644 --- a/ct/rustdeskserver.sh +++ b/ct/rustdeskserver.sh @@ -32,13 +32,13 @@ function update_script() { RELEASE=$(curl -fsSL https://api.github.com/repos/rustdesk/rustdesk-server/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }') APIRELEASE=$(curl -fsSL https://api.github.com/repos/lejianwen/rustdesk-api/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }') if [[ "${RELEASE}" != "$(cat ~/.rustdesk-hbbr)" ]] || [[ "${APIRELEASE}" != "$(cat ~/.rustdesk-api)" ]] || [[ ! -f ~/.rustdesk-hbbr ]] || [[ ! -f ~/.rustdesk-api ]]; then - msg_info "Stopping $APP" + msg_info "Stopping Service" systemctl stop rustdesk-hbbr systemctl stop rustdesk-hbbs if [[ -f /lib/systemd/system/rustdesk-api.service ]]; then systemctl stop rustdesk-api fi - msg_ok "Stopped $APP" + msg_info "Stopped Service" fetch_and_deploy_gh_release "rustdesk-hbbr" "rustdesk/rustdesk-server" "binary" "latest" "/opt/rustdesk" "rustdesk-server-hbbr*amd64.deb" fetch_and_deploy_gh_release "rustdesk-hbbs" "rustdesk/rustdesk-server" "binary" "latest" "/opt/rustdesk" "rustdesk-server-hbbs*amd64.deb" @@ -49,7 +49,7 @@ function update_script() { systemctl start -q rustdesk-* --all msg_ok "Services started" - msg_ok "Update Successful" + msg_ok "Updated successfully!" else msg_ok "No update required. ${APP} is already at v${RELEASE}" fi diff --git a/ct/sabnzbd.sh b/ct/sabnzbd.sh index 41956a284..b69bf77a5 100644 --- a/ct/sabnzbd.sh +++ b/ct/sabnzbd.sh @@ -24,40 +24,37 @@ function update_script() { check_container_storage check_container_resources + if par2 --version | grep -q "par2cmdline-turbo"; then + fetch_and_deploy_gh_release "par2cmdline-turbo" "animetosho/par2cmdline-turbo" "prebuild" "latest" "/usr/bin/" "*-linux-amd64.zip" + fi + if [[ ! -d /opt/sabnzbd ]]; then msg_error "No ${APP} Installation Found!" exit fi - setup_uv - RELEASE=$(curl -fsSL https://api.github.com/repos/sabnzbd/sabnzbd/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }') - if [[ -f /opt/${APP}_version.txt ]] && [[ "${RELEASE}" == "$(cat /opt/${APP}_version.txt)" ]]; then - msg_ok "No update required. ${APP} is already at ${RELEASE}" - exit - fi - setup_uv - msg_info "Updating $APP to ${RELEASE}" - systemctl stop sabnzbd - cp -r /opt/sabnzbd /opt/sabnzbd_backup_$(date +%s) - temp_file=$(mktemp) - curl -fsSL "https://github.com/sabnzbd/sabnzbd/releases/download/${RELEASE}/SABnzbd-${RELEASE}-src.tar.gz" -o "$temp_file" - tar -xzf "$temp_file" -C /opt/sabnzbd --strip-components=1 - rm -f "$temp_file" - if [[ ! -d /opt/sabnzbd/venv ]]; then - msg_info "Migrating SABnzbd to uv virtual environment" - $STD uv venv /opt/sabnzbd/venv - msg_ok "Created uv venv at /opt/sabnzbd/venv" + if check_for_gh_release "sabnzbd-org" "sabnzbd/sabnzbd"; then + PYTHON_VERSION="3.13" setup_uv + systemctl stop sabnzbd + cp -r /opt/sabnzbd /opt/sabnzbd_backup_$(date +%s) + fetch_and_deploy_gh_release "sabnzbd-org" "sabnzbd/sabnzbd" "prebuild" "latest" "/opt/sabnzbd" "SABnzbd-*-src.tar.gz" - if grep -q "ExecStart=python3 SABnzbd.py" /etc/systemd/system/sabnzbd.service; then - sed -i "s|ExecStart=python3 SABnzbd.py|ExecStart=/opt/sabnzbd/venv/bin/python SABnzbd.py|" /etc/systemd/system/sabnzbd.service - systemctl daemon-reload - msg_ok "Updated SABnzbd service to use uv venv" + if [[ ! -d /opt/sabnzbd/venv ]]; then + msg_info "Migrating SABnzbd to uv virtual environment" + $STD uv venv /opt/sabnzbd/venv + msg_ok "Created uv venv at /opt/sabnzbd/venv" + + if grep -q "ExecStart=python3 SABnzbd.py" /etc/systemd/system/sabnzbd.service; then + sed -i "s|ExecStart=python3 SABnzbd.py|ExecStart=/opt/sabnzbd/venv/bin/python SABnzbd.py|" /etc/systemd/system/sabnzbd.service + systemctl daemon-reload + msg_ok "Updated SABnzbd service to use uv venv" + fi fi + $STD uv pip install --upgrade pip --python=/opt/sabnzbd/venv/bin/python + $STD uv pip install -r /opt/sabnzbd/requirements.txt --python=/opt/sabnzbd/venv/bin/python + + systemctl start sabnzbd + msg_ok "Updated successfully!" fi - $STD uv pip install --upgrade pip --python=/opt/sabnzbd/venv/bin/python - $STD uv pip install -r /opt/sabnzbd/requirements.txt --python=/opt/sabnzbd/venv/bin/python - echo "${RELEASE}" >/opt/${APP}_version.txt - systemctl start sabnzbd - msg_ok "Updated ${APP} to ${RELEASE}" exit } diff --git a/ct/salt.sh b/ct/salt.sh index f6acc9baa..7f0b45fe7 100644 --- a/ct/salt.sh +++ b/ct/salt.sh @@ -36,10 +36,11 @@ function update_script() { $STD apt update $STD apt upgrade -y echo "${RELEASE}" >/~.salt - msg_ok "Updated ${APP} to ${RELEASE}" + msg_ok "Updated successfully!" else msg_ok "${APP} is already up to date (${RELEASE})" fi + exit } start diff --git a/ct/scraparr.sh b/ct/scraparr.sh index be7707f51..9d845fec6 100644 --- a/ct/scraparr.sh +++ b/ct/scraparr.sh @@ -48,7 +48,7 @@ function update_script() { msg_info "Starting Services" systemctl start scraparr msg_ok "Services Started" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/seelf.sh b/ct/seelf.sh index c991c77d5..d322d22d1 100644 --- a/ct/seelf.sh +++ b/ct/seelf.sh @@ -29,19 +29,19 @@ function update_script() { exit fi if check_for_gh_release "seelf" "YuukanOO/seelf"; then - msg_info "Stopping $APP" + msg_info "Stopping Service" systemctl stop seelf - msg_ok "Stopped $APP" + msg_info "Stopped Service" msg_info "Updating $APP" cd /opt/seelf $STD make build msg_ok "Updated $APP" - msg_info "Starting $APP" + msg_info "Starting Service" systemctl start seelf - msg_ok "Started $APP" - msg_ok "Update Successfully" + msg_ok "Started Service" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/semaphore.sh b/ct/semaphore.sh index 2c17515ab..c3d554967 100644 --- a/ct/semaphore.sh +++ b/ct/semaphore.sh @@ -38,7 +38,7 @@ function update_script() { msg_info "Starting Service" systemctl start semaphore msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/sftpgo.sh b/ct/sftpgo.sh index f8d5540a9..743b2fa74 100644 --- a/ct/sftpgo.sh +++ b/ct/sftpgo.sh @@ -20,18 +20,19 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources - if [[ ! -d /var ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - msg_info "Updating $APP LXC" - $STD apt update - $STD apt -y upgrade - msg_ok "Updated $APP LXC" + header_info + check_container_storage + check_container_resources + if [[ ! -d /var ]]; then + msg_error "No ${APP} Installation Found!" exit + fi + msg_info "Updating $APP LXC" + $STD apt update + $STD apt -y upgrade + msg_ok "Updated $APP LXC" + msg_ok "Updated successfully!" + exit } start diff --git a/ct/shinobi.sh b/ct/shinobi.sh index 03078cf46..5ae9f34c7 100644 --- a/ct/shinobi.sh +++ b/ct/shinobi.sh @@ -27,13 +27,14 @@ function update_script() { msg_error "No ${APP} Installation Found!" exit fi - msg_info "Updating Shinobi LXC" + msg_info "Updating Shinobi" cd /opt/Shinobi - sh UPDATE.sh - pm2 flush - pm2 restart camera - pm2 restart cron - msg_ok "Updated Shinobi LXC" + $STD sh UPDATE.sh + $STD pm2 flush + $STD pm2 restart camera + $STD pm2 restart cron + msg_ok "Updated Shinobi" + msg_ok "Updated successfully!" exit } diff --git a/ct/signoz.sh b/ct/signoz.sh index 6733c8716..1d92246c2 100644 --- a/ct/signoz.sh +++ b/ct/signoz.sh @@ -48,7 +48,7 @@ function update_script() { systemctl start signoz-otel-collector systemctl start signoz msg_ok "Started Services" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/silverbullet.sh b/ct/silverbullet.sh index 737c94eec..0415d5421 100644 --- a/ct/silverbullet.sh +++ b/ct/silverbullet.sh @@ -37,7 +37,7 @@ function update_script() { msg_info "Starting Service" systemctl start silverbullet msg_ok "Started Service" - msg_ok "Update Successful" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/slskd.sh b/ct/slskd.sh index 89c45d298..174d5f388 100644 --- a/ct/slskd.sh +++ b/ct/slskd.sh @@ -31,9 +31,9 @@ function update_script() { RELEASE=$(curl -s https://api.github.com/repos/slskd/slskd/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }') if [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]] || [[ ! -f /opt/${APP}_version.txt ]]; then - msg_info "Stopping $APP" + msg_info "Stopping Service" systemctl stop slskd soularr.timer soularr.service - msg_ok "Stopped $APP" + msg_info "Stopped Service" msg_info "Updating $APP to v${RELEASE}" tmp_file=$(mktemp) @@ -42,9 +42,9 @@ function update_script() { echo "${RELEASE}" >/opt/${APP}_version.txt msg_ok "Updated $APP to v${RELEASE}" - msg_info "Starting $APP" + msg_info "Starting Service" systemctl start slskd - msg_ok "Started $APP" + msg_ok "Started Service" rm -rf $tmp_file else msg_ok "No ${APP} update required. ${APP} is already at v${RELEASE}" diff --git a/ct/smokeping.sh b/ct/smokeping.sh index b49f0b5dd..bd1c8da6b 100644 --- a/ct/smokeping.sh +++ b/ct/smokeping.sh @@ -31,7 +31,7 @@ function update_script() { msg_info "Updating ${APP}" $STD apt update $STD apt -y upgrade - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" exit } diff --git a/ct/snipeit.sh b/ct/snipeit.sh index f00f65dc3..3f25fa32e 100644 --- a/ct/snipeit.sh +++ b/ct/snipeit.sh @@ -68,7 +68,7 @@ function update_script() { msg_info "Starting Service" systemctl start nginx msg_ok "Started Service" - msg_ok "Update Successful" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/sonarqube.sh b/ct/sonarqube.sh index 50963fc25..aa8dee3ad 100644 --- a/ct/sonarqube.sh +++ b/ct/sonarqube.sh @@ -56,7 +56,7 @@ function update_script() { msg_info "Starting Service" systemctl start sonarqube msg_ok "Service started" - msg_ok "Updated Successfully!" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/sonarr.sh b/ct/sonarr.sh index 78e4f50e9..092d9d638 100644 --- a/ct/sonarr.sh +++ b/ct/sonarr.sh @@ -20,23 +20,29 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources - if [[ ! -d /var/lib/sonarr/ ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - msg_info "Updating $APP v4" - systemctl stop sonarr.service - curl -fsSL "https://services.sonarr.tv/v1/download/main/latest?version=4&os=linux&arch=x64" -o "SonarrV4.tar.gz" - tar -xzf SonarrV4.tar.gz - rm -rf /opt/Sonarr - mv Sonarr /opt - rm -rf SonarrV4.tar.gz - systemctl start sonarr.service - msg_ok "Updated $APP v4" + header_info + check_container_storage + check_container_resources + if [[ ! -d /var/lib/sonarr/ ]]; then + msg_error "No ${APP} Installation Found!" exit + fi + msg_info "Stopping Service" + systemctl stop sonarr + msg_ok "Stopped Service" + + msg_info "Updating Sonarr" + curl -fsSL "https://services.sonarr.tv/v1/download/main/latest?version=4&os=linux&arch=x64" -o "SonarrV4.tar.gz" + tar -xzf SonarrV4.tar.gz + rm -rf /opt/Sonarr + mv Sonarr /opt + rm -rf SonarrV4.tar.gz + msg_ok "Updated Sonarr" + msg_info "Starting Service" + systemctl start sonarr + msg_ok "Started Service" + msg_ok "Updated successfully!" + exit } start diff --git a/ct/spoolman.sh b/ct/spoolman.sh index 2698e0728..0ccc25ee4 100644 --- a/ct/spoolman.sh +++ b/ct/spoolman.sh @@ -54,7 +54,7 @@ function update_script() { rm -rf /opt/spoolman.zip msg_ok "Cleaned" - msg_ok "Updated Successfully!\n" + msg_ok "Updated successfully!" else msg_ok "No update required. ${APP} is already at ${RELEASE}" fi diff --git a/ct/sqlserver2022.sh b/ct/sqlserver2022.sh index e7533986f..eab09751a 100644 --- a/ct/sqlserver2022.sh +++ b/ct/sqlserver2022.sh @@ -30,7 +30,7 @@ function update_script() { msg_info "Updating ${APP} LXC" $STD apt update $STD apt -y upgrade - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" exit } diff --git a/ct/stirling-pdf.sh b/ct/stirling-pdf.sh index 96906dc1d..21e03c07b 100644 --- a/ct/stirling-pdf.sh +++ b/ct/stirling-pdf.sh @@ -55,7 +55,7 @@ function update_script() { msg_info "Starting Services" systemctl start stirlingpdf libreoffice-listener unoserver msg_ok "Started Services" - msg_ok "Update Successful" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/streamlink-webui.sh b/ct/streamlink-webui.sh index 9de0ec7af..b61b77d6a 100644 --- a/ct/streamlink-webui.sh +++ b/ct/streamlink-webui.sh @@ -30,9 +30,9 @@ function update_script() { fi if check_for_gh_release "streamlink-webui" "CrazyWolf13/streamlink-webui"; then - msg_info "Stopping $APP" + msg_info "Stopping Service" systemctl stop ${APP} - msg_ok "Stopped $APP" + msg_info "Stopped Service" rm -rf /opt/${APP} NODE_VERSION="22" NODE_MODULE="yarn" setup_nodejs @@ -49,10 +49,10 @@ function update_script() { chmod +x /opt/"${APP}"/start.sh msg_ok "Updated $APP" - msg_info "Starting $APP" + msg_info "Starting Service" systemctl start ${APP} - msg_ok "Started $APP" - msg_ok "Update Successful" + msg_ok "Started Service" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/stylus.sh b/ct/stylus.sh index 67a88c31c..5da355772 100644 --- a/ct/stylus.sh +++ b/ct/stylus.sh @@ -30,16 +30,16 @@ function update_script() { exit fi if check_for_gh_release "stylus" "mmastrac/stylus"; then - msg_info "Stopping $APP" + msg_info "Stopping Service" systemctl stop stylus - msg_ok "Stopped $APP" + msg_info "Stopped Service" fetch_and_deploy_gh_release "stylus" "mmastrac/stylus" "singlefile" "latest" "/usr/bin/" "*_linux_amd64" - msg_info "Starting $APP" + msg_info "Starting Service" systemctl start stylus - msg_ok "Started $APP" - msg_ok "Update Successful" + msg_ok "Started Service" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/suwayomiserver.sh b/ct/suwayomiserver.sh index bc6d654a4..9c771a711 100644 --- a/ct/suwayomiserver.sh +++ b/ct/suwayomiserver.sh @@ -32,16 +32,16 @@ function update_script() { if check_for_gh_release "suwayomi-server" "Suwayomi/Suwayomi-Server"; then JAVA_VERSION=21 setup_java - msg_info "Stopping $APP" + msg_info "Stopping Service" systemctl stop suwayomi-server - msg_ok "Stopped $APP" + msg_info "Stopped Service" fetch_and_deploy_gh_release "suwayomi-server" "Suwayomi/Suwayomi-Server" "binary" - msg_info "Starting $APP" + msg_info "Starting Service" systemctl start suwayomi-server - msg_ok "Started $APP" - msg_ok "Update Successful" + msg_ok "Started Service" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/swizzin.sh b/ct/swizzin.sh index 96a7cdfb1..46b86da39 100644 --- a/ct/swizzin.sh +++ b/ct/swizzin.sh @@ -29,7 +29,7 @@ function update_script() { fi msg_info "Running 'sudo box update' inside the container" $STD sudo box update - msg_ok "Update finished" + msg_ok "Updated successfully!" exit } diff --git a/ct/syncthing.sh b/ct/syncthing.sh index 38d733616..abf9392c0 100644 --- a/ct/syncthing.sh +++ b/ct/syncthing.sh @@ -30,7 +30,7 @@ function update_script() { msg_info "Updating ${APP} LXC" $STD apt update $STD apt -y upgrade - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" exit } diff --git a/ct/tandoor.sh b/ct/tandoor.sh index 5f9319ea3..0ffeaac02 100644 --- a/ct/tandoor.sh +++ b/ct/tandoor.sh @@ -74,7 +74,7 @@ EOF msg_info "Cleaning Up" rm -rf /opt/tandoor.bak msg_ok "Cleanup Completed" - msg_ok "Update Successfully!" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/tasmoadmin.sh b/ct/tasmoadmin.sh index e0c975560..58a703fb6 100644 --- a/ct/tasmoadmin.sh +++ b/ct/tasmoadmin.sh @@ -31,6 +31,7 @@ function update_script() { $STD apt update $STD apt -y upgrade msg_ok "Updated TasmoAdmin" + msg_ok "Updated successfully!" exit } diff --git a/ct/tasmocompiler.sh b/ct/tasmocompiler.sh index 64fc87bad..fb16107f1 100644 --- a/ct/tasmocompiler.sh +++ b/ct/tasmocompiler.sh @@ -55,7 +55,7 @@ function update_script() { msg_info "Cleaning up" rm -r "/opt/v${RELEASE}.tar.gz" msg_ok "Cleaned" - msg_ok "Update Successfully!" + msg_ok "Updated successfully!" else msg_ok "No update required. ${APP} is already at v${RELEASE}" fi diff --git a/ct/tautulli.sh b/ct/tautulli.sh index 28670f603..8e1178836 100644 --- a/ct/tautulli.sh +++ b/ct/tautulli.sh @@ -31,7 +31,7 @@ function update_script() { $STD apt update $STD apt upgrade -y msg_ok "Updated Tautulli" - msg_ok "Updated Successfully!" + msg_ok "Updated successfully!" exit } diff --git a/ct/tdarr.sh b/ct/tdarr.sh index aee753023..e6f01fac9 100644 --- a/ct/tdarr.sh +++ b/ct/tdarr.sh @@ -42,7 +42,7 @@ function update_script() { msg_info "Cleaning up" rm -rf /opt/tdarr/Tdarr_Updater.zip msg_ok "Cleaned up" - msg_ok "Updated Successfully!" + msg_ok "Updated successfully!" exit } diff --git a/ct/teamspeak-server.sh b/ct/teamspeak-server.sh index 16238d85a..93485c15a 100644 --- a/ct/teamspeak-server.sh +++ b/ct/teamspeak-server.sh @@ -45,7 +45,7 @@ function update_script() { msg_info "Starting Service" systemctl start teamspeak-server msg_ok "Started Service" - msg_ok "Updated Successfully!" + msg_ok "Updated successfully!" else msg_ok "Already up to date" fi diff --git a/ct/technitiumdns.sh b/ct/technitiumdns.sh index 1a0eeb89b..37cd88963 100644 --- a/ct/technitiumdns.sh +++ b/ct/technitiumdns.sh @@ -11,7 +11,7 @@ var_cpu="${var_cpu:-1}" var_ram="${var_ram:-512}" var_disk="${var_disk:-2}" var_os="${var_os:-debian}" -var_version="${var_version:-13}" +var_version="${var_version:-12}" var_unprivileged="${var_unprivileged:-1}" header_info "$APP" @@ -38,6 +38,7 @@ function update_script() { msg_info "Cleaning up" rm -f /opt/DnsServerPortable.tar.gz msg_ok "Cleaned up" + msg_ok "Updated successfully!" else msg_ok "No update required. Technitium DNS is already at v${RELEASE}." fi diff --git a/ct/teddycloud.sh b/ct/teddycloud.sh index 140ef7840..0dbd2dbbc 100644 --- a/ct/teddycloud.sh +++ b/ct/teddycloud.sh @@ -50,7 +50,7 @@ function update_script() { msg_info "Cleaning up" rm -rf /opt/teddycloud_bak msg_ok "Cleaned up" - msg_ok "Updated successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/telegraf.sh b/ct/telegraf.sh index 796f03ef5..2b4894bb8 100644 --- a/ct/telegraf.sh +++ b/ct/telegraf.sh @@ -40,7 +40,7 @@ function update_script() { msg_info "Starting Service" systemctl start telegraf msg_ok "Started Service" - msg_ok "Updated Successfully!" + msg_ok "Updated successfully!" exit } diff --git a/ct/the-lounge.sh b/ct/the-lounge.sh index d9e237b4f..dfb863a16 100644 --- a/ct/the-lounge.sh +++ b/ct/the-lounge.sh @@ -38,7 +38,7 @@ function update_script() { msg_info "Starting Service" systemctl start thelounge msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/threadfin.sh b/ct/threadfin.sh index 4f8f8fbb1..3a922a1dd 100644 --- a/ct/threadfin.sh +++ b/ct/threadfin.sh @@ -38,7 +38,7 @@ function update_script() { msg_info "Starting Service" systemctl start threadfin msg_ok "Started Service" - msg_ok "Updated Successfully!" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/tianji.sh b/ct/tianji.sh index 485ba3a24..e332d9d76 100644 --- a/ct/tianji.sh +++ b/ct/tianji.sh @@ -71,7 +71,7 @@ function update_script() { rm -rf /opt/tianji/website rm -rf /opt/tianji/reporter msg_ok "Cleaned" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/traccar.sh b/ct/traccar.sh index 970f0e0b2..c660cfd5c 100644 --- a/ct/traccar.sh +++ b/ct/traccar.sh @@ -62,7 +62,7 @@ function update_script() { $STD apt -y autoclean $STD apt -y clean msg_ok "Cleaned up" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/tracktor.sh b/ct/tracktor.sh index 3f43ae454..6656697a7 100644 --- a/ct/tracktor.sh +++ b/ct/tracktor.sh @@ -35,10 +35,33 @@ function update_script() { msg_info "Correcting Services" if [ -f /opt/tracktor/app/backend/.env ]; then - mv /opt/tracktor/app/backend/.env /opt/tracktor.env - echo 'AUTH_PIN=123456' >> /opt/tracktor.env - sed -i 's|^EnvironmentFile=.*|EnvironmentFile=/opt/tracktor.env|' /etc/systemd/system/tracktor.service - systemctl daemon-reload + mv /opt/tracktor/app/backend/.env /opt/tracktor.env + echo 'AUTH_PIN=123456' >>/opt/tracktor.env + sed -i 's|^EnvironmentFile=.*|EnvironmentFile=/opt/tracktor.env|' /etc/systemd/system/tracktor.service + systemctl daemon-reload + fi + if [ ! -d "/opt/tracktor-data/uploads" ]; then + mkdir -p /opt/tracktor-data/{uploads,logs} + EXISTING_AUTH_PIN=$(grep '^AUTH_PIN=' /opt/tracktor.env 2>/dev/null | cut -d'=' -f2) + AUTH_PIN=${EXISTING_AUTH_PIN:-123456} + cat </opt/tracktor.env +NODE_ENV=production +DB_PATH=/opt/tracktor-data/tracktor.db +UPLOADS_DIR="/opt/tracktor-data/uploads" +LOG_DIR="/opt/tracktor-data/logs" +# If server host is not set by default it will run on all interfaces - 0.0.0.0 +# SERVER_HOST="" +SERVER_PORT=3000 +# Set this if you want to secure your endpoints otherwise default will be "*" +CORS_ORIGINS="*" +# Set this if you are using backend and frontend separately. +# PUBLIC_API_BASE_URL="" +LOG_REQUESTS=true +LOG_LEVEL="info" +AUTH_PIN=${AUTH_PIN} +# PUBLIC_DEMO_MODE=false +# FORCE_DATA_SEED=false +EOF fi msg_ok "Corrected Services" @@ -54,7 +77,7 @@ function update_script() { msg_info "Starting Service" systemctl start tracktor msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/traefik.sh b/ct/traefik.sh index ac82301a1..0a2095e7e 100644 --- a/ct/traefik.sh +++ b/ct/traefik.sh @@ -38,7 +38,7 @@ function update_script() { msg_info "Starting Service" systemctl start traefik msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/transmission.sh b/ct/transmission.sh index 869b25a75..135dacbaf 100644 --- a/ct/transmission.sh +++ b/ct/transmission.sh @@ -31,6 +31,7 @@ function update_script() { $STD apt update $STD apt -y upgrade msg_ok "Updated Transmission" + msg_ok "Updated successfully!" exit } diff --git a/ct/trilium.sh b/ct/trilium.sh index af47b82db..5d9e9a064 100644 --- a/ct/trilium.sh +++ b/ct/trilium.sh @@ -36,7 +36,7 @@ function update_script() { DB_RESTORE_PATH="/opt/trilium/assets/db" else msg_error "Database not found in either /opt/trilium/db or /opt/trilium/assets/db" - exit 1 + exit fi msg_info "Stopping Service" @@ -68,7 +68,7 @@ function update_script() { systemctl start trilium sleep 1 msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/tududi.sh b/ct/tududi.sh index 8ddcd68b3..389d1ae5f 100644 --- a/ct/tududi.sh +++ b/ct/tududi.sh @@ -62,7 +62,7 @@ function update_script() { msg_info "Starting Service" systemctl start tududi msg_ok "Started Service" - msg_ok "Updated Successfully!" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/tunarr.sh b/ct/tunarr.sh index 04ded915e..9bdfe2147 100644 --- a/ct/tunarr.sh +++ b/ct/tunarr.sh @@ -44,7 +44,7 @@ function update_script() { msg_info "Starting Service" systemctl start tunarr msg_ok "Started Service" - msg_ok "Update Successfully" + msg_ok "Updated successfully!" fi if check_for_gh_release "ersatztv-ffmpeg" "ErsatzTV/ErsatzTV-ffmpeg"; then @@ -64,7 +64,7 @@ function update_script() { msg_info "Starting Service" systemctl start tunarr msg_ok "Started Service" - msg_ok "Update Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/twingate-connector.sh b/ct/twingate-connector.sh index 42fe1a6f7..4b6190230 100644 --- a/ct/twingate-connector.sh +++ b/ct/twingate-connector.sh @@ -33,7 +33,7 @@ function update_script() { $STD apt update $STD apt install -yq twingate-connector $STD systemctl restart twingate-connector - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" exit } diff --git a/ct/typesense.sh b/ct/typesense.sh index 6cd88d220..5eb30786e 100644 --- a/ct/typesense.sh +++ b/ct/typesense.sh @@ -31,7 +31,7 @@ function update_script() { msg_info "Updating Typesense" $STD apt update $STD apt -y upgrade - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/ubuntu.sh b/ct/ubuntu.sh index 8c56166de..57c101a53 100644 --- a/ct/ubuntu.sh +++ b/ct/ubuntu.sh @@ -31,6 +31,7 @@ function update_script() { $STD apt-get update $STD apt-get -y upgrade msg_ok "Updated ${APP} LXC" + msg_ok "Updated successfully!" exit } diff --git a/ct/uhf.sh b/ct/uhf.sh index 2528320e5..62e587f83 100644 --- a/ct/uhf.sh +++ b/ct/uhf.sh @@ -49,7 +49,7 @@ function update_script() { $STD apt -y autoclean $STD apt -y clean msg_ok "Cleaned" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/umami.sh b/ct/umami.sh index 32fc01159..967fcdc36 100644 --- a/ct/umami.sh +++ b/ct/umami.sh @@ -44,7 +44,7 @@ function update_script() { msg_info "Starting Service" systemctl start umami msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/umlautadaptarr.sh b/ct/umlautadaptarr.sh index 41b0908c1..f2b424ce6 100644 --- a/ct/umlautadaptarr.sh +++ b/ct/umlautadaptarr.sh @@ -42,7 +42,7 @@ function update_script() { msg_info "Starting Service" systemctl start umlautadaptarr msg_ok "Started Service" - msg_ok "$APP has been updated to ${RELEASE}." + msg_ok "Updated successfully!" else msg_ok "No update required. ${APP} is already at ${RELEASE}" fi diff --git a/ct/unbound.sh b/ct/unbound.sh index b38c74427..cf7294af0 100644 --- a/ct/unbound.sh +++ b/ct/unbound.sh @@ -31,6 +31,7 @@ function update_script() { $STD apt update $STD apt -y upgrade msg_ok "Updated Unbound" + msg_ok "Updated successfully!" exit } diff --git a/ct/unifi.sh b/ct/unifi.sh index 1cc948e49..f8bd6d9b5 100644 --- a/ct/unifi.sh +++ b/ct/unifi.sh @@ -30,7 +30,7 @@ function update_script() { msg_info "Updating ${APP}" $STD apt update --allow-releaseinfo-change $STD apt install -y unifi - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" exit } diff --git a/ct/unmanic.sh b/ct/unmanic.sh index 3b453db58..3836c4f3b 100644 --- a/ct/unmanic.sh +++ b/ct/unmanic.sh @@ -31,6 +31,7 @@ function update_script() { $STD pip3 install -U unmanic $STD apt -y upgrade msg_ok "Updated $APP LXC" + msg_ok "Updated successfully!" exit } diff --git a/ct/upsnap.sh b/ct/upsnap.sh index b64db903b..6dfc44756 100644 --- a/ct/upsnap.sh +++ b/ct/upsnap.sh @@ -38,7 +38,7 @@ function update_script() { msg_info "Starting Services" systemctl start upsnap msg_ok "Started Services" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/uptimekuma.sh b/ct/uptimekuma.sh index fa5fd0754..1c2a1e38a 100644 --- a/ct/uptimekuma.sh +++ b/ct/uptimekuma.sh @@ -46,7 +46,7 @@ function update_script() { msg_info "Starting Service" systemctl start uptime-kuma msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/urbackupserver.sh b/ct/urbackupserver.sh index 0ffe716c3..023d13fa1 100644 --- a/ct/urbackupserver.sh +++ b/ct/urbackupserver.sh @@ -30,7 +30,7 @@ function update_script() { msg_info "Updating ${APP} LXC" $STD apt update $STD apt -y upgrade - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" exit } diff --git a/ct/vaultwarden.sh b/ct/vaultwarden.sh index 11a9b6ccf..46a9fccd6 100644 --- a/ct/vaultwarden.sh +++ b/ct/vaultwarden.sh @@ -66,8 +66,7 @@ function update_script() { msg_info "Starting Service" systemctl start vaultwarden msg_ok "Started Service" - - msg_ok "$VAULT Update Successful" + msg_ok "Updated successfully!" exit fi if [ "$UPD" == "2" ]; then @@ -87,7 +86,7 @@ function update_script() { msg_info "Starting Service" systemctl start vaultwarden msg_ok "Started Service" - msg_ok "$WVRELEASE Update Successful" + msg_ok "Updated successfully!" exit fi if [ "$UPD" == "3" ]; then diff --git a/ct/verdaccio.sh b/ct/verdaccio.sh index facce9991..e57ef6c35 100644 --- a/ct/verdaccio.sh +++ b/ct/verdaccio.sh @@ -35,7 +35,7 @@ function update_script() { NODE_VERSION="22" NODE_MODULE="verdaccio" setup_nodejs systemctl restart verdaccio - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" exit } diff --git a/ct/victoriametrics.sh b/ct/victoriametrics.sh index af7de16ef..6b67249a3 100644 --- a/ct/victoriametrics.sh +++ b/ct/victoriametrics.sh @@ -45,8 +45,15 @@ function update_script() { fetch_and_deploy_gh_release "vmutils" "VictoriaMetrics/VictoriaMetrics" "prebuild" "latest" "/opt/victoriametrics" "$vmutils_filename" if [[ -f /etc/systemd/system/victoriametrics-logs.service ]]; then - fetch_and_deploy_gh_release "victorialogs" "VictoriaMetrics/VictoriaLogs" "prebuild" "latest" "/opt/victoriametrics" "victoria-logs-linux-amd64*.tar.gz" - fetch_and_deploy_gh_release "vlutils" "VictoriaMetrics/VictoriaLogs" "prebuild" "latest" "/opt/victoriametrics" "vlutils-linux-amd64*.tar.gz" + vmlogs_filename=$(curl -fsSL "https://api.github.com/repos/VictoriaMetrics/VictoriaLogs/releases/latest" | + jq -r '.assets[].name' | + grep -E '^victoria-logs-linux-amd64-v[0-9.]+\.tar\.gz$') + vlutils_filename=$(curl -fsSL "https://api.github.com/repos/VictoriaMetrics/VictoriaLogs/releases/latest" | + jq -r '.assets[].name' | + grep -E '^vlutils-linux-amd64-v[0-9.]+\.tar\.gz$') + + fetch_and_deploy_gh_release "victorialogs" "VictoriaMetrics/VictoriaLogs" "prebuild" "latest" "/opt/victoriametrics" "$vmlogs_filename" + fetch_and_deploy_gh_release "vlutils" "VictoriaMetrics/VictoriaLogs" "prebuild" "latest" "/opt/victoriametrics" "$vlutils_filename" fi chmod +x /opt/victoriametrics/* @@ -54,7 +61,7 @@ function update_script() { systemctl start victoriametrics [[ -f /etc/systemd/system/victoriametrics-logs.service ]] && systemctl start victoriametrics-logs msg_ok "Started Service" - msg_ok "Updated Successfully!" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/vikunja.sh b/ct/vikunja.sh index 88611356e..3556a4b51 100644 --- a/ct/vikunja.sh +++ b/ct/vikunja.sh @@ -49,7 +49,7 @@ function update_script() { msg_info "Cleaning Up" rm -rf /opt/vikunja-"$RELEASE"-amd64.deb msg_ok "Cleaned" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" else msg_ok "No update required. ${APP} is already at ${RELEASE}" fi diff --git a/ct/wallos.sh b/ct/wallos.sh index 004236852..8c3982fb1 100644 --- a/ct/wallos.sh +++ b/ct/wallos.sh @@ -53,7 +53,7 @@ function update_script() { msg_info "Reload Apache2" systemctl reload apache2 msg_ok "Apache2 Reloaded" - msg_ok "Updated Successfully!" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/warracker.sh b/ct/warracker.sh index ccc3261ea..c21103cc3 100644 --- a/ct/warracker.sh +++ b/ct/warracker.sh @@ -48,7 +48,7 @@ function update_script() { systemctl start warracker systemctl start nginx msg_ok "Started Services" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/wastebin.sh b/ct/wastebin.sh index 19f0808b7..9b74ad609 100644 --- a/ct/wastebin.sh +++ b/ct/wastebin.sh @@ -83,7 +83,7 @@ EOF msg_info "Cleaning Up" rm -f "$temp_file" msg_ok "Cleanup Completed" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" else msg_ok "No update required. ${APP} is already at v${RELEASE}" fi diff --git a/ct/watcharr.sh b/ct/watcharr.sh index aacd3015c..7190f2d3f 100644 --- a/ct/watcharr.sh +++ b/ct/watcharr.sh @@ -51,7 +51,7 @@ function update_script() { msg_info "Starting Service" systemctl start watcharr msg_ok "Started Service" - msg_ok "Update Successfully!" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/watchyourlan.sh b/ct/watchyourlan.sh index b374d26e4..9384c264b 100644 --- a/ct/watchyourlan.sh +++ b/ct/watchyourlan.sh @@ -45,7 +45,7 @@ function update_script() { msg_info "Starting service" systemctl enable -q --now watchyourlan msg_ok "Service started" - msg_ok "Updated Successfully!" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/wavelog.sh b/ct/wavelog.sh index 4516739c6..504014464 100644 --- a/ct/wavelog.sh +++ b/ct/wavelog.sh @@ -62,7 +62,7 @@ function update_script() { msg_info "Starting Services" systemctl start apache2 msg_ok "Started Services" - msg_ok "Updated Successfully!" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/wazuh.sh b/ct/wazuh.sh index c67b1e8e3..d9cd1e4a2 100644 --- a/ct/wazuh.sh +++ b/ct/wazuh.sh @@ -20,18 +20,19 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources - if [[ ! -f /lib/systemd/system/wazuh-manager.service ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - msg_info "Updating ${APP} LXC" - $STD apt-get update - $STD apt-get -y upgrade - msg_ok "Updated ${APP} LXC" - exit + header_info + check_container_storage + check_container_resources + if [[ ! -f /lib/systemd/system/wazuh-manager.service ]]; then + msg_error "No ${APP} Installation Found!" + exit + fi + msg_info "Updating ${APP} LXC" + $STD apt-get update + $STD apt-get -y upgrade + msg_ok "Updated ${APP} LXC" + msg_ok "Updated successfully!" + exit } start diff --git a/ct/wger.sh b/ct/wger.sh index 5379300e2..0a3f0ffee 100644 --- a/ct/wger.sh +++ b/ct/wger.sh @@ -55,7 +55,7 @@ function update_script() { msg_info "Cleaning Up" rm -rf "$temp_file" msg_ok "Cleanup Completed" - msg_ok "Updated Successfully!" + msg_ok "Updated successfully!" else msg_ok "No update required. ${APP} is already at v${RELEASE}" fi diff --git a/ct/whisparr.sh b/ct/whisparr.sh index 820a5ca21..ff83a2330 100644 --- a/ct/whisparr.sh +++ b/ct/whisparr.sh @@ -31,7 +31,7 @@ function update_script() { $STD apt update $STD apt -y upgrade msg_ok "Updated Whisparr" - msg_ok "Updated Successfully!" + msg_ok "Updated successfully!" exit } diff --git a/ct/wikijs.sh b/ct/wikijs.sh index 299b726ed..d83e62f89 100644 --- a/ct/wikijs.sh +++ b/ct/wikijs.sh @@ -63,7 +63,7 @@ function update_script() { msg_info "Cleaning Up" rm -rf /opt/wikijs-backup msg_ok "Cleanup Completed" - msg_ok "Updated Successfully!" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/wireguard.sh b/ct/wireguard.sh index 045f23fa6..a0609da38 100644 --- a/ct/wireguard.sh +++ b/ct/wireguard.sh @@ -42,7 +42,7 @@ function update_script() { ./wgd.sh update ./wgd.sh start fi - msg_ok "Updated Successfully!" + msg_ok "Updated successfully!" exit } diff --git a/ct/wizarr.sh b/ct/wizarr.sh index 09b4f69cd..991b22272 100644 --- a/ct/wizarr.sh +++ b/ct/wizarr.sh @@ -65,7 +65,7 @@ function update_script() { msg_info "Cleaning Up" rm -rf "$BACKUP_FILE" msg_ok "Cleanup Completed" - msg_ok "Updated Successfully!" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/yt-dlp-webui.sh b/ct/yt-dlp-webui.sh index 2901995c8..a97290a6f 100644 --- a/ct/yt-dlp-webui.sh +++ b/ct/yt-dlp-webui.sh @@ -43,7 +43,7 @@ function update_script() { msg_info "Starting Service" systemctl start yt-dlp-webui msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/yunohost.sh b/ct/yunohost.sh index ae62a6ea7..c9b785b9e 100644 --- a/ct/yunohost.sh +++ b/ct/yunohost.sh @@ -37,6 +37,7 @@ function update_script() { $STD yunohost tools upgrade system $STD yunohost tools upgrade apps msg_ok "Updated $APP LXC" + msg_ok "Updated successfully!" exit } diff --git a/ct/zabbix.sh b/ct/zabbix.sh index 43ce54de2..cbde042d3 100644 --- a/ct/zabbix.sh +++ b/ct/zabbix.sh @@ -32,7 +32,7 @@ function update_script() { . /etc/os-release if [ "$VERSION_CODENAME" != "trixie" ]; then msg_error "Unsupported Debian version: $VERSION_CODENAME – please upgrade to Debian 13 (Trixie) before updating Zabbix." - exit 1 + exit fi if systemctl list-unit-files | grep -q zabbix-agent2.service; then @@ -42,12 +42,8 @@ function update_script() { fi msg_info "Stopping Services" - $STD systemctl stop zabbix-server - if systemctl list-unit-files | grep -q zabbix-agent2; then - $STD systemctl stop zabbix-agent2 - else - $STD systemctl stop zabbix-agent - fi + systemctl stop zabbix-server + systemctl stop "$AGENT_SERVICE" msg_ok "Stopped Services" msg_info "Updating Zabbix" @@ -88,12 +84,8 @@ function update_script() { msg_ok "Updated Zabbix" msg_info "Starting Services" - $STD systemctl start zabbix-server - if systemctl list-unit-files | grep -q zabbix-agent2; then - $STD systemctl start zabbix-agent2 - else - $STD systemctl start zabbix-agent - fi + systemctl start zabbix-server + systemctl start "$AGENT_SERVICE" systemctl restart apache2 msg_ok "Started Services" @@ -103,7 +95,7 @@ function update_script() { $STD apt -y autoclean $STD apt -y clean msg_ok "Cleaned" - msg_ok "Updated Successfully!" + msg_ok "Updated successfully!" exit } diff --git a/ct/zammad.sh b/ct/zammad.sh index bf9f2fe5f..2c582cce9 100644 --- a/ct/zammad.sh +++ b/ct/zammad.sh @@ -42,6 +42,7 @@ function update_script() { msg_info "Starting Service" systemctl start zammad msg_ok "Updated ${APP} LXC" + msg_ok "Updated successfully!" exit } diff --git a/ct/zerotier-one.sh b/ct/zerotier-one.sh index 10d9e41ef..fb9d3a14b 100644 --- a/ct/zerotier-one.sh +++ b/ct/zerotier-one.sh @@ -41,6 +41,7 @@ function update_script() { msg_info "Starting Service" systemctl start zerotier-one msg_ok "Started Service" + msg_ok "Updated successfully!" exit } diff --git a/ct/zigbee2mqtt.sh b/ct/zigbee2mqtt.sh index dbd5dc566..642747032 100644 --- a/ct/zigbee2mqtt.sh +++ b/ct/zigbee2mqtt.sh @@ -47,7 +47,7 @@ function update_script() { rm -rf /opt/zigbee2mqtt/data mv /opt/z2m_backup/data /opt/zigbee2mqtt cd /opt/zigbee2mqtt - echo "packageImportMethod: hardlink" >>./pnpm-workspace.yaml + grep -q "^packageImportMethod" ./pnpm-workspace.yaml || echo "packageImportMethod: hardlink" >> ./pnpm-workspace.yaml $STD pnpm install --frozen-lockfile $STD pnpm build msg_ok "Updated Zigbee2MQTT" @@ -59,7 +59,7 @@ function update_script() { msg_info "Cleaning up" rm -rf /opt/z2m_backup msg_ok "Cleaned up" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/zipline.sh b/ct/zipline.sh index 64a449b42..f42d78bfe 100644 --- a/ct/zipline.sh +++ b/ct/zipline.sh @@ -52,7 +52,7 @@ function update_script() { msg_info "Starting Service" systemctl start zipline msg_ok "Started Service" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/zitadel.sh b/ct/zitadel.sh index 039cbf67d..d3fc16265 100644 --- a/ct/zitadel.sh +++ b/ct/zitadel.sh @@ -43,7 +43,7 @@ function update_script() { msg_info "Starting Service" systemctl start zitadel msg_ok "Started Service" - msg_ok "Update Successful" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/zoraxy.sh b/ct/zoraxy.sh index 8d9e37e55..10c95ed17 100644 --- a/ct/zoraxy.sh +++ b/ct/zoraxy.sh @@ -38,7 +38,7 @@ function update_script() { msg_info "Starting service" systemctl start zoraxy msg_ok "Service started" - msg_ok "Updated successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/zot-registry.sh b/ct/zot-registry.sh index 2918dce7f..5082255b2 100644 --- a/ct/zot-registry.sh +++ b/ct/zot-registry.sh @@ -43,7 +43,7 @@ function update_script() { msg_info "Starting service" systemctl start zot msg_ok "Service started" - msg_ok "Updated successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/ct/zwave-js-ui.sh b/ct/zwave-js-ui.sh index c33aa397e..abc21136f 100644 --- a/ct/zwave-js-ui.sh +++ b/ct/zwave-js-ui.sh @@ -43,7 +43,7 @@ function update_script() { msg_info "Cleanup" rm -rf /opt/zwave-js-ui/store msg_ok "Cleaned" - msg_ok "Updated Successfully" + msg_ok "Updated successfully!" fi exit } diff --git a/frontend/public/json/bazarr.json b/frontend/public/json/bazarr.json index 2a04bf781..367b319f8 100644 --- a/frontend/public/json/bazarr.json +++ b/frontend/public/json/bazarr.json @@ -23,7 +23,7 @@ "ram": 1024, "hdd": 4, "os": "debian", - "version": "12" + "version": "13" } } ], diff --git a/frontend/public/json/bentopdf.json b/frontend/public/json/bentopdf.json new file mode 100644 index 000000000..2a09b34cf --- /dev/null +++ b/frontend/public/json/bentopdf.json @@ -0,0 +1,35 @@ +{ + "name": "BentoPDF", + "slug": "bentopdf", + "categories": [ + 12 + ], + "date_created": "2025-10-30", + "type": "ct", + "updateable": true, + "privileged": false, + "interface_port": 8080, + "documentation": "https://github.com/alam00000/bentopdf", + "website": "https://www.bentopdf.com", + "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/bentopdf.webp", + "config_path": "", + "description": "A privacy-first, 100% client-side PDF Toolkit. No signups/accounts, works in the browser, online or offline.", + "install_methods": [ + { + "type": "default", + "script": "ct/bentopdf.sh", + "resources": { + "cpu": 1, + "ram": 2048, + "hdd": 4, + "os": "debian", + "version": "13" + } + } + ], + "default_credentials": { + "username": null, + "password": null + }, + "notes": [] +} diff --git a/frontend/public/json/bunkerweb.json b/frontend/public/json/bunkerweb.json index 9fe806f6d..7f491e216 100644 --- a/frontend/public/json/bunkerweb.json +++ b/frontend/public/json/bunkerweb.json @@ -12,7 +12,7 @@ "documentation": "https://docs.bunkerweb.io/latest/", "website": "https://www.bunkerweb.io/", "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/bunkerweb.webp", - "config_path": "/opt/bunkerweb/variables.env", + "config_path": "/etc/bunkerweb/variables.env", "description": "BunkerWeb is a security-focused web server that enhances web application protection. It guards against common web vulnerabilities like SQL injection, XSS, and CSRF. It features simple setup and configuration using a YAML file, customizable security rules, and provides detailed logs for traffic monitoring and threat detection.", "install_methods": [ { diff --git a/frontend/public/json/comfyui.json b/frontend/public/json/comfyui.json new file mode 100644 index 000000000..f30bf5df7 --- /dev/null +++ b/frontend/public/json/comfyui.json @@ -0,0 +1,44 @@ +{ + "name": "ComfyUI", + "slug": "comfyui", + "categories": [ + 20 + ], + "date_created": "2025-10-26", + "type": "ct", + "updateable": true, + "privileged": false, + "config_path": "/opt", + "interface_port": 8188, + "documentation": "https://github.com/comfyanonymous/ComfyUI", + "website": "https://www.comfy.org/", + "logo": "https://framerusercontent.com/images/3cNQMWKzIhIrQ5KErBm7dSmbd2w.png", + "description": "ComfyUI is a node-based interface and inference engine for generative AI. Users can combine various AI models and operations through nodes to achieve highly customizable and controllable content generation.", + "install_methods": [ + { + "type": "default", + "script": "ct/comfyui.sh", + "resources": { + "cpu": 4, + "ram": 8192, + "hdd": 25, + "os": "debian", + "version": "13" + } + } + ], + "default_credentials": { + "username": null, + "password": null + }, + "notes": [ + { + "text": "Application takes long time to install. Please be patient!", + "type": "warning" + }, + { + "text": "Please check that you have installed the drivers for your GPU.", + "type": "info" + } + ] +} diff --git a/frontend/public/json/cronicle.json b/frontend/public/json/cronicle.json index 395cafb27..cee7d00a2 100644 --- a/frontend/public/json/cronicle.json +++ b/frontend/public/json/cronicle.json @@ -28,8 +28,8 @@ } ], "default_credentials": { - "username": null, - "password": null + "username": "admin", + "password": "admin" }, "notes": [ { diff --git a/frontend/public/json/dispatcharr.json b/frontend/public/json/dispatcharr.json new file mode 100644 index 000000000..a6d343ea4 --- /dev/null +++ b/frontend/public/json/dispatcharr.json @@ -0,0 +1,35 @@ +{ + "name": "Dispatcharr", + "slug": "dispatcharr", + "categories": [ + 14 + ], + "date_created": "2025-10-27", + "type": "ct", + "updateable": true, + "privileged": false, + "interface_port": 9191, + "documentation": "https://dispatcharr.github.io/Dispatcharr-Docs/", + "website": "https://github.com/Dispatcharr/Dispatcharr", + "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/dispatcharr.webp", + "config_path": "/opt/dispatcharr/.env", + "description": "Dispatcharr is an open-source powerhouse for managing IPTV streams and EPG data with elegance and control. Born from necessity and built with passion, it started as a personal project by OkinawaBoss and evolved with contributions from legends like dekzter, SergeantPanda and Bucatini.", + "install_methods": [ + { + "type": "default", + "script": "ct/dispatcharr.sh", + "resources": { + "cpu": 2, + "ram": 2048, + "hdd": 8, + "os": "debian", + "version": "13" + } + } + ], + "default_credentials": { + "username": null, + "password": null + }, + "notes": [] +} diff --git a/frontend/public/json/donetick.json b/frontend/public/json/donetick.json new file mode 100644 index 000000000..b11f2e9e9 --- /dev/null +++ b/frontend/public/json/donetick.json @@ -0,0 +1,35 @@ +{ + "name": "Donetick", + "slug": "donetick", + "categories": [ + 19 + ], + "date_created": "2025-11-03", + "type": "ct", + "updateable": true, + "privileged": false, + "interface_port": 2021, + "documentation": "https://docs.donetick.com/getting-started/", + "config_path": "/opt/donetick/config/selfhosted.yml", + "website": "https://donetick.com", + "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/donetick.webp", + "description": "Donetick an open-source, user-friendly app for managing tasks and chores, featuring customizable options to help you and others stay organized", + "install_methods": [ + { + "type": "default", + "script": "ct/donetick.sh", + "resources": { + "cpu": 1, + "ram": 512, + "hdd": 2, + "os": "Debian", + "version": "13" + } + } + ], + "default_credentials": { + "username": null, + "password": null + }, + "notes": [] +} diff --git a/frontend/public/json/flaresolverr.json b/frontend/public/json/flaresolverr.json index 03a63d073..50616aecb 100644 --- a/frontend/public/json/flaresolverr.json +++ b/frontend/public/json/flaresolverr.json @@ -23,7 +23,7 @@ "ram": 2048, "hdd": 4, "os": "debian", - "version": "12" + "version": "13" } } ], @@ -31,10 +31,5 @@ "username": null, "password": null }, - "notes": [ - { - "text": "Flaresolverr is pinned to Version 3.3.25 because they add an breaking python package which doesn't work with debian 12.`", - "type": "info" - } - ] + "notes": [] } diff --git a/frontend/public/json/garage.json b/frontend/public/json/garage.json new file mode 100644 index 000000000..7290b1693 --- /dev/null +++ b/frontend/public/json/garage.json @@ -0,0 +1,59 @@ +{ + "name": "Garage", + "slug": "garage", + "categories": [ + 8 + ], + "date_created": "2025-10-27", + "type": "ct", + "updateable": true, + "privileged": false, + "interface_port": 3900, + "documentation": "https://garagehq.deuxfleurs.fr/documentation/quick-start/", + "website": "https://garagehq.deuxfleurs.fr/", + "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/garage.webp", + "config_path": "/etc/garage.toml", + "description": "Garage is a lightweight, self-hosted, S3-compatible object storage service built for distributed environments. It is designed to be simple, efficient, and easy to deploy across multiple nodes.", + "install_methods": [ + { + "type": "default", + "script": "ct/garage.sh", + "resources": { + "cpu": 1, + "ram": 1024, + "hdd": 5, + "os": "debian", + "version": "13" + } + }, + { + "type": "alpine", + "script": "ct/alpine-garage.sh", + "resources": { + "cpu": 1, + "ram": 512, + "hdd": 5, + "os": "alpine", + "version": "3.22" + } + } + ], + "default_credentials": { + "username": null, + "password": null + }, + "notes": [ + { + "text": "The Garage configuration file is located at `/etc/garage.toml`. You can edit RPC and API bindings, tokens, and data directories there.", + "type": "info" + }, + { + "text": "Admin API runs by default on port `3903`, S3 API on port `3900`, Web UI on `3902`. Adjust firewall rules accordingly.", + "type": "warning" + }, + { + "text": "To view your generated tokens and RPC secret, check `~/garage.creds` after installation.", + "type": "info" + } + ] +} diff --git a/frontend/public/json/guardian.json b/frontend/public/json/guardian.json index 60fdd5048..1719dece6 100644 --- a/frontend/public/json/guardian.json +++ b/frontend/public/json/guardian.json @@ -12,7 +12,7 @@ "documentation": "https://github.com/HydroshieldMKII/Guardian/blob/main/README.md", "config_path": "/opt/guardian/.env", "website": "https://github.com/HydroshieldMKII/Guardian", - "logo": null, + "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/guardian-plex.webp", "description": "Guardian is a lightweight companion app for Plex that lets you monitor, approve or block devices in real time. It helps you enforce per-user or global policies, stop unwanted sessions automatically and grant temporary access - all through a simple web interface.", "install_methods": [ { diff --git a/frontend/public/json/jotty.json b/frontend/public/json/jotty.json index c374a4a0a..042130d49 100644 --- a/frontend/public/json/jotty.json +++ b/frontend/public/json/jotty.json @@ -20,7 +20,7 @@ "script": "ct/jotty.sh", "resources": { "cpu": 2, - "ram": 3072, + "ram": 4096, "hdd": 6, "os": "debian", "version": "13" diff --git a/frontend/public/json/livebook.json b/frontend/public/json/livebook.json new file mode 100644 index 000000000..0bad4f4f3 --- /dev/null +++ b/frontend/public/json/livebook.json @@ -0,0 +1,40 @@ +{ + "name": "Livebook", + "slug": "livebook", + "categories": [ + 20 + ], + "date_created": "2025-10-30", + "type": "ct", + "updateable": true, + "privileged": false, + "interface_port": 8080, + "documentation": "https://hexdocs.pm/livebook/readme.html", + "config_path": null, + "website": "https://livebook.dev", + "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/livebook.webp", + "description": "Elixir Livebook is an interactive, web-based notebook platform for Elixir that combines code, documentation, and visualizations in a single document. Similar to Jupyter notebooks, it allows developers to write and execute Elixir code in real-time, making it ideal for data exploration, prototyping, learning, and collaborative development. Livebook features rich markdown support, built-in charting capabilities, and seamless integration with the Elixir ecosystem.", + "install_methods": [ + { + "type": "default", + "script": "ct/livebook.sh", + "resources": { + "cpu": 1, + "ram": 1024, + "hdd": 4, + "os": "Ubuntu", + "version": "24.04" + } + } + ], + "default_credentials": { + "username": null, + "password": null + }, + "notes": [ + { + "text": "Show initial Livebook password: `cat ~/livebook.creds`", + "type": "info" + } + ] +} diff --git a/frontend/public/json/metube.json b/frontend/public/json/metube.json deleted file mode 100644 index c9c02954d..000000000 --- a/frontend/public/json/metube.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "name": "MeTube", - "slug": "metube", - "categories": [ - 11 - ], - "date_created": "2025-06-24", - "type": "ct", - "updateable": true, - "privileged": false, - "interface_port": 8081, - "documentation": "https://github.com/alexta69/metube/blob/master/README.md", - "website": "https://github.com/alexta69/metube", - "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/metube.webp", - "config_path": "/opt/metube/.env", - "description": "MeTube allows you to download videos from YouTube and dozens of other sites.", - "install_methods": [ - { - "type": "default", - "script": "ct/metube.sh", - "resources": { - "cpu": 1, - "ram": 2048, - "hdd": 10, - "os": "debian", - "version": "13" - } - } - ], - "default_credentials": { - "username": null, - "password": null - }, - "notes": [] -} diff --git a/frontend/public/json/mysql.json b/frontend/public/json/mysql.json deleted file mode 100644 index 2bd6b8aff..000000000 --- a/frontend/public/json/mysql.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "name": "MySQL", - "slug": "mysql", - "categories": [ - 8 - ], - "date_created": "2024-10-10", - "type": "ct", - "updateable": true, - "privileged": false, - "interface_port": null, - "documentation": "https://dev.mysql.com/doc/", - "website": "https://www.mysql.com/", - "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/mysql.webp", - "config_path": "", - "description": "MySQL is an open-source relational database management system (RDBMS) that uses SQL for managing and manipulating data. It is known for its scalability, reliability, and high performance, making it suitable for small to large-scale applications. Key features include support for ACID transactions, data replication for high availability, and compatibility with various programming languages like Python, PHP, and Java.", - "install_methods": [ - { - "type": "default", - "script": "ct/mysql.sh", - "resources": { - "cpu": 1, - "ram": 1024, - "hdd": 4, - "os": "debian", - "version": "13" - } - } - ], - "default_credentials": { - "username": null, - "password": null - }, - "notes": [ - { - "text": "Database credentials: `cat mysql.creds`", - "type": "info" - }, - { - "text": "With an option to install the MySQL 8.4 LTS release instead of MySQL 8.0", - "type": "info" - }, - { - "text": "If installed, access phpMyAdmin at `http:///phpMyAdmin`, case sensitive.", - "type": "info" - } - ] -} diff --git a/frontend/public/json/mysql.json.bak b/frontend/public/json/mysql.json.bak new file mode 100644 index 000000000..3095480d7 --- /dev/null +++ b/frontend/public/json/mysql.json.bak @@ -0,0 +1,48 @@ +{ + "name": "MySQL", + "slug": "mysql", + "categories": [ + 8 + ], + "date_created": "2024-10-10", + "type": "ct", + "updateable": true, + "privileged": false, + "interface_port": null, + "documentation": "https://dev.mysql.com/doc/", + "website": "https://www.mysql.com/", + "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/mysql.webp", + "config_path": "", + "description": "MySQL is an open-source relational database management system (RDBMS) that uses SQL for managing and manipulating data. It is known for its scalability, reliability, and high performance, making it suitable for small to large-scale applications. Key features include support for ACID transactions, data replication for high availability, and compatibility with various programming languages like Python, PHP, and Java.", + "install_methods": [ + { + "type": "default", + "script": "ct/mysql.sh", + "resources": { + "cpu": 1, + "ram": 1024, + "hdd": 4, + "os": "debian", + "version": "12" + } + } + ], + "default_credentials": { + "username": null, + "password": null + }, + "notes": [ + { + "text": "Database credentials: `cat mysql.creds`", + "type": "info" + }, + { + "text": "With an option to install the MySQL 8.4 LTS release instead of MySQL 8.0", + "type": "info" + }, + { + "text": "If installed, access phpMyAdmin at `http:///phpMyAdmin`, case sensitive.", + "type": "info" + } + ] +} diff --git a/frontend/public/json/nginxproxymanager.json b/frontend/public/json/nginxproxymanager.json index bbc55a1d1..8986a4a2a 100644 --- a/frontend/public/json/nginxproxymanager.json +++ b/frontend/public/json/nginxproxymanager.json @@ -20,8 +20,8 @@ "script": "ct/nginxproxymanager.sh", "resources": { "cpu": 2, - "ram": 1024, - "hdd": 4, + "ram": 2048, + "hdd": 8, "os": "debian", "version": "13" } @@ -33,12 +33,8 @@ }, "notes": [ { - "text": "Since there are hundreds of Certbot instances, it's necessary to install the specific Certbot of your preference. Running `/app/scripts/install-certbot-plugins` within the nginxproxymanager LXC shell will install many additional plugins.", - "type": "warning" - }, - { - "text": "WARNING: Installation sources scripts outside of Community Scripts repo. Please check the source before installing.", - "type": "warning" + "text": "You can install the specific one certbot you prefer, or you can Running /app/scripts/install-certbot-plugins within the Nginx Proxy Manager (NPM) LXC shell will install many common plugins. Important: This script does not install all Certbot plugins, as some require additional, external system dependencies (like specific packages for certain DNS providers). These external dependencies must be manually installed within the LXC container before you can successfully install and use the corresponding Certbot plugin. Consult the plugin's documentation for required packages.", + "type": "info" } ] } diff --git a/frontend/public/json/omv.json b/frontend/public/json/omv.json index 41e780428..6dd01ef4f 100644 --- a/frontend/public/json/omv.json +++ b/frontend/public/json/omv.json @@ -23,7 +23,7 @@ "ram": 1024, "hdd": 4, "os": "debian", - "version": "13" + "version": "12" } } ], diff --git a/frontend/public/json/openwebui.json b/frontend/public/json/openwebui.json index cc1ccd1a9..a7c5891fb 100644 --- a/frontend/public/json/openwebui.json +++ b/frontend/public/json/openwebui.json @@ -12,7 +12,7 @@ "documentation": "https://docs.openwebui.com/", "website": "https://openwebui.com/", "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/open-webui.webp", - "config_path": "/opt/open-webui/.env", + "config_path": "/root/.env", "description": "OpenWebUI is a self-hosted, web-based interface that allows you to run AI models entirely offline. It integrates with various LLM runners, such as OpenAI and Ollama, and supports features like markdown and LaTeX rendering, model management, and voice/video calls. It also offers multilingual support and the ability to generate images using APIs like DALL-E or ComfyUI", "install_methods": [ { @@ -23,7 +23,7 @@ "ram": 8192, "hdd": 25, "os": "debian", - "version": "12" + "version": "13" } } ], @@ -35,6 +35,10 @@ { "text": "Script contains optional installation of Ollama.", "type": "info" + }, + { + "text": "Initial run of the application/container can take some time, depending on your host speed, as the application is installed/updated at runtime. Please be patient!", + "type": "warning" } ] } diff --git a/frontend/public/json/pangolin.json b/frontend/public/json/pangolin.json new file mode 100644 index 000000000..8cd3c13b2 --- /dev/null +++ b/frontend/public/json/pangolin.json @@ -0,0 +1,48 @@ +{ + "name": "Pangolin", + "slug": "pangolin", + "categories": [ + 21 + ], + "date_created": "2025-11-01", + "type": "ct", + "updateable": true, + "privileged": false, + "interface_port": 3002, + "documentation": "https://docs.pangolin.net/", + "config_path": "/opt/pangolin/config/config.yml", + "website": "https://pangolin.net/", + "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/pangolin.webp", + "description": "Pangolin securely routes traffic over WireGuard tunnels to any private network. It works like a reverse proxy that spans multiple networks — no public IPs, DNS setup, or certificates required.", + "install_methods": [ + { + "type": "default", + "script": "ct/pangolin.sh", + "resources": { + "cpu": 2, + "ram": 4096, + "hdd": 5, + "os": "Debian", + "version": "13" + } + } + ], + "default_credentials": { + "username": null, + "password": null + }, + "notes": [ + { + "text": "Type `journalctl -u pangolin | grep -oP 'Token:\\s*\\K\\w+'` into LXC console to get admin token which you will use to create admin account.", + "type": "info" + }, + { + "text": "LXC has 4GB of RAM set initially for the build stage. After installation finishes, you can decrease the RAM allocated to 1024MB or 512MB even.", + "type": "info" + }, + { + "text": "Make sure you edit `/opt/pangolin/config/config.yml` and change it to match your needs", + "type": "warning" + } + ] +} diff --git a/frontend/public/json/patchmon.json b/frontend/public/json/patchmon.json new file mode 100644 index 000000000..0d46496ee --- /dev/null +++ b/frontend/public/json/patchmon.json @@ -0,0 +1,35 @@ +{ + "name": "PatchMon", + "slug": "patchmon", + "categories": [ + 9 + ], + "date_created": "2025-10-25", + "type": "ct", + "updateable": true, + "privileged": false, + "interface_port": 3399, + "documentation": "https://docs.patchmon.net", + "website": "https://patchmon.net", + "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/patchmon.webp", + "config_path": "/opt/patchmon/backend/.env, /opt/patchmon/frontend/.env", + "description": "Monitor Linux patches across all your hosts with real-time visibility, security update tracking, and comprehensive package management.", + "install_methods": [ + { + "type": "default", + "script": "ct/patchmon.sh", + "resources": { + "cpu": 2, + "ram": 2048, + "hdd": 4, + "os": "debian", + "version": "13" + } + } + ], + "default_credentials": { + "username": null, + "password": null + }, + "notes": [] +} diff --git a/frontend/public/json/pihole.json b/frontend/public/json/pihole.json index e97cad664..c29182781 100644 --- a/frontend/public/json/pihole.json +++ b/frontend/public/json/pihole.json @@ -23,7 +23,7 @@ "ram": 512, "hdd": 2, "os": "debian", - "version": "13" + "version": "12" } } ], diff --git a/frontend/public/json/reitti.json b/frontend/public/json/reitti.json new file mode 100644 index 000000000..818d79653 --- /dev/null +++ b/frontend/public/json/reitti.json @@ -0,0 +1,40 @@ +{ + "name": "Reitti", + "slug": "reitti", + "categories": [ + 21 + ], + "date_created": "2025-10-30", + "type": "ct", + "updateable": true, + "privileged": false, + "interface_port": 8080, + "documentation": "https://www.dedicatedcode.com/projects/reitti/", + "config_path": "/opt/reitti/.env", + "website": "https://www.dedicatedcode.com/projects/reitti/", + "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/reitti.webp", + "description": "Reitti is a self-hosted location tracking and analysis platform that detects significant places, trip patterns, and integrates with OwnTracks, GPSLogger, and Immich. It uses PostgreSQL + PostGIS, RabbitMQ, Redis, and an optional Photon geocoder.", + "install_methods": [ + { + "type": "default", + "script": "ct/reitti.sh", + "resources": { + "cpu": 2, + "ram": 4096, + "hdd": 15, + "os": "debian", + "version": "13" + } + } + ], + "default_credentials": { + "username": "admin", + "password": "admin" + }, + "notes": [ + { + "text": "Photon Geocoder running at http://127.0.0.1:2322. Photon is fully setup, but without sample data. (filesize is big) -> checkout our guide: `https://github.com/community-scripts/ProxmoxVE/discussions/8737`.", + "type": "info" + } + ] +} diff --git a/frontend/public/json/technitiumdns.json b/frontend/public/json/technitiumdns.json index 479a84801..57376feef 100644 --- a/frontend/public/json/technitiumdns.json +++ b/frontend/public/json/technitiumdns.json @@ -23,7 +23,7 @@ "ram": 512, "hdd": 2, "os": "debian", - "version": "13" + "version": "12" } } ], diff --git a/frontend/public/json/tracktor.json b/frontend/public/json/tracktor.json index ca08d6dbf..12bd1d3b0 100644 --- a/frontend/public/json/tracktor.json +++ b/frontend/public/json/tracktor.json @@ -9,9 +9,9 @@ "updateable": true, "privileged": false, "interface_port": 3000, - "documentation": "https://tracktor.bytedge.in/introduction.html", + "documentation": "https://github.com/javedh-dev/tracktor/tree/main/docs", "config_path": "/opt/tracktor.env", - "website": "https://tracktor.bytedge.in/", + "website": "https://github.com/javedh-dev/tracktor", "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/tracktor.webp", "description": "Tracktor is an open-source web application for comprehensive vehicle management.\nEasily track fuel consumption, maintenance, insurance, and regulatory documents for all your vehicles in one place.", "install_methods": [ diff --git a/frontend/public/json/unifi.json b/frontend/public/json/unifi.json index ca834a6eb..ab1989fc2 100644 --- a/frontend/public/json/unifi.json +++ b/frontend/public/json/unifi.json @@ -23,7 +23,7 @@ "ram": 2048, "hdd": 8, "os": "debian", - "version": "13" + "version": "12" } } ], diff --git a/frontend/public/json/urbackupserver.json b/frontend/public/json/urbackupserver.json index 37341c969..cfe6df4d8 100644 --- a/frontend/public/json/urbackupserver.json +++ b/frontend/public/json/urbackupserver.json @@ -35,6 +35,10 @@ { "text": "You probably want to drastically extend the storage space to fit whatever clients you want to back up", "type": "info" + }, + { + "text": "Directory `/opt/urbackup/backups` is set as initial backup path. Change it to your liking", + "type": "info" } ] } diff --git a/frontend/public/json/versions.json b/frontend/public/json/versions.json index 492af847c..e3793381a 100644 --- a/frontend/public/json/versions.json +++ b/frontend/public/json/versions.json @@ -1,113 +1,498 @@ [ { - "name": "duplicati/duplicati", - "version": "v2.2.0.0-2.2.0.0_stable_2025-10-23", - "date": "2025-10-23T11:25:25Z" + "name": "transmission/transmission", + "version": "4.0.1-beta.1", + "date": "2024-12-13T00:16:24Z" + }, + { + "name": "semaphoreui/semaphore", + "version": "v2.17.0-beta20", + "date": "2025-11-06T10:49:56Z" + }, + { + "name": "FlowiseAI/Flowise", + "version": "flowise@3.0.9", + "date": "2025-11-06T10:27:13Z" }, { "name": "keycloak/keycloak", - "version": "26.4.2", - "date": "2025-10-23T06:59:32Z" + "version": "26.4.3", + "date": "2025-11-06T09:56:20Z" + }, + { + "name": "OliveTin/OliveTin", + "version": "2025.11.06", + "date": "2025-11-06T08:45:02Z" + }, + { + "name": "SigNoz/signoz", + "version": "v0.100.1", + "date": "2025-11-06T07:53:11Z" + }, + { + "name": "apache/tomcat", + "version": "9.0.112", + "date": "2025-11-06T07:49:59Z" }, { "name": "Jackett/Jackett", - "version": "v0.24.175", - "date": "2025-10-23T05:50:23Z" + "version": "v0.24.252", + "date": "2025-11-06T05:55:30Z" }, { - "name": "YunoHost/yunohost", - "version": "debian/12.1.31", - "date": "2025-10-23T00:45:04Z" + "name": "Kozea/Radicale", + "version": "v3.5.8", + "date": "2025-11-06T05:32:51Z" + }, + { + "name": "firefly-iii/firefly-iii", + "version": "v6.4.4", + "date": "2025-11-01T19:48:08Z" + }, + { + "name": "apache/couchdb", + "version": "3.5.1-RC1", + "date": "2025-11-06T03:23:20Z" + }, + { + "name": "Notifiarr/notifiarr", + "version": "v0.9.1", + "date": "2025-11-06T02:26:53Z" }, { "name": "jeedom/core", "version": "4.4.20", - "date": "2025-10-23T00:27:05Z" + "date": "2025-11-06T00:27:04Z" }, { "name": "steveiliop56/tinyauth", "version": "v4.0.1", "date": "2025-10-15T16:53:55Z" }, + { + "name": "ollama/ollama", + "version": "v0.12.10-rc0", + "date": "2025-11-05T19:58:03Z" + }, + { + "name": "neo4j/neo4j", + "version": "5.26.16", + "date": "2025-11-05T20:41:40Z" + }, { "name": "BerriAI/litellm", - "version": "v1.78.7-nightly", - "date": "2025-10-22T22:33:31Z" + "version": "v1.79.1.dev6", + "date": "2025-11-05T19:25:05Z" }, { - "name": "jhuckaby/Cronicle", - "version": "v0.9.99", - "date": "2025-10-22T22:20:33Z" + "name": "home-assistant/core", + "version": "2025.11.0", + "date": "2025-11-05T19:23:12Z" }, { - "name": "sabnzbd/sabnzbd", - "version": "4.5.4", - "date": "2025-10-22T21:23:17Z" + "name": "leiweibau/Pi.Alert", + "version": "v2025-11-05", + "date": "2025-11-05T18:08:26Z" }, { - "name": "moghtech/komodo", - "version": "v1.19.5", - "date": "2025-09-27T20:59:46Z" + "name": "n8n-io/n8n", + "version": "n8n@1.118.2", + "date": "2025-11-05T18:07:04Z" }, { - "name": "paperless-ngx/paperless-ngx", - "version": "v2.19.1", - "date": "2025-10-22T20:40:07Z" + "name": "bunkerity/bunkerweb", + "version": "v1.6.5", + "date": "2025-10-06T15:25:17Z" }, { - "name": "rcourtman/Pulse", - "version": "issue-596", - "date": "2025-10-22T19:48:56Z" - }, - { - "name": "gtsteffaniak/filebrowser", - "version": "v0.8.10-beta", - "date": "2025-10-22T18:41:54Z" - }, - { - "name": "docker/compose", - "version": "v2.40.2", - "date": "2025-10-22T17:38:12Z" - }, - { - "name": "louislam/uptime-kuma", - "version": "2.0.2", - "date": "2025-10-22T17:03:54Z" - }, - { - "name": "chrisvel/tududi", - "version": "v0.84.2", - "date": "2025-10-22T17:03:48Z" - }, - { - "name": "prometheus/prometheus", - "version": "v0.307.2", - "date": "2025-10-22T16:00:08Z" - }, - { - "name": "thecfu/scraparr", - "version": "v3.0.0-beta", - "date": "2025-10-22T13:12:10Z" - }, - { - "name": "NLnetLabs/unbound", - "version": "release-1.24.1", - "date": "2025-10-22T10:28:00Z" + "name": "wazuh/wazuh", + "version": "coverity-w45-4.14.1", + "date": "2025-11-05T16:56:57Z" }, { "name": "mattermost/mattermost", - "version": "server/public/v0.1.21", - "date": "2025-10-16T09:46:16Z" + "version": "v10.11.6", + "date": "2025-11-04T09:43:16Z" + }, + { + "name": "javedh-dev/tracktor", + "version": "0.5.1", + "date": "2025-11-05T15:51:02Z" + }, + { + "name": "zitadel/zitadel", + "version": "v4.6.4", + "date": "2025-11-05T15:57:00Z" + }, + { + "name": "chrisvel/tududi", + "version": "v0.85.1", + "date": "2025-10-31T10:45:26Z" + }, + { + "name": "Graylog2/graylog2-server", + "version": "6.2.9", + "date": "2025-11-05T13:55:39Z" + }, + { + "name": "immich-app/immich", + "version": "v2.2.3", + "date": "2025-11-05T13:47:03Z" + }, + { + "name": "duplicati/duplicati", + "version": "v2.2.0.100-2.2.0.100_canary_2025-11-05", + "date": "2025-11-05T13:01:37Z" + }, + { + "name": "azukaar/Cosmos-Server", + "version": "v0.18.4", + "date": "2025-04-05T19:12:57Z" + }, + { + "name": "getumbrel/umbrel", + "version": "1.5.0", + "date": "2025-11-05T11:10:20Z" + }, + { + "name": "emqx/emqx", + "version": "e5.10.2-alpha.1", + "date": "2025-11-05T09:55:26Z" + }, + { + "name": "glpi-project/glpi", + "version": "11.0.2", + "date": "2025-11-05T09:55:05Z" + }, + { + "name": "nicolargo/glances", + "version": "v4.4.1", + "date": "2025-11-05T09:08:23Z" + }, + { + "name": "evcc-io/evcc", + "version": "0.209.7", + "date": "2025-11-05T08:32:08Z" + }, + { + "name": "NginxProxyManager/nginx-proxy-manager", + "version": "v2.13.1", + "date": "2025-11-05T06:06:08Z" + }, + { + "name": "jenkinsci/jenkins", + "version": "jenkins-2.535", + "date": "2025-11-05T05:30:07Z" + }, + { + "name": "slskd/slskd", + "version": "0.24.0", + "date": "2025-11-05T02:17:00Z" + }, + { + "name": "Sonarr/Sonarr", + "version": "v4.0.16.2944", + "date": "2025-11-05T01:56:48Z" + }, + { + "name": "gethomepage/homepage", + "version": "v1.6.1", + "date": "2025-11-05T00:21:14Z" + }, + { + "name": "FlareSolverr/FlareSolverr", + "version": "v3.4.4", + "date": "2025-11-04T23:05:14Z" + }, + { + "name": "henrygd/beszel", + "version": "v0.15.4", + "date": "2025-11-04T22:34:12Z" + }, + { + "name": "chrisbenincasa/tunarr", + "version": "v0.23.0-alpha.21", + "date": "2025-11-04T22:05:17Z" + }, + { + "name": "wizarrrr/wizarr", + "version": "v2025.11.1", + "date": "2025-11-04T20:55:51Z" + }, + { + "name": "go-gitea/gitea", + "version": "v1.25.1", + "date": "2025-11-04T20:01:09Z" + }, + { + "name": "runtipi/runtipi", + "version": "v4.6.2", + "date": "2025-11-03T19:45:24Z" + }, + { + "name": "element-hq/synapse", + "version": "v1.142.0rc2", + "date": "2025-11-04T16:22:11Z" + }, + { + "name": "jhuckaby/Cronicle", + "version": "v0.9.100", + "date": "2025-11-04T17:44:39Z" + }, + { + "name": "msgbyte/tianji", + "version": "v1.30.6", + "date": "2025-11-04T17:41:01Z" + }, + { + "name": "meilisearch/meilisearch", + "version": "prototype-v1.24.0.s3-snapshots-4", + "date": "2025-11-04T16:46:01Z" + }, + { + "name": "VictoriaMetrics/VictoriaMetrics", + "version": "v1.129.1", + "date": "2025-11-04T15:15:47Z" + }, + { + "name": "prometheus/alertmanager", + "version": "v0.29.0", + "date": "2025-11-04T15:00:07Z" + }, + { + "name": "cross-seed/cross-seed", + "version": "v6.13.6", + "date": "2025-11-04T13:35:35Z" + }, + { + "name": "OctoPrint/OctoPrint", + "version": "1.11.4", + "date": "2025-11-04T12:43:30Z" + }, + { + "name": "home-assistant/operating-system", + "version": "16.3", + "date": "2025-11-04T12:28:47Z" + }, + { + "name": "syncthing/syncthing", + "version": "v2.0.11", + "date": "2025-11-04T08:51:05Z" + }, + { + "name": "redis/redis", + "version": "8.4-rc1-int2", + "date": "2025-11-03T09:00:38Z" + }, + { + "name": "clusterzx/paperless-ai", + "version": "v3.0.9", + "date": "2025-11-04T07:28:45Z" + }, + { + "name": "esphome/esphome", + "version": "2025.10.4", + "date": "2025-11-04T03:04:13Z" + }, + { + "name": "paperless-ngx/paperless-ngx", + "version": "v2.19.4", + "date": "2025-11-04T01:34:35Z" + }, + { + "name": "hyperion-project/hyperion.ng", + "version": "2.1.1", + "date": "2025-06-14T17:45:06Z" + }, + { + "name": "actualbudget/actual", + "version": "v25.11.0", + "date": "2025-11-04T00:32:21Z" + }, + { + "name": "inventree/InvenTree", + "version": "1.1.2", + "date": "2025-11-03T23:16:29Z" + }, + { + "name": "gtsteffaniak/filebrowser", + "version": "v1.0.0-stable", + "date": "2025-11-03T22:24:23Z" + }, + { + "name": "jupyter/notebook", + "version": "@jupyter-notebook/ui-components@7.5.0-rc.0", + "date": "2025-11-03T19:37:03Z" + }, + { + "name": "dgtlmoon/changedetection.io", + "version": "0.50.39", + "date": "2025-11-03T17:58:41Z" + }, + { + "name": "cloudflare/cloudflared", + "version": "2025.10.1-3-g52809511", + "date": "2025-11-03T17:13:35Z" + }, + { + "name": "goauthentik/authentik", + "version": "version/2025.10.1", + "date": "2025-11-03T16:49:16Z" + }, + { + "name": "Cleanuparr/Cleanuparr", + "version": "v2.4.3", + "date": "2025-11-03T16:49:03Z" + }, + { + "name": "YunoHost/yunohost", + "version": "debian/12.1.34", + "date": "2025-11-03T16:42:07Z" + }, + { + "name": "Paymenter/Paymenter", + "version": "v1.4.2", + "date": "2025-11-03T11:52:53Z" + }, + { + "name": "silverbulletmd/silverbullet", + "version": "2.2.1", + "date": "2025-11-03T06:57:15Z" + }, + { + "name": "fuma-nama/fumadocs", + "version": "fumadocs-mdx@13.0.5", + "date": "2025-11-03T06:55:11Z" + }, + { + "name": "jellyfin/jellyfin", + "version": "v10.11.2", + "date": "2025-11-03T02:29:00Z" + }, + { + "name": "maxdorninger/MediaManager", + "version": "v1.9.1", + "date": "2025-11-02T21:14:50Z" + }, + { + "name": "karlomikus/bar-assistant", + "version": "v5.9.1", + "date": "2025-11-02T20:54:28Z" + }, + { + "name": "tobychui/zoraxy", + "version": "v3.2.9", + "date": "2025-11-02T05:48:39Z" + }, + { + "name": "theonedev/onedev", + "version": "v13.0.10", + "date": "2025-11-02T02:47:45Z" + }, + { + "name": "9001/copyparty", + "version": "v1.19.20", + "date": "2025-11-02T01:27:38Z" + }, + { + "name": "Koenkk/zigbee2mqtt", + "version": "2.6.3", + "date": "2025-11-01T20:48:39Z" + }, + { + "name": "motioneye-project/motioneye", + "version": "0.42.1", + "date": "2020-06-07T07:27:04Z" + }, + { + "name": "Luligu/matterbridge", + "version": "3.3.6", + "date": "2025-11-01T10:41:15Z" + }, + { + "name": "tailscale/tailscale", + "version": "v1.90.6", + "date": "2025-10-31T22:24:04Z" + }, + { + "name": "homarr-labs/homarr", + "version": "v1.43.1", + "date": "2025-10-31T19:15:02Z" + }, + { + "name": "mealie-recipes/mealie", + "version": "v3.4.0", + "date": "2025-10-31T18:50:18Z" + }, + { + "name": "pommee/goaway", + "version": "v0.62.12", + "date": "2025-10-31T17:30:55Z" }, { "name": "zabbix/zabbix", - "version": "7.4.4rc1", - "date": "2025-10-22T09:20:59Z" + "version": "7.4.5", + "date": "2025-10-31T14:39:13Z" }, { - "name": "SigNoz/signoz", - "version": "v0.98.0", - "date": "2025-10-22T06:49:36Z" + "name": "gristlabs/grist-core", + "version": "v1.7.5", + "date": "2025-10-31T13:42:36Z" + }, + { + "name": "plankanban/planka", + "version": "planka-1.1.1", + "date": "2025-10-31T12:38:47Z" + }, + { + "name": "garethgeorge/backrest", + "version": "v1.10.1", + "date": "2025-10-31T08:25:57Z" + }, + { + "name": "pymedusa/Medusa", + "version": "v1.0.24", + "date": "2025-10-30T19:04:42Z" + }, + { + "name": "mongodb/mongo", + "version": "r7.0.26", + "date": "2025-10-30T18:44:14Z" + }, + { + "name": "sassanix/Warracker", + "version": "1.0.2", + "date": "2025-10-30T18:23:23Z" + }, + { + "name": "TwiN/gatus", + "version": "v5.30.0", + "date": "2025-10-30T16:52:58Z" + }, + { + "name": "AdguardTeam/AdGuardHome", + "version": "v0.107.69", + "date": "2025-10-30T15:31:50Z" + }, + { + "name": "Lidarr/Lidarr", + "version": "v3.0.1.4866", + "date": "2025-10-30T14:29:25Z" + }, + { + "name": "danielbrendel/hortusfox-web", + "version": "v5.4", + "date": "2025-10-30T14:25:23Z" + }, + { + "name": "docker/compose", + "version": "v2.40.3", + "date": "2025-10-30T09:35:37Z" + }, + { + "name": "prometheus/prometheus", + "version": "v0.307.3", + "date": "2025-10-30T08:13:40Z" }, { "name": "morpheus65535/bazarr", @@ -115,69 +500,29 @@ "date": "2025-09-20T12:12:33Z" }, { - "name": "fuma-nama/fumadocs", - "version": "create-fumadocs-app@16.0.1", - "date": "2025-10-22T05:44:06Z" + "name": "documenso/documenso", + "version": "v1.13.2", + "date": "2025-10-30T04:12:40Z" }, { - "name": "chrisbenincasa/tunarr", - "version": "v0.23.0-alpha.17", - "date": "2025-10-22T00:33:47Z" + "name": "ipfs/kubo", + "version": "v0.38.2", + "date": "2025-10-30T02:44:09Z" }, { - "name": "msgbyte/tianji", - "version": "v1.30.0", - "date": "2025-10-21T21:37:52Z" + "name": "homebridge/homebridge", + "version": "v1.11.1", + "date": "2025-10-29T22:09:26Z" }, { - "name": "bluenviron/mediamtx", - "version": "v1.15.3", - "date": "2025-10-21T19:56:55Z" + "name": "influxdata/influxdb", + "version": "v2.7.12", + "date": "2025-05-29T17:08:26Z" }, { - "name": "dgtlmoon/changedetection.io", - "version": "0.50.28", - "date": "2025-10-21T19:51:28Z" - }, - { - "name": "mongodb/mongo", - "version": "r8.0.15", - "date": "2025-10-21T19:03:20Z" - }, - { - "name": "jenkinsci/jenkins", - "version": "jenkins-2.533", - "date": "2025-10-21T18:26:10Z" - }, - { - "name": "TwiN/gatus", - "version": "v5.27.2", - "date": "2025-10-21T18:03:22Z" - }, - { - "name": "kyantech/Palmr", - "version": "v3.2.5-beta", - "date": "2025-10-21T16:49:14Z" - }, - { - "name": "n8n-io/n8n", - "version": "n8n@1.116.2", - "date": "2025-10-21T11:39:58Z" - }, - { - "name": "element-hq/synapse", - "version": "v1.140.0", - "date": "2025-10-14T15:57:12Z" - }, - { - "name": "grafana/grafana", - "version": "v12.2.1", - "date": "2025-10-21T14:40:19Z" - }, - { - "name": "crowdsecurity/crowdsec", - "version": "v1.7.2", - "date": "2025-10-21T14:36:48Z" + "name": "zwave-js/zwave-js-ui", + "version": "v11.6.1", + "date": "2025-10-29T16:51:06Z" }, { "name": "laurent22/joplin", @@ -185,14 +530,184 @@ "date": "2025-09-25T13:19:26Z" }, { - "name": "wazuh/wazuh", - "version": "v4.14.0", - "date": "2025-10-21T13:39:55Z" + "name": "heiher/hev-socks5-server", + "version": "2.11.0", + "date": "2025-10-29T14:26:23Z" }, { - "name": "goauthentik/authentik", - "version": "version/2025.10.0-rc2", - "date": "2025-10-21T00:19:36Z" + "name": "cockpit-project/cockpit", + "version": "350", + "date": "2025-10-29T09:51:00Z" + }, + { + "name": "pocket-id/pocket-id", + "version": "v1.14.2", + "date": "2025-10-29T08:37:03Z" + }, + { + "name": "apache/cassandra", + "version": "cassandra-5.0.6", + "date": "2025-10-29T07:40:47Z" + }, + { + "name": "openobserve/openobserve", + "version": "v0.15.3", + "date": "2025-10-29T05:15:45Z" + }, + { + "name": "outline/outline", + "version": "v1.0.1", + "date": "2025-10-29T03:25:13Z" + }, + { + "name": "moghtech/komodo", + "version": "v1.19.5", + "date": "2025-09-27T20:59:46Z" + }, + { + "name": "booklore-app/booklore", + "version": "v1.10.0", + "date": "2025-10-28T19:04:35Z" + }, + { + "name": "netbox-community/netbox", + "version": "v4.4.5", + "date": "2025-10-28T18:35:47Z" + }, + { + "name": "pi-hole/pi-hole", + "version": "v6.2.2", + "date": "2025-10-28T17:07:47Z" + }, + { + "name": "PrivateBin/PrivateBin", + "version": "2.0.2", + "date": "2025-10-28T15:51:35Z" + }, + { + "name": "traefik/traefik", + "version": "v3.5.4", + "date": "2025-10-28T11:09:25Z" + }, + { + "name": "librespeed/speedtest-rust", + "version": "v1.4.0", + "date": "2025-10-28T15:11:12Z" + }, + { + "name": "nzbgetcom/nzbget", + "version": "v25.4", + "date": "2025-10-09T10:27:01Z" + }, + { + "name": "thecfu/scraparr", + "version": "v3.0.0-beta.2", + "date": "2025-10-28T10:16:29Z" + }, + { + "name": "rabbitmq/rabbitmq-server", + "version": "v4.2.0", + "date": "2025-10-27T16:56:40Z" + }, + { + "name": "juanfont/headscale", + "version": "v0.27.0", + "date": "2025-10-27T11:16:35Z" + }, + { + "name": "Radarr/Radarr", + "version": "v5.28.0.10274", + "date": "2025-10-06T21:31:07Z" + }, + { + "name": "openhab/openhab-core", + "version": "5.1.0.M2", + "date": "2025-10-26T14:38:02Z" + }, + { + "name": "ErsatzTV/ErsatzTV", + "version": "v25.8.0", + "date": "2025-10-26T14:23:37Z" + }, + { + "name": "forgejo/forgejo", + "version": "v13.0.2", + "date": "2025-10-26T06:33:05Z" + }, + { + "name": "Prowlarr/Prowlarr", + "version": "v2.1.5.5216", + "date": "2025-10-25T19:41:59Z" + }, + { + "name": "verdaccio/verdaccio", + "version": "v6.2.1", + "date": "2025-10-24T15:40:49Z" + }, + { + "name": "usememos/memos", + "version": "v0.25.2", + "date": "2025-10-24T12:30:04Z" + }, + { + "name": "sabnzbd/sabnzbd", + "version": "4.5.5", + "date": "2025-10-24T11:12:22Z" + }, + { + "name": "crowdsecurity/crowdsec", + "version": "v1.7.3", + "date": "2025-10-24T10:51:12Z" + }, + { + "name": "pocketbase/pocketbase", + "version": "v0.31.0", + "date": "2025-10-24T04:07:27Z" + }, + { + "name": "drakkan/sftpgo", + "version": "v2.7.0", + "date": "2025-10-23T17:15:07Z" + }, + { + "name": "HabitRPG/habitica", + "version": "v5.41.5", + "date": "2025-10-23T15:12:42Z" + }, + { + "name": "Kareadita/Kavita", + "version": "v0.8.8.3", + "date": "2025-10-23T12:31:49Z" + }, + { + "name": "rcourtman/Pulse", + "version": "issue-596", + "date": "2025-10-22T19:48:56Z" + }, + { + "name": "louislam/uptime-kuma", + "version": "2.0.2", + "date": "2025-10-22T17:03:54Z" + }, + { + "name": "NLnetLabs/unbound", + "version": "release-1.24.1", + "date": "2025-10-22T10:28:00Z" + }, + { + "name": "bluenviron/mediamtx", + "version": "v1.15.3", + "date": "2025-10-21T19:56:55Z" + }, + { + "name": "kyantech/Palmr", + "version": "v3.2.5-beta", + "date": "2025-10-21T16:49:14Z" + }, + { + "name": "grafana/grafana", + "version": "v12.2.1", + "date": "2025-10-21T14:40:19Z" }, { "name": "AlexxIT/go2rtc", @@ -204,111 +719,21 @@ "version": "v1.36.3", "date": "2025-10-21T12:53:58Z" }, - { - "name": "apache/cassandra", - "version": "5.0.6-tentative", - "date": "2025-10-21T11:42:35Z" - }, - { - "name": "evcc-io/evcc", - "version": "0.209.3", - "date": "2025-10-21T10:53:07Z" - }, - { - "name": "VictoriaMetrics/VictoriaMetrics", - "version": "pmm-6401-v1.128.0", - "date": "2025-10-21T08:30:52Z" - }, - { - "name": "meilisearch/meilisearch", - "version": "prototype-v1.24.0.ignore-embedding-failures-2", - "date": "2025-10-21T07:36:22Z" - }, - { - "name": "openobserve/openobserve", - "version": "v0.16.0-rc1", - "date": "2025-10-21T00:37:47Z" - }, - { - "name": "documenso/documenso", - "version": "v1.13.0", - "date": "2025-10-21T00:21:04Z" - }, - { - "name": "henrygd/beszel", - "version": "v0.14.1", - "date": "2025-10-20T22:10:56Z" - }, - { - "name": "booklore-app/booklore", - "version": "v1.8.1", - "date": "2025-10-20T20:53:56Z" - }, { "name": "coder/code-server", "version": "v4.105.1", "date": "2025-10-20T20:19:23Z" }, - { - "name": "pymedusa/Medusa", - "version": "v1.0.23", - "date": "2025-10-20T19:51:33Z" - }, { "name": "MediaBrowser/Emby.Releases", "version": "4.9.1.80", "date": "2025-09-30T20:25:16Z" }, - { - "name": "tailscale/tailscale", - "version": "v1.91.0-pre", - "date": "2025-10-20T16:18:51Z" - }, { "name": "rclone/rclone", "version": "v1.71.2", "date": "2025-10-20T15:25:52Z" }, - { - "name": "Graylog2/graylog2-server", - "version": "7.0.0-rc.1", - "date": "2025-10-20T11:53:31Z" - }, - { - "name": "Kareadita/Kavita", - "version": "v0.8.8", - "date": "2025-10-20T11:26:24Z" - }, - { - "name": "wizarrrr/wizarr", - "version": "v2025.10.4", - "date": "2025-10-20T10:45:54Z" - }, - { - "name": "jupyter/notebook", - "version": "@jupyter-notebook/ui-components@7.5.0-beta.1", - "date": "2025-10-20T07:01:38Z" - }, - { - "name": "inventree/InvenTree", - "version": "1.0.7", - "date": "2025-10-20T05:23:10Z" - }, - { - "name": "firefly-iii/firefly-iii", - "version": "v6.4.2", - "date": "2025-10-07T08:11:58Z" - }, - { - "name": "jellyfin/jellyfin", - "version": "v10.11.0", - "date": "2025-10-20T00:45:19Z" - }, - { - "name": "esphome/esphome", - "version": "2025.10.2", - "date": "2025-10-20T00:42:57Z" - }, { "name": "pelican-dev/panel", "version": "v1.0.0-beta27", @@ -319,11 +744,6 @@ "version": "5.2.3", "date": "2025-10-19T20:50:15Z" }, - { - "name": "verdaccio/verdaccio", - "version": "generator-verdaccio-plugin@6.0.0-next-8.24", - "date": "2025-10-19T19:43:46Z" - }, { "name": "Part-DB/Part-DB-server", "version": "v2.2.1", @@ -334,46 +754,16 @@ "version": "v13.0.0", "date": "2025-10-19T10:03:18Z" }, - { - "name": "Prowlarr/Prowlarr", - "version": "v2.0.5.5160", - "date": "2025-08-23T21:23:11Z" - }, - { - "name": "Lidarr/Lidarr", - "version": "v2.14.5.4836", - "date": "2025-10-08T15:30:50Z" - }, - { - "name": "Luligu/matterbridge", - "version": "3.3.3", - "date": "2025-10-18T22:27:42Z" - }, { "name": "ellite/Wallos", "version": "v4.5.0", "date": "2025-10-18T22:00:50Z" }, - { - "name": "leiweibau/Pi.Alert", - "version": "v2025-10-18", - "date": "2025-10-18T20:35:54Z" - }, { "name": "project-zot/zot", "version": "v2.1.10", "date": "2025-10-18T18:46:36Z" }, - { - "name": "homarr-labs/homarr", - "version": "v1.42.1", - "date": "2025-10-18T18:31:38Z" - }, - { - "name": "Notifiarr/notifiarr", - "version": "v0.9.0", - "date": "2025-10-18T17:03:56Z" - }, { "name": "TasmoAdmin/TasmoAdmin", "version": "v4.3.2", @@ -384,36 +774,6 @@ "version": "0.20.4", "date": "2025-10-18T10:00:42Z" }, - { - "name": "theonedev/onedev", - "version": "v13.0.9", - "date": "2025-10-18T09:59:25Z" - }, - { - "name": "runtipi/runtipi", - "version": "v4.5.1", - "date": "2025-10-18T08:12:19Z" - }, - { - "name": "nzbgetcom/nzbget", - "version": "v25.4", - "date": "2025-10-09T10:27:01Z" - }, - { - "name": "9001/copyparty", - "version": "v1.19.17", - "date": "2025-10-17T23:40:02Z" - }, - { - "name": "home-assistant/core", - "version": "2025.10.3", - "date": "2025-10-17T21:15:07Z" - }, - { - "name": "forgejo/forgejo", - "version": "v13.0.1", - "date": "2025-10-17T18:54:16Z" - }, { "name": "grokability/snipe-it", "version": "v8.3.4", @@ -424,26 +784,6 @@ "version": "v4.6.1", "date": "2025-10-17T15:21:59Z" }, - { - "name": "neo4j/neo4j", - "version": "5.26.14", - "date": "2025-10-17T12:38:22Z" - }, - { - "name": "zwave-js/zwave-js-ui", - "version": "v11.5.2", - "date": "2025-10-17T08:20:13Z" - }, - { - "name": "pocketbase/pocketbase", - "version": "v0.30.4", - "date": "2025-10-17T08:03:10Z" - }, - { - "name": "juanfont/headscale", - "version": "v0.26.1", - "date": "2025-06-06T11:22:02Z" - }, { "name": "diced/zipline", "version": "v4.3.2", @@ -454,16 +794,6 @@ "version": "v1.5.0", "date": "2025-10-16T23:14:45Z" }, - { - "name": "openhab/openhab-core", - "version": "5.0.2", - "date": "2025-10-16T21:27:35Z" - }, - { - "name": "ollama/ollama", - "version": "v0.12.6", - "date": "2025-10-16T20:07:41Z" - }, { "name": "minio/minio", "version": "RELEASE.2025-10-15T17-29-55Z", @@ -474,46 +804,16 @@ "version": "v0.6.34", "date": "2025-10-16T16:55:58Z" }, - { - "name": "tobychui/zoraxy", - "version": "v3.2.8", - "date": "2025-10-16T14:21:48Z" - }, - { - "name": "zitadel/zitadel", - "version": "v4.4.0", - "date": "2025-10-16T07:20:34Z" - }, { "name": "cloudreve/cloudreve", "version": "4.9.2", "date": "2025-10-16T03:24:44Z" }, - { - "name": "outline/outline", - "version": "v1.0.0-test8", - "date": "2025-10-16T01:32:14Z" - }, { "name": "Ombi-app/Ombi", "version": "v4.47.1", "date": "2025-01-05T21:14:23Z" }, - { - "name": "netbox-community/netbox", - "version": "v4.4.4", - "date": "2025-10-15T19:27:01Z" - }, - { - "name": "immich-app/immich", - "version": "v2.1.0", - "date": "2025-10-15T19:24:14Z" - }, - { - "name": "karlomikus/bar-assistant", - "version": "v5.9.0", - "date": "2025-10-15T18:27:56Z" - }, { "name": "linkwarden/linkwarden", "version": "v2.13.1", @@ -524,11 +824,6 @@ "version": "2.3.3", "date": "2025-10-15T13:18:27Z" }, - { - "name": "cockpit-project/cockpit", - "version": "349", - "date": "2025-10-15T11:43:12Z" - }, { "name": "blakeblackshear/frigate", "version": "v0.14.1", @@ -544,26 +839,11 @@ "version": "preview-seerr", "date": "2025-10-14T22:21:33Z" }, - { - "name": "cloudflare/cloudflared", - "version": "2025.10.0", - "date": "2025-10-14T19:07:37Z" - }, { "name": "crafty-controller/crafty-4", "version": "v4.5.5", "date": "2025-10-14T18:48:36Z" }, - { - "name": "plankanban/planka", - "version": "planka-1.1.0", - "date": "2025-10-14T16:51:22Z" - }, - { - "name": "home-assistant/operating-system", - "version": "16.2", - "date": "2025-09-08T14:03:25Z" - }, { "name": "rogerfar/rdt-client", "version": "v2.0.119", @@ -579,21 +859,11 @@ "version": "4.1.1", "date": "2025-10-13T14:23:53Z" }, - { - "name": "prometheus/alertmanager", - "version": "v0.29.0-rc.0", - "date": "2025-10-10T01:13:27Z" - }, { "name": "globaleaks/globaleaks-whistleblowing-software", "version": "v5.0.85", "date": "2025-10-12T19:55:18Z" }, - { - "name": "PrivateBin/PrivateBin", - "version": "2.0.1", - "date": "2025-10-12T10:00:52Z" - }, { "name": "authelia/authelia", "version": "v4.39.13", @@ -609,11 +879,6 @@ "version": "v0.27.0", "date": "2025-10-10T20:11:48Z" }, - { - "name": "getumbrel/umbrel", - "version": "1.4.2", - "date": "2025-05-09T08:54:49Z" - }, { "name": "Brandawg93/PeaNUT", "version": "v5.16.0", @@ -624,91 +889,21 @@ "version": "v1.17.1", "date": "2025-10-10T16:12:41Z" }, - { - "name": "apache/tomcat", - "version": "10.1.48", - "date": "2025-10-10T14:46:53Z" - }, - { - "name": "semaphoreui/semaphore", - "version": "v2.16.34", - "date": "2025-10-10T11:57:38Z" - }, - { - "name": "azukaar/Cosmos-Server", - "version": "v0.18.4", - "date": "2025-04-05T19:12:57Z" - }, - { - "name": "emqx/emqx", - "version": "e6.0.1-alpha.1", - "date": "2025-10-10T06:57:48Z" - }, - { - "name": "mealie-recipes/mealie", - "version": "v3.3.2", - "date": "2025-10-10T03:45:06Z" - }, { "name": "projectsend/projectsend", "version": "r1945", "date": "2025-10-10T02:30:05Z" }, - { - "name": "FlareSolverr/FlareSolverr", - "version": "v3.4.2", - "date": "2025-10-09T19:05:48Z" - }, - { - "name": "ErsatzTV/ErsatzTV", - "version": "v25.7.1", - "date": "2025-10-09T15:42:11Z" - }, - { - "name": "silverbulletmd/silverbullet", - "version": "2.1.9", - "date": "2025-10-09T13:57:14Z" - }, - { - "name": "glpi-project/glpi", - "version": "11.0.1", - "date": "2025-10-09T12:34:15Z" - }, - { - "name": "rabbitmq/rabbitmq-server", - "version": "v4.1.4", - "date": "2025-09-02T14:26:24Z" - }, - { - "name": "ipfs/kubo", - "version": "v0.38.1", - "date": "2025-10-08T21:34:07Z" - }, { "name": "autobrr/autobrr", "version": "v1.68.0", "date": "2025-10-08T18:33:12Z" }, - { - "name": "AdguardTeam/AdGuardHome", - "version": "v0.107.67", - "date": "2025-09-29T14:45:57Z" - }, { "name": "advplyr/audiobookshelf", "version": "v2.30.0", "date": "2025-10-08T16:03:49Z" }, - { - "name": "nicolargo/glances", - "version": "v4.3.3", - "date": "2025-10-08T15:45:21Z" - }, - { - "name": "FlowiseAI/Flowise", - "version": "flowise@3.0.8", - "date": "2025-10-08T12:19:18Z" - }, { "name": "gotson/komga", "version": "1.23.5", @@ -724,30 +919,15 @@ "version": "v0.15.1", "date": "2025-10-07T20:30:56Z" }, - { - "name": "pocket-id/pocket-id", - "version": "v1.13.1", - "date": "2025-10-07T06:32:50Z" - }, - { - "name": "sassanix/Warracker", - "version": "0.10.1.14", - "date": "2025-10-06T23:35:16Z" - }, - { - "name": "Radarr/Radarr", - "version": "v5.28.0.10274", - "date": "2025-10-06T21:31:07Z" - }, { "name": "Kometa-Team/Kometa", "version": "v2.2.2", "date": "2025-10-06T21:31:07Z" }, { - "name": "bunkerity/bunkerweb", - "version": "v1.6.5", - "date": "2025-10-06T15:25:17Z" + "name": "mysql/mysql-server", + "version": "mysql-cluster-7.6.36", + "date": "2025-10-06T15:19:49Z" }, { "name": "bastienwirtz/homer", @@ -759,51 +939,16 @@ "version": "v1.5.9", "date": "2025-10-06T08:34:01Z" }, - { - "name": "hyperion-project/hyperion.ng", - "version": "2.1.1", - "date": "2025-06-14T17:45:06Z" - }, { "name": "BookStackApp/BookStack", "version": "v25.07.3", "date": "2025-10-05T14:47:20Z" }, - { - "name": "pommee/goaway", - "version": "v0.62.11", - "date": "2025-10-05T07:31:57Z" - }, { "name": "webmin/webmin", "version": "2.520", "date": "2025-10-05T00:51:34Z" }, - { - "name": "redis/redis", - "version": "8.2.2", - "date": "2025-10-03T06:22:38Z" - }, - { - "name": "actualbudget/actual", - "version": "v25.10.0", - "date": "2025-10-02T11:34:39Z" - }, - { - "name": "Koenkk/zigbee2mqtt", - "version": "2.6.2", - "date": "2025-10-01T17:51:09Z" - }, - { - "name": "Kozea/Radicale", - "version": "v3.5.7.pypi", - "date": "2025-10-01T05:32:27Z" - }, - { - "name": "HabitRPG/habitica", - "version": "v5.41.4", - "date": "2025-09-30T22:26:11Z" - }, { "name": "WordPress/WordPress", "version": "4.7.31", @@ -814,26 +959,11 @@ "version": "v2.33.0", "date": "2025-09-30T16:18:10Z" }, - { - "name": "gristlabs/grist-core", - "version": "v1.7.4", - "date": "2025-09-30T13:34:30Z" - }, { "name": "thomiceli/opengist", "version": "v1.11.1", "date": "2025-09-30T00:24:16Z" }, - { - "name": "Cleanuparr/Cleanuparr", - "version": "v2.3.3", - "date": "2025-09-29T18:53:35Z" - }, - { - "name": "influxdata/influxdb", - "version": "v2.7.12", - "date": "2025-05-29T17:08:26Z" - }, { "name": "MDeLuise/plant-it", "version": "1.0.0", @@ -859,31 +989,11 @@ "version": "1.27.1", "date": "2025-09-27T13:07:26Z" }, - { - "name": "javedh-dev/tracktor", - "version": "0.3.18", - "date": "2025-09-27T10:32:09Z" - }, { "name": "Dolibarr/dolibarr", "version": "22.0.2", "date": "2025-09-27T01:43:20Z" }, - { - "name": "cross-seed/cross-seed", - "version": "v6.13.5", - "date": "2025-09-27T01:10:59Z" - }, - { - "name": "traefik/traefik", - "version": "v3.5.3", - "date": "2025-09-26T09:31:01Z" - }, - { - "name": "go-gitea/gitea", - "version": "v1.26.0-dev", - "date": "2025-09-24T16:45:38Z" - }, { "name": "Threadfin/Threadfin", "version": "1.2.39", @@ -894,26 +1004,11 @@ "version": "2025.09.24", "date": "2025-09-24T13:51:23Z" }, - { - "name": "mysql/mysql-server", - "version": "mysql-cluster-8.4.7", - "date": "2025-09-24T12:23:38Z" - }, - { - "name": "syncthing/syncthing", - "version": "v2.0.10", - "date": "2025-09-24T08:33:37Z" - }, { "name": "postgres/postgres", "version": "REL_18_0", "date": "2025-09-22T20:11:33Z" }, - { - "name": "gethomepage/homepage", - "version": "v1.5.0", - "date": "2025-09-22T15:28:49Z" - }, { "name": "itsmng/itsm-ng", "version": "v2.1.0", @@ -954,11 +1049,6 @@ "version": "2.1.0-test1", "date": "2025-09-17T18:21:45Z" }, - { - "name": "heiher/hev-socks5-server", - "version": "2.10.0", - "date": "2025-09-17T14:47:00Z" - }, { "name": "icereed/paperless-gpt", "version": "v0.23.0", @@ -974,11 +1064,6 @@ "version": "v2.4.0p12", "date": "2025-09-16T12:53:03Z" }, - { - "name": "Paymenter/Paymenter", - "version": "v1.3.4", - "date": "2025-09-15T20:48:02Z" - }, { "name": "apache/tika", "version": "3.2.0", @@ -989,11 +1074,6 @@ "version": "v2.7.6", "date": "2025-09-15T15:50:44Z" }, - { - "name": "usememos/memos", - "version": "v0.25.1", - "date": "2025-09-15T14:57:30Z" - }, { "name": "karakeep-app/karakeep", "version": "cli/v0.27.1", @@ -1019,11 +1099,6 @@ "version": "2.1.4", "date": "2025-09-10T12:08:09Z" }, - { - "name": "OctoPrint/OctoPrint", - "version": "1.11.3", - "date": "2025-09-09T08:03:31Z" - }, { "name": "Tautulli/Tautulli", "version": "v2.16.0", @@ -1059,11 +1134,6 @@ "version": "1.7.0", "date": "2025-08-28T18:10:59Z" }, - { - "name": "garethgeorge/backrest", - "version": "v1.9.2", - "date": "2025-08-28T07:06:14Z" - }, { "name": "plexguide/Huntarr.io", "version": "8.2.10", @@ -1079,11 +1149,6 @@ "version": "v0.21.0", "date": "2025-08-23T18:33:53Z" }, - { - "name": "maxdorninger/MediaManager", - "version": "1.8.0", - "date": "2025-08-23T16:22:30Z" - }, { "name": "caddyserver/caddy", "version": "v2.10.2", @@ -1134,11 +1199,6 @@ "version": "v2.5.308", "date": "2025-08-13T07:09:29Z" }, - { - "name": "slskd/slskd", - "version": "0.23.2", - "date": "2025-08-10T23:35:07Z" - }, { "name": "ioBroker/ioBroker", "version": "1012-08-09", @@ -1169,21 +1229,11 @@ "version": "v2.1.1867", "date": "2025-07-31T18:08:43Z" }, - { - "name": "danielbrendel/hortusfox-web", - "version": "v5.2", - "date": "2025-07-30T10:40:00Z" - }, { "name": "dani-garcia/vaultwarden", "version": "1.34.3", "date": "2025-07-30T09:10:59Z" }, - { - "name": "OliveTin/OliveTin", - "version": "2025.7.29", - "date": "2025-07-29T22:20:13Z" - }, { "name": "caddyserver/xcaddy", "version": "v0.4.5", @@ -1209,26 +1259,11 @@ "version": "v2.1.1", "date": "2025-07-15T22:38:01Z" }, - { - "name": "pi-hole/pi-hole", - "version": "v6.1.4", - "date": "2025-07-14T21:22:17Z" - }, - { - "name": "homebridge/homebridge", - "version": "v1.11.0", - "date": "2025-07-13T19:22:47Z" - }, { "name": "mayswind/AriaNg", "version": "1.3.11", "date": "2025-07-13T13:33:48Z" }, - { - "name": "NginxProxyManager/nginx-proxy-manager", - "version": "v2.12.6", - "date": "2025-07-09T21:52:15Z" - }, { "name": "photoprism/photoprism", "version": "250707-d28b3101e", @@ -1249,26 +1284,11 @@ "version": "v29.0", "date": "2025-06-30T03:52:33Z" }, - { - "name": "librespeed/speedtest-rust", - "version": "v1.3.8", - "date": "2025-06-29T07:41:53Z" - }, { "name": "arunavo4/gitea-mirror", "version": "v2.18.0", "date": "2025-06-24T08:29:55Z" }, - { - "name": "clusterzx/paperless-ai", - "version": "v3.0.7", - "date": "2025-06-22T17:49:29Z" - }, - { - "name": "Sonarr/Sonarr", - "version": "v4.0.15.2941", - "date": "2025-06-20T17:20:54Z" - }, { "name": "prometheus-pve/prometheus-pve-exporter", "version": "v3.5.5", @@ -1314,11 +1334,6 @@ "version": "v0.0.8", "date": "2025-05-18T11:37:31Z" }, - { - "name": "motioneye-project/motioneye", - "version": "0.42.1", - "date": "2020-06-07T07:27:04Z" - }, { "name": "stackblitz-labs/bolt.diy", "version": "1.0.0", @@ -1334,11 +1349,6 @@ "version": "2025-05-07-r1", "date": "2025-05-07T12:18:42Z" }, - { - "name": "apache/couchdb", - "version": "3.5.0", - "date": "2025-05-05T16:28:24Z" - }, { "name": "TechnitiumSoftware/DnsServer", "version": "v13.6.0", @@ -1409,11 +1419,6 @@ "version": "v0.22.1", "date": "2025-03-18T21:01:22Z" }, - { - "name": "transmission/transmission", - "version": "4.0.1-beta.1", - "date": "2024-12-13T00:16:24Z" - }, { "name": "excalidraw/excalidraw", "version": "v0.18.0", @@ -1444,11 +1449,6 @@ "version": "v1.11.2", "date": "2025-02-24T19:47:06Z" }, - { - "name": "drakkan/sftpgo", - "version": "v2.6.6", - "date": "2025-02-24T19:14:46Z" - }, { "name": "babybuddy/babybuddy", "version": "v2.7.1", diff --git a/frontend/public/json/wireguard.json b/frontend/public/json/wireguard.json index a26317f93..1a557dbd3 100644 --- a/frontend/public/json/wireguard.json +++ b/frontend/public/json/wireguard.json @@ -48,7 +48,7 @@ "type": "info" }, { - "text": "WGDashboard installation is optional.`", + "text": "WGDashboard installation is optional.", "type": "info" } ] diff --git a/frontend/src/config/site-config.tsx b/frontend/src/config/site-config.tsx index f08822aaf..1f53980fa 100644 --- a/frontend/src/config/site-config.tsx +++ b/frontend/src/config/site-config.tsx @@ -58,8 +58,8 @@ export const OperatingSystems: OperatingSystem[] = [ { name: "Debian", versions: [ - { name: "11", slug: "bullseye" }, { name: "12", slug: "bookworm" }, + { name: "13", slug: "trixie" }, ], }, { diff --git a/install/alpine-garage-install.sh b/install/alpine-garage-install.sh new file mode 100644 index 000000000..c5497c2ba --- /dev/null +++ b/install/alpine-garage-install.sh @@ -0,0 +1,84 @@ +#!/usr/bin/env bash + +# Copyright (c) 2021-2025 community-scripts ORG +# Author: MickLesk (CanbiZ) +# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE +# Source: https://garagehq.deuxfleurs.fr/ + +source /dev/stdin <<<"$FUNCTIONS_FILE_PATH" +color +verb_ip6 +catch_errors +setting_up_container +network_check +update_os + +msg_info "Installing Dependencies" +$STD apk add --no-cache openssl +msg_ok "Installed Dependencies" + +GITEA_RELEASE=$(curl -s https://api.github.com/repos/deuxfleurs-org/garage/tags | jq -r '.[0].name') +curl -fsSL "https://garagehq.deuxfleurs.fr/_releases/${GITEA_RELEASE}/x86_64-unknown-linux-musl/garage" -o /usr/local/bin/garage +chmod +x /usr/local/bin/garage +mkdir -p /var/lib/garage/{data,meta,snapshots} +mkdir -p /etc/garage +RPC_SECRET=$(openssl rand -hex 64 | cut -c1-64) +ADMIN_TOKEN=$(openssl rand -base64 32) +METRICS_TOKEN=$(openssl rand -base64 32) +{ + echo "Garage Tokens and Secrets" + echo "RPC Secret: $RPC_SECRET" + echo "Admin Token: $ADMIN_TOKEN" + echo "Metrics Token: $METRICS_TOKEN" +} >~/garage.creds +echo $GITEA_RELEASE >>~/.garage +cat </etc/garage.toml +metadata_dir = "/var/lib/garage/meta" +data_dir = "/var/lib/garage/data" +db_engine = "sqlite" +replication_factor = 1 + +rpc_bind_addr = "0.0.0.0:3901" +rpc_public_addr = "127.0.0.1:3901" +rpc_secret = "${RPC_SECRET}" + +[s3_api] +s3_region = "garage" +api_bind_addr = "0.0.0.0:3900" +root_domain = ".s3.garage" + +[s3_web] +bind_addr = "0.0.0.0:3902" +root_domain = ".web.garage" +index = "index.html" + +[k2v_api] +api_bind_addr = "0.0.0.0:3904" + +[admin] +api_bind_addr = "0.0.0.0:3903" +admin_token = "${ADMIN_TOKEN}" +metrics_token = "${METRICS_TOKEN}" +EOF +msg_ok "Configured Garage" + +msg_info "Creating Service" +cat <<'EOF' >/etc/init.d/garage +#!/sbin/openrc-run +name="Garage Object Storage" +command="/usr/local/bin/garage" +command_args="server" +command_background="yes" +pidfile="/run/garage.pid" +depend() { + need net +} +EOF + +chmod +x /etc/init.d/garage +$STD rc-update add garage default +$STD rc-service garage restart || rc-service garage start +msg_ok "Service active" + +motd_ssh +customize diff --git a/install/archivebox-install.sh b/install/archivebox-install.sh index a6943fa6a..8c9e13e74 100644 --- a/install/archivebox-install.sh +++ b/install/archivebox-install.sh @@ -22,7 +22,8 @@ $STD apt-get install -y \ libsasl2-dev \ procps \ dnsutils \ - ripgrep + ripgrep \ + chromium msg_ok "Installed Dependencies" msg_info "Installing Python Dependencies" @@ -32,7 +33,7 @@ $STD apt-get install -y \ python3-regex msg_ok "Installed Python Dependencies" -NODE_VERSION="22" setup_nodejs +NODE_VERSION="22" NODE_MODULE="@postlight/parser@latest,single-file-cli@latest" setup_nodejs PYTHON_VERSION="3.13" setup_uv msg_info "Installing Playwright" @@ -40,7 +41,7 @@ $STD uv pip install playwright --system $STD playwright install-deps chromium msg_ok "Installed Playwright" -msg_info "Installing Chromium and ArchiveBox" +msg_info "Installing ArchiveBox" mkdir -p /opt/archivebox/{data,.npm,.cache,.local} $STD adduser --system --shell /bin/bash --gecos 'Archive Box User' --group --disabled-password --home /home/archivebox archivebox chown -R archivebox:archivebox /opt/archivebox/{data,.npm,.cache,.local} @@ -92,6 +93,7 @@ motd_ssh customize msg_info "Cleaning up" -$STD apt-get -y autoremove -$STD apt-get -y autoclean +$STD apt -y autoremove +$STD apt -y autoclean +$STD apt -y clean msg_ok "Cleaned" diff --git a/install/asterisk-install.sh b/install/asterisk-install.sh index adb53406e..202c12e10 100644 --- a/install/asterisk-install.sh +++ b/install/asterisk-install.sh @@ -13,8 +13,66 @@ setting_up_container network_check update_os +ASTERISK_VERSIONS_URL="https://www.asterisk.org/downloads/asterisk/all-asterisk-versions/" +html=$(curl -fsSL "$ASTERISK_VERSIONS_URL") + +LTS_VERSION="" +for major in 20 22 24 26; do + block=$(echo "$html" | awk "/Asterisk $major - LTS/,/
    /" || true) + ver=$(echo "$block" | grep -oE 'Download Latest - [0-9]+\.[0-9]+(\.[0-9]+)?' | head -n1 | sed -E 's/.* - //' || true) + if [ -n "$ver" ]; then + LTS_VERSION="$LTS_VERSION $ver" + fi + unset ver block +done +LTS_VERSION=$(echo "$LTS_VERSION" | xargs | tr ' ' '\n' | sort -V | tail -n1) + +STD_VERSION="" +for major in 21 23 25 27; do + block=$(echo "$html" | grep -A 20 "Asterisk $major" | head -n 20 || true) + ver=$(echo "$block" | grep -oE 'Download (Latest - )?'"$major"'\.[0-9]+\.[0-9]+' | head -n1 | sed -E 's/Download (Latest - )?//' || true) + if [ -n "$ver" ]; then + STD_VERSION="$STD_VERSION $ver" + fi + unset ver block +done +STD_VERSION=$(echo "$STD_VERSION" | xargs | tr ' ' '\n' | sort -V | tail -n1) + +cert_block=$(echo "$html" | awk '/Certified Asterisk/,/
      /') +CERT_VERSION=$(echo "$cert_block" | grep -oE 'Download Latest - [0-9]+\.[0-9]+-cert[0-9]+' | head -n1 | sed -E 's/.* - //' || true) + +cat </etc/systemd/system/bentopdf.service +[Unit] +Description=BentoPDF Service +After=network.target + +[Service] +Type=simple +WorkingDirectory=/opt/bentopdf +ExecStart=/usr/bin/npx serve dist -p 8080 +Restart=always +RestartSec=10 + +[Install] +WantedBy=multi-user.target +EOF + +systemctl enable -q --now bentopdf +msg_ok "Created & started service" + +motd_ssh +customize + +msg_info "Cleaning up" +$STD apt -y autoremove +$STD apt -y autoclean +$STD apt -y clean +msg_ok "Cleaned" diff --git a/install/booklore-install.sh b/install/booklore-install.sh index 6f67537d2..e95067b72 100644 --- a/install/booklore-install.sh +++ b/install/booklore-install.sh @@ -77,7 +77,8 @@ msg_info "Configure Nginx" rm -rf /usr/share/nginx/html ln -s /opt/booklore/booklore-ui/dist/booklore/browser /usr/share/nginx/html cp /opt/booklore/nginx.conf /etc/nginx/nginx.conf -sed -i "s/listen \${BOOKLORE_PORT};/listen 6060;/" /etc/nginx/nginx.conf +sed -i 's/listen \${BOOKLORE_PORT};/listen 6060;/' /etc/nginx/nginx.conf +sed -i 's/listen \[::\]:${BOOKLORE_PORT};/listen [::]:6060;/' /etc/nginx/nginx.conf systemctl restart nginx msg_ok "Configured Nginx" diff --git a/install/comfyui-install.sh b/install/comfyui-install.sh new file mode 100644 index 000000000..4f5b7de41 --- /dev/null +++ b/install/comfyui-install.sh @@ -0,0 +1,87 @@ +#!/usr/bin/env bash + +# Copyright (c) 2021-2025 community-scripts ORG +# Author: jdacode +# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE +# Source: https://github.com/comfyanonymous/ComfyUI + +source /dev/stdin <<<"$FUNCTIONS_FILE_PATH" +color +verb_ip6 +catch_errors +setting_up_container +network_check +update_os + +echo +echo "${TAB3}Choose the GPU type for ComfyUI:" +echo "${TAB3}[1]-None [2]-NVIDIA [3]-AMD [4]-Intel" +read -rp "${TAB3}Enter your choice [1-4] (default: 1): " gpu_choice +gpu_choice=${gpu_choice:-1} +case "$gpu_choice" in +1) comfyui_gpu_type="none";; +2) comfyui_gpu_type="nvidia";; +3) comfyui_gpu_type="amd";; +4) comfyui_gpu_type="intel";; +*) comfyui_gpu_type="none"; echo "${TAB3}Invalid choice. Defaulting to ${comfyui_gpu_type}." ;; +esac +echo + +PYTHON_VERSION="3.12" setup_uv + +fetch_and_deploy_gh_release "ComfyUI" "comfyanonymous/ComfyUI" "tarball" "latest" "/opt/ComfyUI" + +msg_info "Python dependencies" +$STD uv venv "/opt/ComfyUI/venv" +if [[ "${comfyui_gpu_type,,}" == "nvidia" ]]; then + $STD uv pip install \ + torch \ + torchvision \ + torchaudio \ + --extra-index-url "https://download.pytorch.org/whl/cu128" \ + --python="/opt/ComfyUI/venv/bin/python" +elif [[ "${comfyui_gpu_type,,}" == "amd" ]]; then + $STD uv pip install \ + torch \ + torchvision \ + torchaudio \ + --index-url "https://download.pytorch.org/whl/rocm6.3" \ + --python="/opt/ComfyUI/venv/bin/python" +elif [[ "${comfyui_gpu_type,,}" == "intel" ]]; then + $STD uv pip install \ + torch \ + torchvision \ + torchaudio \ + --index-url "https://download.pytorch.org/whl/xpu" \ + --python="/opt/ComfyUI/venv/bin/python" +fi +$STD uv pip install -r "/opt/ComfyUI/requirements.txt" --python="/opt/ComfyUI/venv/bin/python" +msg_ok "Python dependencies" + +msg_info "Creating Service" +cat </etc/systemd/system/comfyui.service +[Unit] +Description=ComfyUI Service +After=network.target + +[Service] +Type=simple +User=root +WorkingDirectory=/opt/ComfyUI +ExecStart=/opt/ComfyUI/venv/bin/python /opt/ComfyUI/main.py --listen --port 8188 --cpu +Restart=on-failure + +[Install] +WantedBy=multi-user.target +EOF +systemctl enable -q --now comfyui +msg_ok "Created Service" + +motd_ssh +customize + +msg_info "Cleaning up" +$STD apt -y autoremove +$STD apt -y autoclean +$STD apt -y clean +msg_ok "Cleaned" diff --git a/install/dispatcharr-install.sh b/install/dispatcharr-install.sh new file mode 100644 index 000000000..69b3682ed --- /dev/null +++ b/install/dispatcharr-install.sh @@ -0,0 +1,268 @@ +#!/usr/bin/env bash + +# Copyright (c) 2021-2025 community-scripts ORG +# Author: ekke85 +# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE +# Source: https://github.com/Dispatcharr/Dispatcharr + +source /dev/stdin <<<"$FUNCTIONS_FILE_PATH" +color +verb_ip6 +catch_errors +setting_up_container +network_check +update_os + +msg_info "Installing Dependencies" +$STD apt install -y \ + build-essential \ + python3-dev \ + libpq-dev \ + nginx \ + redis-server \ + ffmpeg \ + procps \ + streamlink +msg_ok "Installed Dependencies" + +setup_uv +NODE_VERSION="24" setup_nodejs +PG_VERSION="16" setup_postgresql + +msg_info "Creating PostgreSQL Database" +DB_NAME=dispatcharr_db +DB_USER=dispatcharr_usr +DB_PASS="$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | cut -c1-13)" +$STD sudo -u postgres psql -c "CREATE ROLE $DB_USER WITH LOGIN PASSWORD '$DB_PASS';" +$STD sudo -u postgres psql -c "CREATE DATABASE $DB_NAME WITH OWNER $DB_USER ENCODING 'UTF8' TEMPLATE template0;" +$STD sudo -u postgres psql -c "ALTER ROLE $DB_USER SET client_encoding TO 'utf8';" +$STD sudo -u postgres psql -c "ALTER ROLE $DB_USER SET default_transaction_isolation TO 'read committed';" +$STD sudo -u postgres psql -c "ALTER ROLE $DB_USER SET timezone TO 'UTC';" +{ + echo "Dispatcharr Credentials" + echo "Database Name: $DB_NAME" + echo "Database User: $DB_USER" + echo "Database Password: $DB_PASS" + echo "" +} >>~/dispatcharr.creds +msg_ok "Created PostgreSQL Database" + +fetch_and_deploy_gh_release "dispatcharr" "Dispatcharr/Dispatcharr" + +msg_info "Installing Python Dependencies with uv" +cd /opt/dispatcharr +$STD uv venv +$STD uv pip install -r requirements.txt --index-strategy unsafe-best-match +$STD uv pip install gunicorn gevent celery redis daphne +msg_ok "Installed Python Dependencies" + +msg_info "Configuring Dispatcharr" +install -d -m 755 \ + /data/{logos,recordings,plugins,db} \ + /data/uploads/{m3us,epgs} \ + /data/{m3us,epgs} +chown -R root:root /data +export DATABASE_URL="postgresql://${DB_USER}:${DB_PASS}@localhost:5432/${DB_NAME}" +export POSTGRES_DB=$DB_NAME +export POSTGRES_USER=$DB_USER +export POSTGRES_PASSWORD=$DB_PASS +export POSTGRES_HOST=localhost +$STD uv run python manage.py migrate --noinput +$STD uv run python manage.py collectstatic --noinput +cat </opt/dispatcharr/.env +DATABASE_URL=postgresql://${DB_USER}:${DB_PASS}@localhost:5432/${DB_NAME} +POSTGRES_DB=$DB_NAME +POSTGRES_USER=$DB_USER +POSTGRES_PASSWORD=$DB_PASS +POSTGRES_HOST=localhost +CELERY_BROKER_URL=redis://localhost:6379/0 +EOF +cd /opt/dispatcharr/frontend +$STD npm install --legacy-peer-deps +$STD npm run build +msg_ok "Configured Dispatcharr" + +msg_info "Configuring Nginx" +cat </etc/nginx/sites-available/dispatcharr.conf +server { + listen 80; + server_name _; + + # Serve static assets with correct MIME types + location /assets/ { + alias /opt/dispatcharr/frontend/dist/assets/; + expires 30d; + add_header Cache-Control "public, immutable"; + + # Explicitly set MIME types for webpack-built assets + types { + text/javascript js; + text/css css; + image/png png; + image/svg+xml svg svgz; + font/woff2 woff2; + font/woff woff; + font/ttf ttf; + } + } + + location /static/ { + alias /opt/dispatcharr/static/; + expires 30d; + add_header Cache-Control "public, immutable"; + } + + location /media/ { + alias /opt/dispatcharr/media/; + } + + location /ws/ { + proxy_pass http://127.0.0.1:8001; + proxy_http_version 1.1; + proxy_set_header Upgrade \$http_upgrade; + proxy_set_header Connection "Upgrade"; + proxy_set_header Host \$host; + proxy_set_header X-Real-IP \$remote_addr; + proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto \$scheme; + } + + # All other requests proxy to Gunicorn + location / { + include proxy_params; + proxy_pass http://127.0.0.1:5656; + } +} +EOF +ln -sf /etc/nginx/sites-available/dispatcharr.conf /etc/nginx/sites-enabled/dispatcharr.conf +rm -f /etc/nginx/sites-enabled/default +systemctl restart nginx +msg_ok "Configured Nginx" + +msg_info "Creating Services" +cat </opt/dispatcharr/start-gunicorn.sh +#!/usr/bin/env bash +cd /opt/dispatcharr +set -a +source .env +set +a +exec uv run gunicorn \\ + --workers=4 \\ + --worker-class=gevent \\ + --timeout=300 \\ + --bind 0.0.0.0:5656 \\ + dispatcharr.wsgi:application +EOF +chmod +x /opt/dispatcharr/start-gunicorn.sh + +cat </opt/dispatcharr/start-celery.sh +#!/usr/bin/env bash +cd /opt/dispatcharr +set -a +source .env +set +a +exec uv run celery -A dispatcharr worker -l info -c 4 +EOF +chmod +x /opt/dispatcharr/start-celery.sh + +cat </opt/dispatcharr/start-celerybeat.sh +#!/usr/bin/env bash +cd /opt/dispatcharr +set -a +source .env +set +a +exec uv run celery -A dispatcharr beat -l info +EOF +chmod +x /opt/dispatcharr/start-celerybeat.sh + +cat </opt/dispatcharr/start-daphne.sh +#!/usr/bin/env bash +cd /opt/dispatcharr +set -a +source .env +set +a +exec uv run daphne -b 0.0.0.0 -p 8001 dispatcharr.asgi:application +EOF +chmod +x /opt/dispatcharr/start-daphne.sh + +cat </etc/systemd/system/dispatcharr.service +[Unit] +Description=Dispatcharr Web Server +After=network.target postgresql.service redis-server.service + +[Service] +Type=simple +WorkingDirectory=/opt/dispatcharr +ExecStart=/opt/dispatcharr/start-gunicorn.sh +Restart=on-failure +RestartSec=10 +User=root + +[Install] +WantedBy=multi-user.target +EOF + +cat </etc/systemd/system/dispatcharr-celery.service +[Unit] +Description=Dispatcharr Celery Worker +After=network.target redis-server.service +Requires=dispatcharr.service + +[Service] +Type=simple +WorkingDirectory=/opt/dispatcharr +ExecStart=/opt/dispatcharr/start-celery.sh +Restart=on-failure +RestartSec=10 +User=root + +[Install] +WantedBy=multi-user.target +EOF + +cat </etc/systemd/system/dispatcharr-celerybeat.service +[Unit] +Description=Dispatcharr Celery Beat Scheduler +After=network.target redis-server.service +Requires=dispatcharr.service + +[Service] +Type=simple +WorkingDirectory=/opt/dispatcharr +ExecStart=/opt/dispatcharr/start-celerybeat.sh +Restart=on-failure +RestartSec=10 +User=root + +[Install] +WantedBy=multi-user.target +EOF + +cat </etc/systemd/system/dispatcharr-daphne.service +[Unit] +Description=Dispatcharr WebSocket Server (Daphne) +After=network.target +Requires=dispatcharr.service + +[Service] +Type=simple +WorkingDirectory=/opt/dispatcharr +ExecStart=/opt/dispatcharr/start-daphne.sh +Restart=on-failure +RestartSec=10 +User=root + +[Install] +WantedBy=multi-user.target +EOF +systemctl enable -q --now dispatcharr dispatcharr-celery dispatcharr-celerybeat dispatcharr-daphne +msg_ok "Created Services" + +motd_ssh +customize + +msg_info "Cleaning up" +$STD apt -y autoremove +$STD apt -y autoclean +$STD apt -y clean +msg_ok "Cleaned" diff --git a/install/donetick-install.sh b/install/donetick-install.sh new file mode 100644 index 000000000..5bc12e07f --- /dev/null +++ b/install/donetick-install.sh @@ -0,0 +1,54 @@ +#!/usr/bin/env bash + +# Copyright (c) 2021-2025 community-scripts ORG +# Author: fstof +# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE +# Source: https://github.com/donetick/donetick + +source /dev/stdin <<<"$FUNCTIONS_FILE_PATH" +color +verb_ip6 +catch_errors +setting_up_container +network_check +update_os + +msg_info "Installing Dependencies" +$STD apt install -y ca-certificates +msg_ok "Installed Dependencies" + +fetch_and_deploy_gh_release "donetick" "donetick/donetick" "prebuild" "latest" "/opt/donetick" "donetick_Linux_x86_64.tar.gz" + +msg_info "Setup Donetick" +cd /opt/donetick +TOKEN=$(openssl rand -hex 16) +sed -i -e "s/change_this_to_a_secure_random_string_32_characters_long/${TOKEN}/g" config/selfhosted.yaml +msg_ok "Setup Donetick" + +msg_info "Creating Service" +cat </etc/systemd/system/donetick.service +[Unit] +Description=donetick Service +After=network.target + +[Service] +Environment="DT_ENV=selfhosted" +WorkingDirectory=/opt/donetick +ExecStart=/opt/donetick/donetick +Restart=always + +[Install] +WantedBy=multi-user.target +EOF +systemctl enable -q --now donetick +msg_ok "Created Service" + +motd_ssh +customize + +msg_info "Cleaning up" +$STD apt -y autoremove +$STD apt -y autoclean +$STD apt -y clean +msg_ok "Cleaned" + diff --git a/install/flaresolverr-install.sh b/install/flaresolverr-install.sh index 3751f9ba8..ff22bcb89 100644 --- a/install/flaresolverr-install.sh +++ b/install/flaresolverr-install.sh @@ -21,13 +21,18 @@ $STD apt-get install -y \ msg_ok "Installed Dependencies" msg_info "Installing Chrome" -curl -fsSL "https://dl.google.com/linux/linux_signing_key.pub" | gpg --dearmor -o /usr/share/keyrings/google-chrome.gpg -echo "deb [arch=amd64 signed-by=/usr/share/keyrings/google-chrome.gpg] http://dl.google.com/linux/chrome/deb/ stable main" >/etc/apt/sources.list.d/google-chrome.list +setup_deb822_repo \ + "google-chrome" \ + "https://dl.google.com/linux/linux_signing_key.pub" \ + "https://dl.google.com/linux/chrome/deb/" \ + "stable" $STD apt update $STD apt install -y google-chrome-stable +# remove google-chrome.list added by google-chrome-stable +rm /etc/apt/sources.list.d/google-chrome.list msg_ok "Installed Chrome" -fetch_and_deploy_gh_release "flaresolverr" "FlareSolverr/FlareSolverr" "prebuild" "v3.3.25" "/opt/flaresolverr" "flaresolverr_linux_x64.tar.gz" +fetch_and_deploy_gh_release "flaresolverr" "FlareSolverr/FlareSolverr" "prebuild" "latest" "/opt/flaresolverr" "flaresolverr_linux_x64.tar.gz" msg_info "Creating Service" cat </etc/systemd/system/flaresolverr.service diff --git a/install/garage-install.sh b/install/garage-install.sh new file mode 100644 index 000000000..4c51e7cdb --- /dev/null +++ b/install/garage-install.sh @@ -0,0 +1,95 @@ +#!/usr/bin/env bash + +# Copyright (c) 2021-2025 community-scripts ORG +# Author: MickLesk (CanbiZ) +# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE +# Source: https://garagehq.deuxfleurs.fr/ + +source /dev/stdin <<<"$FUNCTIONS_FILE_PATH" +color +verb_ip6 +catch_errors +setting_up_container +network_check +update_os + +msg_info "Setup Garage" +GITEA_RELEASE=$(curl -s https://api.github.com/repos/deuxfleurs-org/garage/tags | jq -r '.[0].name') +curl -fsSL "https://garagehq.deuxfleurs.fr/_releases/${GITEA_RELEASE}/x86_64-unknown-linux-musl/garage" -o /usr/local/bin/garage +chmod +x /usr/local/bin/garage +mkdir -p /var/lib/garage/{data,meta,snapshots} +mkdir -p /etc/garage +RPC_SECRET=$(openssl rand -hex 32) +ADMIN_TOKEN=$(openssl rand -base64 32) +METRICS_TOKEN=$(openssl rand -base64 32) +{ + echo "Garage Tokens and Secrets" + echo "RPC Secret: $RPC_SECRET" + echo "Admin Token: $ADMIN_TOKEN" + echo "Metrics Token: $METRICS_TOKEN" +} >>~/garage.creds +echo $GITEA_RELEASE >>~/.garage +cat </etc/garage.toml +metadata_dir = "/var/lib/garage/meta" +data_dir = "/var/lib/garage/data" +db_engine = "sqlite" +replication_factor = 1 + +rpc_bind_addr = "[::]:3901" +rpc_public_addr = "127.0.0.1:3901" +rpc_secret = "${RPC_SECRET}" + +[s3_api] +s3_region = "garage" +api_bind_addr = "[::]:3900" +root_domain = ".s3.garage.localhost" + +[s3_web] +bind_addr = "[::]:3902" +root_domain = ".web.garage.localhost" +index = "index.html" + +[k2v_api] +api_bind_addr = "[::]:3904" + +[admin] +api_bind_addr = "[::]:3903" +admin_token = "${ADMIN_TOKEN}" +metrics_token = "${METRICS_TOKEN}" +EOF +msg_ok "Set up Garage" + + +msg_info "Creating service" +cat <<'EOF' >/etc/systemd/system/garage.service +[Unit] +Description=Garage Object Storage (Deuxfleurs) +After=network-online.target +Wants=network-online.target + +[Service] +Type=simple +ExecStart=/usr/local/bin/garage -c /etc/garage.toml server +Restart=always +RestartSec=5 +User=root +WorkingDirectory=/var/lib/garage +Environment=RUST_LOG=info +StandardOutput=append:/var/log/garage.log +StandardError=append:/var/log/garage.log +LimitNOFILE=65536 + +[Install] +WantedBy=multi-user.target +EOF +$STD systemctl enable -q --now garage +msg_ok "Created Service" + +motd_ssh +customize + +msg_info "Cleaning up" +$STD apt -y autoremove +$STD apt -y autoclean +$STD apt -y clean +msg_ok "Cleaned" diff --git a/install/ghost-install.sh b/install/ghost-install.sh index 593181631..39960ab02 100644 --- a/install/ghost-install.sh +++ b/install/ghost-install.sh @@ -20,22 +20,22 @@ $STD apt-get install -y \ libjemalloc2 msg_ok "Installed Dependencies" -setup_mysql +setup_mariadb msg_info "Configuring Database" DB_NAME=ghost DB_USER=ghostuser DB_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13) -$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 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 ON $DB_NAME.* TO '$DB_USER'@'localhost'; FLUSH PRIVILEGES;" { echo "Ghost-Credentials" echo "Ghost Database User: $DB_USER" echo "Ghost Database Password: $DB_PASS" echo "Ghost Database Name: $DB_NAME" } >>~/ghost.creds -msg_ok "Configured MySQL" +msg_ok "Configured MariaDB" NODE_VERSION="22" setup_nodejs @@ -60,4 +60,5 @@ customize msg_info "Cleaning up" $STD apt-get -y autoremove $STD apt-get -y autoclean +$STD apt-get -y clean msg_ok "Cleaned" diff --git a/install/immich-install.sh b/install/immich-install.sh index 4ac27e55c..a4551f4c3 100644 --- a/install/immich-install.sh +++ b/install/immich-install.sh @@ -64,7 +64,8 @@ $STD apt-get install --no-install-recommends -y \ libdav1d-dev \ libhwy-dev \ libwebp-dev \ - libaom-dev + libaom-dev \ + ccache curl -fsSL https://repo.jellyfin.org/jellyfin_team.gpg.key | gpg --dearmor -o /etc/apt/keyrings/jellyfin.gpg DPKG_ARCHITECTURE="$(dpkg --print-architecture)" export DPKG_ARCHITECTURE @@ -126,7 +127,7 @@ $STD apt-get install -t testing --no-install-recommends -yqq libmimalloc3 msg_ok "Installed libmimalloc3" PNPM_VERSION="$(curl -fsSL "https://raw.githubusercontent.com/immich-app/immich/refs/heads/main/package.json" | jq -r '.packageManager | split("@")[1]')" -NODE_VERSION="22" NODE_MODULE="pnpm@${PNPM_VERSION}" setup_nodejs +NODE_VERSION="24" NODE_MODULE="pnpm@${PNPM_VERSION}" setup_nodejs PG_VERSION="16" PG_MODULES="pgvector" setup_postgresql msg_info "Setting up Postgresql Database" @@ -287,7 +288,7 @@ GEO_DIR="${INSTALL_DIR}/geodata" mkdir -p "$INSTALL_DIR" mkdir -p {"${APP_DIR}","${UPLOAD_DIR}","${GEO_DIR}","${INSTALL_DIR}"/cache} -fetch_and_deploy_gh_release "immich" "immich-app/immich" "tarball" "v2.1.0" "$SRC_DIR" +fetch_and_deploy_gh_release "immich" "immich-app/immich" "tarball" "v2.2.3" "$SRC_DIR" msg_info "Installing ${APPLICATION} (patience)" @@ -351,15 +352,10 @@ ln -s "$UPLOAD_DIR" "$ML_DIR"/upload msg_info "Installing GeoNames data" cd "$GEO_DIR" -URL_LIST=( - https://download.geonames.org/export/dump/admin1CodesASCII.txt - https://download.geonames.org/export/dump/admin2Codes.txt - https://download.geonames.org/export/dump/cities500.zip - https://raw.githubusercontent.com/nvkelso/natural-earth-vector/v5.1.2/geojson/ne_10m_admin_0_countries.geojson -) -for geo in "${URL_LIST[@]}"; do - curl -fsSLO "$geo" -done +curl -fsSLZ -O "https://download.geonames.org/export/dump/admin1CodesASCII.txt" \ + -O "https://download.geonames.org/export/dump/admin2Codes.txt" \ + -O "https://download.geonames.org/export/dump/cities500.zip" \ + -O "https://raw.githubusercontent.com/nvkelso/natural-earth-vector/v5.1.2/geojson/ne_10m_admin_0_countries.geojson" unzip -q cities500.zip date --iso-8601=seconds | tr -d "\n" >geodata-date.txt rm cities500.zip diff --git a/install/jellyfin-install.sh b/install/jellyfin-install.sh index 113307945..d33573448 100644 --- a/install/jellyfin-install.sh +++ b/install/jellyfin-install.sh @@ -19,9 +19,11 @@ if ! grep -qEi 'ubuntu' /etc/os-release; then fetch_and_deploy_gh_release "intel-igc-opencl-2" "intel/intel-graphics-compiler" "binary" "latest" "" "intel-igc-opencl-2_*_amd64.deb" fetch_and_deploy_gh_release "intel-libgdgmm12" "intel/compute-runtime" "binary" "latest" "" "libigdgmm12_*_amd64.deb" fetch_and_deploy_gh_release "intel-opencl-icd" "intel/compute-runtime" "binary" "latest" "" "intel-opencl-icd_*_amd64.deb" +else + $STD apt -y install intel-opencl-icd fi -$STD apt -y install {va-driver-all,ocl-icd-libopencl1,intel-opencl-icd,vainfo,intel-gpu-tools} +$STD apt -y install {va-driver-all,ocl-icd-libopencl1,vainfo,intel-gpu-tools} if [[ "$CTTYPE" == "0" ]]; then chgrp video /dev/dri chmod 755 /dev/dri diff --git a/install/jotty-install.sh b/install/jotty-install.sh index 7f46ae4f1..0492b14b6 100644 --- a/install/jotty-install.sh +++ b/install/jotty-install.sh @@ -25,7 +25,15 @@ mkdir -p data/{users,checklists,notes} cat </opt/jotty/.env NODE_ENV=production + +# --- Uncomment to enable # HTTPS=true +# SERVE_PUBLIC_IMAGES=yes +# SERVE_PUBLIC_FILES=yes +# SERVE_PUBLIC_VIDEOS=yes +# STOP_CHECK_UPDATES=yes +# --- For troubleshooting +# DEBUGGER=true # --- SSO with OIDC (optional) # SSO_MODE=oidc diff --git a/install/libretranslate-install.sh b/install/libretranslate-install.sh index 79f2c6956..eda190d6a 100644 --- a/install/libretranslate-install.sh +++ b/install/libretranslate-install.sh @@ -14,10 +14,14 @@ network_check update_os msg_info "Installing dependencies" -$STD apt install -y --no-install-recommends \ +$STD apt install -y \ pkg-config \ - gcc \ + build-essential \ g++ \ + cmake \ + libprotobuf-dev \ + protobuf-compiler \ + libsentencepiece-dev \ libicu-dev msg_ok "Installed dependencies" @@ -32,13 +36,18 @@ setup_uv fetch_and_deploy_gh_release "libretranslate" "LibreTranslate/LibreTranslate" msg_info "Setup LibreTranslate (Patience)" +TORCH_VERSION=$(grep -Eo '"torch ==[0-9]+\.[0-9]+\.[0-9]+' /opt/libretranslate/pyproject.toml | \ + tail -n1 | sed 's/.*==//') +if [[ -z "$TORCH_VERSION" ]]; then + TORCH_VERSION="2.5.0" +fi cd /opt/libretranslate $STD uv venv .venv $STD source .venv/bin/activate $STD uv pip install --upgrade pip setuptools $STD uv pip install Babel==2.12.1 $STD .venv/bin/python scripts/compile_locales.py -$STD uv pip install torch==2.2.0 --extra-index-url https://download.pytorch.org/whl/cpu +$STD uv pip install "torch==${TORCH_VERSION}" --extra-index-url https://download.pytorch.org/whl/cpu $STD uv pip install "numpy<2" $STD uv pip install . $STD uv pip install libretranslate diff --git a/install/linkstack-install.sh b/install/linkstack-install.sh index d90bc2c30..3b01aad1e 100644 --- a/install/linkstack-install.sh +++ b/install/linkstack-install.sh @@ -14,7 +14,7 @@ network_check update_os PHP_VERSION="8.3" PHP_MODULE="sqlite3" PHP_APACHE="YES" setup_php -fetch_and_deploy_gh_release "linkstack" "linkstackorg/linkstack" "prebuild" "latest" "/var/www/html/linkstack" "linkstack.zip" +fetch_and_deploy_gh_release "linkstack" "linkstackorg/linkstack" "prebuild" "latest" "/var/www/html/" "linkstack.zip" msg_info "Configuring LinkStack" $STD a2enmod rewrite diff --git a/install/livebook-install.sh b/install/livebook-install.sh new file mode 100644 index 000000000..1d24e25eb --- /dev/null +++ b/install/livebook-install.sh @@ -0,0 +1,106 @@ +#!/usr/bin/env bash + +# Copyright (c) 2021-2025 community-scripts ORG +# Author: dkuku +# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE +# Source: https://github.com/livebook-dev/livebook + +source /dev/stdin <<<"$FUNCTIONS_FILE_PATH" +color +verb_ip6 +catch_errors +setting_up_container +network_check +update_os + +msg_info "Installing Dependencies" +$STD apt-get install -y \ + build-essential \ + ca-certificates \ + cmake \ + git \ + libncurses5-dev +msg_ok "Installed Dependencies" + +msg_info "Creating livebook user" +mkdir -p /opt/livebook /data +export HOME=/opt/livebook +$STD adduser --system --group --home /opt/livebook --shell /bin/bash livebook +msg_ok "Created livebook user" + +msg_warn "WARNING: This script will run an external installer from a third-party source (https://elixir-lang.org)." +msg_warn "The following code is NOT maintained or audited by our repository." +msg_warn "If you have any doubts or concerns, please review the installer code before proceeding:" +msg_custom "${TAB3}${GATEWAY}${BGN}${CL}" "\e[1;34m" "→ https://elixir-lang.org/install.sh" +echo +read -r -p "${TAB3}Do you want to continue? [y/N]: " CONFIRM +if [[ ! "$CONFIRM" =~ ^([yY][eE][sS]|[yY])$ ]]; then + msg_error "Aborted by user. No changes have been made." + exit 10 +fi +curl -fsSO https://elixir-lang.org/install.sh +$STD sh install.sh elixir@latest otp@latest + +msg_info "Setup Erlang and Elixir" +ERLANG_VERSION=$(ls /opt/livebook/.elixir-install/installs/otp/ | head -n1) +ELIXIR_VERSION=$(ls /opt/livebook/.elixir-install/installs/elixir/ | head -n1) +LIVEBOOK_PASSWORD=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c16) + +export ERLANG_BIN="/opt/livebook/.elixir-install/installs/otp/$ERLANG_VERSION/bin" +export ELIXIR_BIN="/opt/livebook/.elixir-install/installs/elixir/$ELIXIR_VERSION/bin" +export PATH="$ERLANG_BIN:$ELIXIR_BIN:$PATH" + +$STD mix local.hex --force +$STD mix local.rebar --force +$STD mix escript.install hex livebook --force + +cat </opt/livebook/.env +export HOME=/opt/livebook +export ERLANG_VERSION=$ERLANG_VERSION +export ELIXIR_VERSION=$ELIXIR_VERSION +export LIVEBOOK_PORT=8080 +export LIVEBOOK_IP="::" +export LIVEBOOK_HOME=/data +export LIVEBOOK_PASSWORD="$LIVEBOOK_PASSWORD" +export ESCRIPTS_BIN=/opt/livebook/.mix/escripts +export ERLANG_BIN="/opt/livebook/.elixir-install/installs/otp/\${ERLANG_VERSION}/bin" +export ELIXIR_BIN="/opt/livebook/.elixir-install/installs/elixir/\${ELIXIR_VERSION}/bin" +export PATH="\$ESCRIPTS_BIN:\$ERLANG_BIN:\$ELIXIR_BIN:\$PATH" +EOF +{ + echo "Livebook-Credentials" + echo "Livebook Password: $LIVEBOOK_PASSWORD" +} >>~/livebook.creds +msg_ok "Installed Erlang $ERLANG_VERSION and Elixir $ELIXIR_VERSION" + +msg_info "Installing Livebook" +cat </etc/systemd/system/livebook.service +[Unit] +Description=Livebook +After=network.target + +[Service] +Type=exec +User=livebook +Group=livebook +WorkingDirectory=/data +EnvironmentFile=-/opt/livebook/.env +ExecStart=/bin/bash -c 'source /opt/livebook/.env && cd /opt/livebook && livebook server' +Restart=always +RestartSec=5 + +[Install] +WantedBy=multi-user.target +EOF +chown -R livebook:livebook /opt/livebook /data +systemctl enable -q --now livebook +msg_ok "Installed Livebook" + +motd_ssh +customize + +msg_info "Cleaning Up" +$STD apt autoremove -y +$STD apt autoclean -y +$STD apt clean -y +msg_ok "Cleaned Up" diff --git a/install/managemydamnlife-install.sh b/install/managemydamnlife-install.sh index 69cd7015d..10eefdf90 100644 --- a/install/managemydamnlife-install.sh +++ b/install/managemydamnlife-install.sh @@ -14,19 +14,19 @@ network_check update_os msg_info "Installing dependencies" -$STD apt install --no-install-recommends -y build-essential +$STD apt install -y build-essential msg_ok "Installed dependencies" NODE_VERSION="22" setup_nodejs -MYSQL_VERSION="8.0" setup_mysql +setup_mariadb msg_info "Setting up Database" DB_NAME="mmdl" DB_USER="mmdl" DB_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13) -$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 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 ON $DB_NAME.* TO '$DB_USER'@'localhost'; FLUSH PRIVILEGES;" { echo "Manage My Damn Life Credentials" echo "Database User: $DB_USER" @@ -59,7 +59,7 @@ msg_info "Creating Service" cat </etc/systemd/system/mmdl.service [Unit] Description=${APPLICATION} Service -After=network.target mysql.service +After=network.target mariadb.service [Service] WorkingDirectory=/opt/mmdl diff --git a/install/mediamanager-install.sh b/install/mediamanager-install.sh index fa6638122..2fe6ed323 100644 --- a/install/mediamanager-install.sh +++ b/install/mediamanager-install.sh @@ -47,14 +47,13 @@ export CONFIG_DIR="${MM_DIR}/config" export FRONTEND_FILES_DIR="${MM_DIR}/web/build" export BASE_PATH="" export PUBLIC_VERSION="" -export PUBLIC_API_URL="${BASE_PATH}/api/v1" -export BASE_PATH="${BASE_PATH}/web" +export PUBLIC_API_URL="" +export BASE_PATH="" cd /opt/mediamanager/web $STD npm ci $STD npm run build mkdir -p {"$MM_DIR"/web,"$MEDIA_DIR","$CONFIG_DIR"} cp -r build "$FRONTEND_FILES_DIR" -export BASE_PATH="" export VIRTUAL_ENV="${MM_DIR}/venv" cd /opt/mediamanager cp -r {media_manager,alembic*} "$MM_DIR" diff --git a/install/metube-install.sh b/install/metube-install.sh deleted file mode 100644 index ce6fde8c3..000000000 --- a/install/metube-install.sh +++ /dev/null @@ -1,85 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (c) 2021-2025 tteck -# Author: MickLesk (Canbiz) -# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE -# Source: https://github.com/alexta69/metube - -source /dev/stdin <<<"$FUNCTIONS_FILE_PATH" -color -verb_ip6 -catch_errors -setting_up_container -network_check -update_os - -msg_info "Installing Dependencies" -$STD apt install -y --no-install-recommends \ - build-essential \ - aria2 \ - coreutils \ - gcc \ - g++ \ - musl-dev \ - ffmpeg \ - make \ - ca-certificates -msg_ok "Installed Dependencies" - -PYTHON_VERSION="3.13" setup_uv -NODE_VERSION="22" setup_nodejs - -msg_info "Installing Deno" -export DENO_INSTALL="/usr/local" -curl -fsSL https://deno.land/install.sh | $STD sh -s -- -y -[[ ":$PATH:" != *":/usr/local/bin:"* ]] && - echo -e "\nexport PATH=\"/usr/local/bin:\$PATH\"" >>~/.bashrc && - source ~/.bashrc -msg_ok "Installed Deno" - -fetch_and_deploy_gh_release "metube" "alexta69/metube" "tarball" "latest" - -msg_info "Installing MeTube" -cd /opt/metube/ui -$STD npm install -$STD node_modules/.bin/ng build -cd /opt/metube -$STD uv sync - -mkdir -p /opt/metube_downloads /opt/metube_downloads/.metube /opt/metube_downloads/music /opt/metube_downloads/videos -cat </opt/metube/.env -DOWNLOAD_DIR=/opt/metube_downloads -STATE_DIR=/opt/metube_downloads/.metube -TEMP_DIR=/opt/metube_downloads -YTDL_OPTIONS={"trim_file_name":10,"extractor_args":{"youtube":{"player_client":["default","-tv_simply"]}}} -EOF -msg_ok "Installed MeTube" - -msg_info "Creating Service" -cat </etc/systemd/system/metube.service -[Unit] -Description=Metube - YouTube Downloader -After=network.target - -[Service] -Type=simple -WorkingDirectory=/opt/metube -EnvironmentFile=/opt/metube/.env -ExecStart=/opt/metube/.venv/bin/python3 app/main.py -Restart=always -User=root - -[Install] -WantedBy=multi-user.target -EOF -systemctl enable -q --now metube -msg_ok "Created Service" - -motd_ssh -customize - -msg_info "Cleaning up" -$STD apt -y autoremove -$STD apt -y autoclean -$STD apt -y clean -msg_ok "Cleaned" diff --git a/install/mongodb-install.sh b/install/mongodb-install.sh index 139403f88..fe46ed304 100644 --- a/install/mongodb-install.sh +++ b/install/mongodb-install.sh @@ -15,25 +15,12 @@ update_os read -p "${TAB3}Do you want to install MongoDB 8.0 instead of 7.0? [y/N]: " install_mongodb_8 if [[ "$install_mongodb_8" =~ ^[Yy]$ ]]; then - MONGODB_VERSION="8.0" + MONGO_VERSION="8.0" setup_mongodb else - MONGODB_VERSION="7.0" + MONGO_VERSION="7.0" setup_mongodb fi - -msg_info "Installing MongoDB $MONGODB_VERSION" -curl -fsSL "https://www.mongodb.org/static/pgp/server-${MONGODB_VERSION}.asc" | gpg --dearmor >/usr/share/keyrings/mongodb-server-${MONGODB_VERSION}.gpg -cat </etc/apt/sources.list.d/mongodb-org-${MONGODB_VERSION}.sources -Types: deb -URIs: http://repo.mongodb.org/apt/debian -Suites: $(grep '^VERSION_CODENAME=' /etc/os-release | cut -d'=' -f2)/mongodb-org/${MONGODB_VERSION} -Components: main -Signed-By: /usr/share/keyrings/mongodb-server-${MONGODB_VERSION}.gpg -EOF -$STD apt update -$STD apt install -y mongodb-org sed -i 's/bindIp: 127.0.0.1/bindIp: 0.0.0.0/' /etc/mongod.conf -systemctl enable -q --now mongod -msg_ok "Installed MongoDB $MONGODB_VERSION" +msg_ok "Installed MongoDB $MONGO_VERSION" motd_ssh customize diff --git a/install/mylar3-install.sh b/install/mylar3-install.sh index 66917f1d5..bcb866894 100644 --- a/install/mylar3-install.sh +++ b/install/mylar3-install.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # Copyright (c) 2021-2025 community-scripts ORG -# Author: davalanche +# Author: davalanche | Co-Author: Slaviša Arežina (tremor021) # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE # Source: https://github.com/mylar3/mylar3 @@ -14,7 +14,6 @@ network_check update_os msg_info "Installing Dependencies" -$STD apt install -y jq cat </etc/apt/sources.list.d/non-free.sources Types: deb URIs: http://deb.debian.org/debian @@ -23,22 +22,17 @@ Components: non-free non-free-firmware EOF $STD apt update $STD apt install -y unrar -rm /etc/apt/sources.list.d/non-free.sources msg_ok "Installed Dependencies" -msg_info "Setup Python3" -$STD apt install -y python3-pip -rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED -$STD pip install -U --no-cache-dir pip -msg_ok "Setup Python3" +PYTHON_VERSION="3.12" setup_uv +fetch_and_deploy_gh_release "mylar3" "mylar3/mylar3" "tarball" msg_info "Installing ${APPLICATION}" -mkdir -p /opt/mylar3 mkdir -p /opt/mylar3-data -RELEASE=$(curl -fsSL https://api.github.com/repos/mylar3/mylar3/releases/latest | jq -r '.tag_name') -curl -fsSL "https://github.com/mylar3/mylar3/archive/refs/tags/${RELEASE}.tar.gz" | tar -xz --strip-components=1 -C /opt/mylar3 -$STD pip install --no-cache-dir -r /opt/mylar3/requirements.txt -echo "${RELEASE}" >/opt/${APPLICATION}_version.txt +$STD uv venv /opt/mylar3/.venv +$STD /opt/mylar3/.venv/bin/python -m ensurepip --upgrade +$STD /opt/mylar3/.venv/bin/python -m pip install --upgrade pip +$STD /opt/mylar3/.venv/bin/python -m pip install --no-cache-dir -r /opt/mylar3/requirements.txt msg_ok "Installed ${APPLICATION}" msg_info "Creating Service" @@ -48,7 +42,7 @@ Description=Mylar3 Service After=network-online.target [Service] -ExecStart=/usr/bin/python3 /opt/mylar3/Mylar.py --daemon --nolaunch --datadir=/opt/mylar3-data +ExecStart=/opt/mylar3/.venv/bin/python /opt/mylar3/Mylar.py --daemon --nolaunch --datadir=/opt/mylar3-data GuessMainPID=no Type=forking Restart=on-failure diff --git a/install/mysql-install.sh b/install/mysql-install.sh index 44dcbcd76..404f2957d 100644 --- a/install/mysql-install.sh +++ b/install/mysql-install.sh @@ -63,27 +63,7 @@ msg_ok "MySQL Server configured" read -r -p "${TAB3}Would you like to add PhpMyAdmin? " prompt if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then - msg_info "Installing phpMyAdmin" - $STD apt install -y \ - apache2 \ - php \ - php-mysqli \ - php-mbstring \ - php-zip \ - php-gd \ - php-json \ - php-curl - - curl -fsSL "https://files.phpmyadmin.net/phpMyAdmin/5.2.2/phpMyAdmin-5.2.2-all-languages.tar.gz" -o "phpMyAdmin-5.2.2-all-languages.tar.gz" - mkdir -p /var/www/html/phpMyAdmin - tar xf phpMyAdmin-5.2.2-all-languages.tar.gz --strip-components=1 -C /var/www/html/phpMyAdmin - cp /var/www/html/phpMyAdmin/config.sample.inc.php /var/www/html/phpMyAdmin/config.inc.php - SECRET=$(openssl rand -base64 24) - sed -i "s#\$cfg\['blowfish_secret'\] = '';#\$cfg['blowfish_secret'] = '${SECRET}';#" /var/www/html/phpMyAdmin/config.inc.php - chmod 660 /var/www/html/phpMyAdmin/config.inc.php - chown -R www-data:www-data /var/www/html/phpMyAdmin - systemctl restart apache2 - msg_ok "Installed phpMyAdmin" + bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/phpmyadmin.sh)" fi msg_info "Start Service" diff --git a/install/nginxproxymanager-install.sh b/install/nginxproxymanager-install.sh index 664878130..11fdb4cf2 100644 --- a/install/nginxproxymanager-install.sh +++ b/install/nginxproxymanager-install.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash -# Copyright (c) 2021-2025 tteck -# Author: tteck (tteckster) +# Copyright (c) 2021-2025 Community-Scripts ORG +# Author: tteck (tteckster) | Co-Author: CrazyWolf13 # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE # Source: https://nginxproxymanager.com/ @@ -39,18 +39,15 @@ $STD /opt/certbot/bin/pip install certbot certbot-dns-cloudflare ln -sf /opt/certbot/bin/certbot /usr/local/bin/certbot msg_ok "Set up Certbot" -VERSION="$(awk -F'=' '/^VERSION_CODENAME=/{ print $NF }' /etc/os-release)" - msg_info "Installing Openresty" -curl -fsSL "https://openresty.org/package/pubkey.gpg" | gpg --dearmor -o /etc/apt/trusted.gpg.d/openresty-archive-keyring.gpg -case "$VERSION" in -trixie) - echo -e "deb http://openresty.org/package/debian bookworm openresty" >/etc/apt/sources.list.d/openresty.list - ;; -*) - echo -e "deb http://openresty.org/package/debian $VERSION openresty" >/etc/apt/sources.list.d/openresty.list - ;; -esac +curl -fsSL "https://openresty.org/package/pubkey.gpg" | gpg --dearmor -o /etc/apt/trusted.gpg.d/openresty.gpg +cat <<'EOF' >/etc/apt/sources.list.d/openresty.sources +Types: deb +URIs: http://openresty.org/package/debian/ +Suites: bookworm +Components: openresty +Signed-By: /etc/apt/trusted.gpg.d/openresty.gpg +EOF $STD apt update $STD apt -y install openresty msg_ok "Installed Openresty" @@ -61,28 +58,25 @@ RELEASE=$(curl -fsSL https://api.github.com/repos/NginxProxyManager/nginx-proxy- grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }') -msg_info "Downloading Nginx Proxy Manager v${RELEASE}" -curl -fsSL "https://codeload.github.com/NginxProxyManager/nginx-proxy-manager/tar.gz/v${RELEASE}" | tar -xz -cd ./nginx-proxy-manager-"${RELEASE}" -msg_ok "Downloaded Nginx Proxy Manager v${RELEASE}" +fetch_and_deploy_gh_release "nginxproxymanager" "NginxProxyManager/nginx-proxy-manager" msg_info "Setting up Environment" ln -sf /usr/bin/python3 /usr/bin/python ln -sf /usr/local/openresty/nginx/sbin/nginx /usr/sbin/nginx ln -sf /usr/local/openresty/nginx/ /etc/nginx -sed -i "s|\"version\": \"0.0.0\"|\"version\": \"$RELEASE\"|" backend/package.json -sed -i "s|\"version\": \"0.0.0\"|\"version\": \"$RELEASE\"|" frontend/package.json -sed -i 's+^daemon+#daemon+g' docker/rootfs/etc/nginx/nginx.conf -NGINX_CONFS=$(find "$(pwd)" -type f -name "*.conf") +sed -i "s|\"version\": \"2.0.0\"|\"version\": \"$RELEASE\"|" /opt/nginxproxymanager/backend/package.json +sed -i "s|\"version\": \"2.0.0\"|\"version\": \"$RELEASE\"|" /opt/nginxproxymanager/frontend/package.json +sed -i 's+^daemon+#daemon+g' /opt/nginxproxymanager/docker/rootfs/etc/nginx/nginx.conf +NGINX_CONFS=$(find /opt/nginxproxymanager -type f -name "*.conf") for NGINX_CONF in $NGINX_CONFS; do sed -i 's+include conf.d+include /etc/nginx/conf.d+g' "$NGINX_CONF" done mkdir -p /var/www/html /etc/nginx/logs -cp -r docker/rootfs/var/www/html/* /var/www/html/ -cp -r docker/rootfs/etc/nginx/* /etc/nginx/ -cp docker/rootfs/etc/letsencrypt.ini /etc/letsencrypt.ini -cp docker/rootfs/etc/logrotate.d/nginx-proxy-manager /etc/logrotate.d/nginx-proxy-manager +cp -r /opt/nginxproxymanager/docker/rootfs/var/www/html/* /var/www/html/ +cp -r /opt/nginxproxymanager/docker/rootfs/etc/nginx/* /etc/nginx/ +cp /opt/nginxproxymanager/docker/rootfs/etc/letsencrypt.ini /etc/letsencrypt.ini +cp /opt/nginxproxymanager/docker/rootfs/etc/logrotate.d/nginx-proxy-manager /etc/logrotate.d/nginx-proxy-manager ln -sf /etc/nginx/nginx.conf /etc/nginx/conf/nginx.conf rm -f /etc/nginx/conf.d/dev.conf @@ -109,23 +103,22 @@ chown root /tmp/nginx echo resolver "$(awk 'BEGIN{ORS=" "} $1=="nameserver" {print ($2 ~ ":")? "["$2"]": $2}' /etc/resolv.conf);" >/etc/nginx/conf.d/include/resolvers.conf if [ ! -f /data/nginx/dummycert.pem ] || [ ! -f /data/nginx/dummykey.pem ]; then - openssl req -new -newkey rsa:2048 -days 3650 -nodes -x509 -subj "/O=Nginx Proxy Manager/OU=Dummy Certificate/CN=localhost" -keyout /data/nginx/dummykey.pem -out /data/nginx/dummycert.pem &>/dev/null + $STD openssl req -new -newkey rsa:2048 -days 3650 -nodes -x509 -subj "/O=Nginx Proxy Manager/OU=Dummy Certificate/CN=localhost" -keyout /data/nginx/dummykey.pem -out /data/nginx/dummycert.pem fi -mkdir -p /app/global /app/frontend/images -cp -r backend/* /app -cp -r global/* /app/global +mkdir -p /app/frontend/images +cp -r /opt/nginxproxymanager/backend/* /app msg_ok "Set up Environment" msg_info "Building Frontend" -cd ./frontend -export NODE_OPTIONS="--openssl-legacy-provider" +export NODE_OPTIONS="--max_old_space_size=2048 --openssl-legacy-provider" +cd /opt/nginxproxymanager/frontend # Replace node-sass with sass in package.json before installation -sed -i 's/"node-sass".*$/"sass": "^1.92.1",/g' package.json +sed -E -i 's/"node-sass" *: *"([^"]*)"/"sass": "\1"/g' package.json $STD yarn install --network-timeout 600000 $STD yarn build -cp -r dist/* /app/frontend -cp -r app-images/* /app/frontend/images +cp -r /opt/nginxproxymanager/frontend/dist/* /app/frontend +cp -r /opt/nginxproxymanager/frontend/public/images/* /app/frontend/images msg_ok "Built Frontend" msg_info "Initializing Backend" @@ -146,7 +139,6 @@ if [ ! -f /app/config/production.json ]; then EOF fi cd /app -export NODE_OPTIONS="--openssl-legacy-provider" $STD yarn install --network-timeout 600000 msg_ok "Initialized Backend" @@ -170,9 +162,6 @@ WantedBy=multi-user.target EOF msg_ok "Created Service" -motd_ssh -customize - msg_info "Starting Services" sed -i 's/user npm/user root/g; s/^pid/#pid/g' /usr/local/openresty/nginx/conf/nginx.conf sed -r -i 's/^([[:space:]]*)su npm npm/\1#su npm npm/g;' /etc/logrotate.d/nginx-proxy-manager @@ -180,8 +169,10 @@ systemctl enable -q --now openresty systemctl enable -q --now npm msg_ok "Started Services" +motd_ssh +customize + msg_info "Cleaning up" -rm -rf ../nginx-proxy-manager-* systemctl restart openresty $STD apt -y autoremove $STD apt -y autoclean diff --git a/install/open-archiver-install.sh b/install/open-archiver-install.sh index 628ede760..126c46c16 100644 --- a/install/open-archiver-install.sh +++ b/install/open-archiver-install.sh @@ -90,7 +90,7 @@ sed -i "s|^ENCRYPTION_KEY=.*|ENCRYPTION_KEY=$SECRET_KEY|g" /opt/openarchiver/.en sed -i "s|^TIKA_URL=.*|TIKA_URL=|g" /opt/openarchiver/.env echo "ORIGIN=http://$IP_ADDR:3000" >> /opt/openarchiver/.env $STD pnpm install --shamefully-hoist --frozen-lockfile --prod=false -$STD pnpm build +$STD pnpm run build:oss $STD pnpm db:migrate msg_ok "Setup Open Archiver" @@ -105,7 +105,7 @@ Type=simple User=root EnvironmentFile=/opt/openarchiver/.env WorkingDirectory=/opt/openarchiver -ExecStart=/usr/bin/pnpm docker-start +ExecStart=/usr/bin/pnpm docker-start:oss Restart=on-failure [Install] diff --git a/install/openwebui-install.sh b/install/openwebui-install.sh index b9889ae35..ad43ac7c3 100644 --- a/install/openwebui-install.sh +++ b/install/openwebui-install.sh @@ -1,8 +1,7 @@ #!/usr/bin/env bash # Copyright (c) 2021-2025 tteck -# Author: tteck -# Co-Author: havardthom +# Author: tteck | Co-Author: havardthom | Co-Author: Slaviša Arežina (tremor021) # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE # Source: https://openwebui.com/ @@ -15,36 +14,10 @@ network_check update_os msg_info "Installing Dependencies" -$STD apt install -y \ - git \ - ffmpeg \ - libpq-dev +$STD apt install -y ffmpeg msg_ok "Installed Dependencies" -msg_info "Setup Python3" -$STD apt install -y --no-install-recommends \ - python3 \ - python3-pip -msg_ok "Setup Python3" - -NODE_VERSION="22" setup_nodejs - -msg_info "Installing Open WebUI (Patience)" -$STD git clone https://github.com/open-webui/open-webui.git /opt/open-webui -cd /opt/open-webui/backend -$STD pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu -$STD pip3 install -r requirements.txt -U -cd /opt/open-webui -cp .env.example .env -cat </opt/open-webui/.env -ENV=prod -ENABLE_OLLAMA_API=false -OLLAMA_BASE_URL=http://0.0.0.0:11434 -EOF -$STD npm install --force -export NODE_OPTIONS="--max-old-space-size=6000" -$STD npm run build -msg_ok "Installed Open WebUI" +USE_UVX="YES" PYTHON_VERSION="3.12" setup_uv read -r -p "${TAB3}Would you like to add Ollama? " prompt if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then @@ -69,7 +42,7 @@ RestartSec=3 WantedBy=multi-user.target EOF systemctl enable -q --now ollama - sed -i 's/ENABLE_OLLAMA_API=false/ENABLE_OLLAMA_API=true/g' /opt/open-webui/.env + echo "ENABLE_OLLAMA_API=true" >/root/.env msg_ok "Installed Ollama" fi @@ -80,10 +53,14 @@ Description=Open WebUI Service After=network.target [Service] -Type=exec -WorkingDirectory=/opt/open-webui -EnvironmentFile=/opt/open-webui/.env -ExecStart=/opt/open-webui/backend/start.sh +Type=simple +EnvironmentFile=-/root/.env +Environment=DATA_DIR=/root/.open-webui +ExecStart=/usr/local/bin/uvx --python 3.12 open-webui@latest serve +WorkingDirectory=/root +Restart=on-failure +RestartSec=5 +User=root [Install] WantedBy=multi-user.target diff --git a/install/pangolin-install.sh b/install/pangolin-install.sh new file mode 100644 index 000000000..d0557963c --- /dev/null +++ b/install/pangolin-install.sh @@ -0,0 +1,134 @@ +#!/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://pangolin.net/ + +source /dev/stdin <<<"$FUNCTIONS_FILE_PATH" +color +verb_ip6 +catch_errors +setting_up_container +network_check +update_os + +msg_info "Installing Dependencies" +$STD apt install -y \ + sqlite3 \ + iptables +msg_ok "Installed Dependencies" + +NODE_VERSION="22" setup_nodejs +fetch_and_deploy_gh_release "pangolin" "fosrl/pangolin" "tarball" +fetch_and_deploy_gh_release "gerbil" "fosrl/gerbil" "singlefile" "latest" "/usr/bin" "gerbil_linux_amd64" + +msg_info "Setup Pangolin" +IP_ADDR=$(hostname -I | awk '{print $1}') +SECRET_KEY=$(openssl rand -base64 48 | tr -dc 'A-Za-z0-9' | head -c 32) +cd /opt/pangolin +$STD npm ci +$STD npm run set:sqlite +$STD npm run set:oss +rm -rf server/private +$STD npm run build:sqlite +$STD npm run build:cli +cp -R .next/standalone ./ + +cat </usr/local/bin/pangctl +#!/bin/sh +cd /opt/pangolin +./dist/cli.mjs "$@" +EOF +chmod +x /usr/local/bin/pangctl ./dist/cli.mjs +cp server/db/names.json ./dist/names.json +mkdir -p /var/config + +cat </opt/pangolin/config/config.yml +app: + dashboard_url: http://$IP_ADDR:3002 + log_level: debug + +domains: + domain1: + base_domain: example.com + +server: + secret: $SECRET_KEY + +gerbil: + base_endpoint: example.com + +orgs: + block_size: 24 + subnet_group: 100.90.137.0/20 + +flags: + require_email_verification: false + disable_signup_without_invite: true + disable_user_create_org: true + allow_raw_resources: true + enable_integration_api: true + enable_clients: true +EOF +$STD npm run db:sqlite:generate +$STD npm run db:sqlite:push + +. /etc/os-release +if [ "$VERSION_CODENAME" = "trixie" ]; then + echo "net.ipv4.ip_forward=1" >>/etc/sysctl.d/sysctl.conf + $STD sysctl -p /etc/sysctl.d/sysctl.conf +else + echo "net.ipv4.ip_forward=1" >>/etc/sysctl.conf + $STD sysctl -p /etc/sysctl.conf +fi +msg_ok "Setup Pangolin" + +msg_info "Creating Services" +cat </etc/systemd/system/pangolin.service +[Unit] +Description=Pangolin Service +After=network.target + +[Service] +Type=simple +User=root +Environment=NODE_ENV=production +Environment=ENVIRONMENT=prod +WorkingDirectory=/opt/pangolin +ExecStart=/usr/bin/node --enable-source-maps dist/server.mjs +Restart=always +RestartSec=10 + +[Install] +WantedBy=multi-user.target +EOF +systemctl enable -q --now pangolin + +cat </etc/systemd/system/gerbil.service +[Unit] +Description=Gerbil Service +After=network.target +Requires=pangolin.service + +[Service] +Type=simple +User=root +ExecStart=/usr/bin/gerbil --reachableAt=http://$IP_ADDR:3004 --generateAndSaveKeyTo=/var/config/key --remoteConfig=http://$IP_ADDR:3001/api/v1/ +Restart=always +RestartSec=10 + +[Install] +WantedBy=multi-user.target +EOF +systemctl enable -q --now gerbil +msg_ok "Created Services" + +motd_ssh +customize + +msg_info "Cleaning up" +$STD apt -y autoremove +$STD apt -y autoclean +$STD apt -y clean +msg_ok "Cleaned" diff --git a/install/patchmon-install.sh b/install/patchmon-install.sh new file mode 100644 index 000000000..b2c948787 --- /dev/null +++ b/install/patchmon-install.sh @@ -0,0 +1,287 @@ +#!/usr/bin/env bash + +# Copyright (c) 2021-2025 community-scripts ORG +# Author: vhsdream +# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE +# Source: https://github.com/PatcMmon/PatchMon + +source /dev/stdin <<<"$FUNCTIONS_FILE_PATH" +color +verb_ip6 +catch_errors +setting_up_container +network_check +update_os + +msg_info "Installing Dependencies" +$STD apt install -y \ + build-essential \ + nginx \ + redis-server +msg_ok "Installed Dependencies" + +NODE_VERSION="24" setup_nodejs +PG_VERSION="17" setup_postgresql + +msg_info "Setup PostgreSQL Database" +DB_NAME=patchmon_db +DB_USER=patchmon_usr +DB_PASS="$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | cut -c1-13)" +$STD sudo -u postgres psql -c "CREATE ROLE $DB_USER WITH LOGIN PASSWORD '$DB_PASS';" +$STD sudo -u postgres psql -c "CREATE DATABASE $DB_NAME WITH OWNER $DB_USER ENCODING 'UTF8' TEMPLATE template0;" +$STD sudo -u postgres psql -c "ALTER ROLE $DB_USER SET client_encoding TO 'utf8';" +$STD sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE $DB_NAME TO $DB_USER;" +{ + echo "PatchMon Credentials" + echo "PatchMon Database Name: $DB_NAME" + echo "PatchMon Database User: $DB_USER" + echo "PatchMon Database Password: $DB_PASS" +} >>~/patchmon.creds +msg_ok "Setup PostgreSQL Database" + +fetch_and_deploy_gh_release "PatchMon" "PatchMon/PatchMon" "tarball" "latest" "/opt/patchmon" + +msg_info "Configuring PatchMon" +cd /opt/patchmon +export NODE_ENV=production +$STD npm install --no-audit --no-fund --no-save --ignore-scripts +cd /opt/patchmon/backend +$STD npm install --no-audit --no-fund --no-save --ignore-scripts +cd /opt/patchmon/frontend +$STD npm install --include=dev --no-audit --no-fund --no-save --ignore-scripts +$STD npm run build + +JWT_SECRET="$(openssl rand -base64 64 | tr -d "=+/" | cut -c1-50)" +LOCAL_IP="$(hostname -I | awk '{print $1}')" +cat </opt/patchmon/backend/.env +# Database Configuration +DATABASE_URL="postgresql://$DB_USER:$DB_PASS@localhost:5432/$DB_NAME" +PY_THRESHOLD=3M_DB_CONN_MAX_ATTEMPTS=30 +PM_DB_CONN_WAIT_INTERVAL=2 + +# JWT Configuration +JWT_SECRET="$JWT_SECRET" +JWT_EXPIRES_IN=1h +JWT_REFRESH_EXPIRES_IN=7d + +# Server Configuration +PORT=3399 +NODE_ENV=production + +# API Configuration +API_VERSION=v1 + +# CORS Configuration +CORS_ORIGIN="http://$LOCAL_IP" + +# Session Configuration +SESSION_INACTIVITY_TIMEOUT_MINUTES=30 + +# User Configuration +DEFAULT_USER_ROLE=user + +# Rate Limiting (times in milliseconds) +RATE_LIMIT_WINDOW_MS=900000 +RATE_LIMIT_MAX=5000 +AUTH_RATE_LIMIT_WINDOW_MS=600000 +AUTH_RATE_LIMIT_MAX=500 +AGENT_RATE_LIMIT_WINDOW_MS=60000 +AGENT_RATE_LIMIT_MAX=1000 + +# Redis Configuration +REDIS_HOST=localhost +REDIS_PORT=6379 + +# Logging +LOG_LEVEL=info +ENABLE_LOGGING=true + +# TFA Configuration +TFA_REMEMBER_ME_EXPIRES_IN=30d +TFA_MAX_REMEMBER_SESSIONS=5 +TFA_SUSPICIOUS_ACTIVITY_THRESHOLD=3 +EOF + +cat </opt/patchmon/frontend/.env +VITE_API_URL=http://$LOCAL_IP/api/v1 +VITE_APP_NAME=PatchMon +VITE_APP_VERSION=1.3.0 +EOF + +cd /opt/patchmon/backend +$STD npx prisma migrate deploy +$STD npx prisma generate +msg_ok "Configured PatchMon" + +msg_info "Configuring Nginx" +cat </etc/nginx/sites-available/patchmon.conf +server { + listen 80; + server_name $LOCAL_IP; + + # Security headers + add_header X-Frame-Options DENY always; + add_header X-Content-Type-Options nosniff always; + add_header X-XSS-Protection "1; mode=block" always; + add_header Referrer-Policy "strict-origin-when-cross-origin" always; + + # Frontend + location / { + root /opt/patchmon/frontend/dist; + try_files \$uri \$uri/ /index.html; + } + + # Bull Board proxy + location /bullboard { + proxy_pass http://127.0.0.1:3399; + proxy_http_version 1.1; + proxy_set_header Upgrade \$http_upgrade; + proxy_set_header Connection 'upgrade'; + proxy_set_header Host \$host; + proxy_set_header X-Real-IP \$remote_addr; + proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto \$scheme; + proxy_set_header X-Forwarded-Host \$host; + proxy_set_header Cookie \$http_cookie; + proxy_cache_bypass \$http_upgrade; + proxy_read_timeout 300s; + proxy_connect_timeout 75s; + + # Enable cookie passthrough + proxy_pass_header Set-Cookie; + proxy_cookie_path / /; + + # Preserve original client IP + proxy_set_header X-Original-Forwarded-For \$http_x_forwarded_for; + if (\$request_method = 'OPTIONS') { + return 204; + } + } + + # API proxy + location /api/ { + proxy_pass http://127.0.0.1:3399; + proxy_http_version 1.1; + proxy_set_header Upgrade \$http_upgrade; + proxy_set_header Connection 'upgrade'; + proxy_set_header Host \$host; + proxy_set_header X-Real-IP \$remote_addr; + proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto \$scheme; + proxy_cache_bypass \$http_upgrade; + proxy_read_timeout 300s; + proxy_connect_timeout 75s; + + # Preserve original client IP + proxy_set_header X-Original-Forwarded-For \$http_x_forwarded_for; + if (\$request_method = 'OPTIONS') { + return 204; + } + } + + # Static assets caching (exclude Bull Board assets) + location ~* ^/(?!bullboard).*\.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { + root /opt/patchmon/frontend/dist; + expires 1y; + add_header Cache-Control "public, immutable"; + } + + # Health check endpoint + location /health { + proxy_pass http://127.0.0.1:3399/health; + access_log off; + } +} +EOF +ln -sf /etc/nginx/sites-available/patchmon.conf /etc/nginx/sites-enabled/ +rm -f /etc/nginx/sites-enabled/default +$STD nginx -t +systemctl restart nginx +msg_ok "Configured Nginx" + +msg_info "Creating service" +cat </etc/systemd/system/patchmon-server.service +[Unit] +Description=PatchMon Service +After=network.target postgresql.service + +[Service] +Type=simple +WorkingDirectory=/opt/patchmon/backend +ExecStart=/usr/bin/node src/server.js +Restart=always +RestartSec=10 +Environment=NODE_ENV=production +Environment=PATH=/usr/bin:/usr/local/bin +NoNewPrivileges=true +PrivateTmp=true +ProtectSystem=strict +ProtectHome=true +ReadWritePaths=/opt/patchmon + +[Install] +WantedBy=multi-user.target +EOF +systemctl enable -q --now patchmon-server +msg_ok "Created and started service" + +msg_info "Updating settings" +cat </opt/patchmon/backend/update-settings.js +const { PrismaClient } = require('@prisma/client'); +const { v4: uuidv4 } = require('uuid'); +const prisma = new PrismaClient(); + +async function updateSettings() { + try { + const existingSettings = await prisma.settings.findFirst(); + + const settingsData = { + id: uuidv4(), + server_url: 'http://$LOCAL_IP', + server_protocol: 'http', + server_host: '$LOCAL_IP', + server_port: 3399, + update_interval: 60, + auto_update: true, + signup_enabled: false, + ignore_ssl_self_signed: false, + updated_at: new Date() + }; + + if (existingSettings) { + // Update existing settings + await prisma.settings.update({ + where: { id: existingSettings.id }, + data: settingsData + }); + } else { + // Create new settings record + await prisma.settings.create({ + data: settingsData + }); + } + + console.log('✅ Database settings updated successfully'); + } catch (error) { + console.error('❌ Error updating settings:', error.message); + process.exit(1); + } finally { + await prisma.\$disconnect(); + } +} + +updateSettings(); +EOF + +cd /opt/patchmon/backend +$STD node update-settings.js +msg_ok "Settings updated successfully" + +motd_ssh +customize + +msg_info "Cleaning up" +$STD apt -y autoremove +$STD apt -y autoclean +$STD apt -y clean +msg_ok "Cleaned" diff --git a/install/radicale-install.sh b/install/radicale-install.sh index d4231ee27..a43d4bb56 100644 --- a/install/radicale-install.sh +++ b/install/radicale-install.sh @@ -17,7 +17,7 @@ msg_info "Installing Dependencies" $STD apt install -y \ apache2-utils \ python3-pip \ - python3.11-venv + python3-venv msg_ok "Installed Dependencies" msg_info "Setting up Radicale" diff --git a/install/reactive-resume-install.sh b/install/reactive-resume-install.sh index f1585e55a..fa1579dad 100644 --- a/install/reactive-resume-install.sh +++ b/install/reactive-resume-install.sh @@ -61,6 +61,8 @@ cd /opt/browserless $STD npm install rm -rf src/routes/{chrome,edge,firefox,webkit} $STD node_modules/playwright-core/cli.js install --with-deps chromium +$STD npm install typescript --save-dev +$STD npm install esbuild --save-dev $STD npm run build $STD npm run build:function $STD npm prune production diff --git a/install/reitti-install.sh b/install/reitti-install.sh new file mode 100644 index 000000000..851a2aa4e --- /dev/null +++ b/install/reitti-install.sh @@ -0,0 +1,165 @@ +#!/usr/bin/env bash + +# 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/dedicatedcode/reitti + +source /dev/stdin <<<"$FUNCTIONS_FILE_PATH" +color +verb_ip6 +catch_errors +setting_up_container +network_check +update_os + +msg_info "Installing Dependencies" +$STD apt install -y \ + redis-server \ + rabbitmq-server \ + libpq-dev \ + zstd +msg_ok "Installed Dependencies" + +JAVA_VERSION="24" setup_java +PG_VERSION="17" PG_MODULES="postgis" setup_postgresql + +msg_info "Setting up PostgreSQL" +DB_NAME="reitti_db" +DB_USER="reitti" +DB_PASS="$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | cut -c1-13)" +$STD sudo -u postgres psql -c "CREATE ROLE $DB_USER WITH LOGIN PASSWORD '$DB_PASS';" +$STD sudo -u postgres psql -c "CREATE DATABASE $DB_NAME WITH OWNER $DB_USER ENCODING 'UTF8' TEMPLATE template0;" +$STD sudo -u postgres psql -c "ALTER ROLE $DB_USER SET client_encoding TO 'utf8';" +$STD sudo -u postgres psql -c "ALTER ROLE $DB_USER SET default_transaction_isolation TO 'read committed';" +$STD sudo -u postgres psql -c "ALTER ROLE $DB_USER SET timezone TO 'UTC';" +$STD sudo -u postgres psql -d "$DB_NAME" -c "CREATE EXTENSION IF NOT EXISTS postgis;" +$STD sudo -u postgres psql -d "$DB_NAME" -c "CREATE EXTENSION IF NOT EXISTS postgis_topology;" +{ + echo "Reitti Credentials" + echo "Database Name: $DB_NAME" + echo "Database User: $DB_USER" + echo "Database Password: $DB_PASS" +} >>~/reitti.creds +msg_ok "PostgreSQL Setup Completed" + +msg_info "Configuring RabbitMQ" +RABBIT_USER="reitti" +RABBIT_PASS="$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | cut -c1-13)" +RABBIT_VHOST="/" +$STD rabbitmqctl add_user "$RABBIT_USER" "$RABBIT_PASS" +$STD rabbitmqctl add_vhost "$RABBIT_VHOST" +$STD rabbitmqctl set_permissions -p "$RABBIT_VHOST" "$RABBIT_USER" ".*" ".*" ".*" +$STD rabbitmqctl set_user_tags "$RABBIT_USER" administrator +{ + echo "" + echo "Reitti Credentials" + echo "RabbitMQ User: $RABBIT_USER" + echo "RabbitMQ Password: $RABBIT_PASS" +} >>~/reitti.creds +msg_ok "Configured RabbitMQ" + +USE_ORIGINAL_FILENAME="true" fetch_and_deploy_gh_release "reitti" "dedicatedcode/reitti" "singlefile" "latest" "/opt/reitti" "reitti-app.jar" +mv /opt/reitti/reitti-*.jar /opt/reitti/reitti.jar +USE_ORIGINAL_FILENAME="true" fetch_and_deploy_gh_release "photon" "komoot/photon" "singlefile" "latest" "/opt/photon" "photon-0*.jar" +mv /opt/photon/photon-*.jar /opt/photon/photon.jar + +msg_info "Creating Reitti Configuration-File" +mkdir -p /opt/reitti/data +cat </opt/reitti/application.properties +# Reitti Server Base URI +reitti.server.advertise-uri=http://127.0.0.1:8080 + +# PostgreSQL Database Connection +spring.datasource.url=jdbc:postgresql://127.0.0.1:5432/$DB_NAME +spring.datasource.username=$DB_USER +spring.datasource.password=$DB_PASS +spring.datasource.driver-class-name=org.postgresql.Driver + +# Flyway Database Migrations +spring.flyway.enabled=true +spring.flyway.locations=classpath:db/migration +spring.flyway.baseline-on-migrate=true + +# RabbitMQ (Message Queue) +spring.rabbitmq.host=127.0.0.1 +spring.rabbitmq.port=5672 +spring.rabbitmq.username=$RABBIT_USER +spring.rabbitmq.password=$RABBIT_PASS + +# Redis (Cache) +spring.data.redis.host=127.0.0.1 +spring.data.redis.port=6379 + +# Server Port +server.port=8080 + +# Optional: Logging & Performance +logging.level.root=INFO +spring.jpa.hibernate.ddl-auto=none +spring.datasource.hikari.maximum-pool-size=10 + +# OIDC / Security Settings +reitti.security.oidc.registration.enabled=false + +# Photon (Geocoding) +PHOTON_BASE_URL=http://127.0.0.1:2322 +PROCESSING_WAIT_TIME=15 +PROCESSING_BATCH_SIZE=1000 +PROCESSING_WORKERS_PER_QUEUE=4-16 + +# Disable potentially dangerous features unless needed +DANGEROUS_LIFE=false +EOF +msg_ok "Created Configuration-File for Reitti" + +msg_info "Creating Services" +cat </etc/systemd/system/reitti.service +[Unit] +Description=Reitti +After=network.target postgresql.service redis-server.service rabbitmq-server.service photon.service +Wants=postgresql.service redis-server.service rabbitmq-server.service photon.service + +[Service] +Type=simple +WorkingDirectory=/opt/reitti/ +ExecStart=/usr/bin/java --enable-native-access=ALL-UNNAMED -jar -Xmx2g reitti.jar +TimeoutStopSec=20 +KillMode=process +Restart=on-failure + +[Install] +WantedBy=multi-user.target +EOF + +cat <<'EOF' >/etc/systemd/system/photon.service +[Unit] +Description=Photon Geocoding Service (Germany, OpenSearch) +After=network.target + +[Service] +Type=simple +WorkingDirectory=/opt/photon +ExecStart=/usr/bin/java -Xmx4g -jar photon.jar \ + -data-dir /opt/photon \ + -listen-port 2322 \ + -listen-ip 0.0.0.0 \ + -cors-any +Restart=on-failure +TimeoutStopSec=20 + +[Install] +WantedBy=multi-user.target +EOF +systemctl enable -q --now photon +systemctl enable -q --now reitti +msg_ok "Created Services" + +motd_ssh +customize + +msg_info "Cleaning up" +$STD apt -y autoremove +$STD apt -y autoclean +$STD apt -y clean +msg_ok "Cleaned" diff --git a/install/sabnzbd-install.sh b/install/sabnzbd-install.sh index 1036a8a34..baa868c54 100644 --- a/install/sabnzbd-install.sh +++ b/install/sabnzbd-install.sh @@ -19,30 +19,33 @@ $STD apt install -y \ p7zip-full msg_ok "Installed Dependencies" -msg_info "Setup uv" -setup_uv -msg_ok "Setup uv" +PYTHON_VERSION="3.13" setup_uv msg_info "Setup Unrar" -cat </etc/apt/sources.list.d/non-free.list -deb http://deb.debian.org/debian bookworm main contrib non-free non-free-firmware +cat </etc/apt/sources.list.d/non-free.sources +Types: deb +URIs: http://deb.debian.org/debian/ +Suites: trixie +Components: non-free +Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg EOF $STD apt update $STD apt install -y unrar -rm /etc/apt/sources.list.d/non-free.list msg_ok "Setup Unrar" +fetch_and_deploy_gh_release "sabnzbd-org" "sabnzbd/sabnzbd" "prebuild" "latest" "/opt/sabnzbd" "SABnzbd-*-src.tar.gz" + msg_info "Installing SABnzbd" -RELEASE=$(curl -fsSL https://api.github.com/repos/sabnzbd/sabnzbd/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }') -mkdir -p /opt/sabnzbd $STD uv venv /opt/sabnzbd/venv -temp_file=$(mktemp) -curl -fsSL "https://github.com/sabnzbd/sabnzbd/releases/download/${RELEASE}/SABnzbd-${RELEASE}-src.tar.gz" -o "$temp_file" -tar -xzf "$temp_file" -C /opt/sabnzbd --strip-components=1 $STD uv pip install -r /opt/sabnzbd/requirements.txt --python=/opt/sabnzbd/venv/bin/python -echo "${RELEASE}" >/opt/${APPLICATION}_version.txt msg_ok "Installed SABnzbd" +read -r -p "Would you like to install par2cmdline-turbo? " prompt +if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then + mv /usr/bin/par2 /usr/bin/par2.old + fetch_and_deploy_gh_release "par2cmdline-turbo" "animetosho/par2cmdline-turbo" "prebuild" "latest" "/usr/bin/" "*-linux-amd64.zip" +fi + msg_info "Creating Service" cat </etc/systemd/system/sabnzbd.service [Unit] @@ -65,7 +68,6 @@ motd_ssh customize msg_info "Cleaning up" -rm -f "$temp_file" $STD apt -y autoremove $STD apt -y autoclean $STD apt -y clean diff --git a/install/stirling-pdf-install.sh b/install/stirling-pdf-install.sh index cdd02a48e..6b4d805e2 100644 --- a/install/stirling-pdf-install.sh +++ b/install/stirling-pdf-install.sh @@ -26,7 +26,8 @@ $STD apt install -y \ unpaper \ fonts-urw-base35 \ qpdf \ - poppler-utils + poppler-utils \ + jbig2 msg_ok "Installed Dependencies" PYTHON_VERSION="3.12" setup_uv @@ -69,24 +70,12 @@ $STD uv pip install \ ocrmypdf \ pillow \ pdf2image - $STD apt install -y python3-uno python3-pip -$STD pip3 install --break-system-packages unoserver +$STD pip3 install --break-system-packages --timeout=120 unoserver ln -sf /opt/.venv/bin/python3 /usr/local/bin/python3 ln -sf /opt/.venv/bin/pip /usr/local/bin/pip msg_ok "Installed Python Dependencies" -msg_info "Installing JBIG2" -$STD curl -fsSL -o /tmp/jbig2enc.tar.gz https://github.com/agl/jbig2enc/archive/refs/tags/0.30.tar.gz -mkdir -p /opt/jbig2enc -tar -xzf /tmp/jbig2enc.tar.gz -C /opt/jbig2enc --strip-components=1 -cd /opt/jbig2enc -$STD bash ./autogen.sh -$STD bash ./configure -$STD make -$STD make install -msg_ok "Installed JBIG2" - msg_info "Installing Language Packs (Patience)" $STD apt install -y 'tesseract-ocr-*' msg_ok "Installed Language Packs" diff --git a/install/tracktor-install.sh b/install/tracktor-install.sh index 8db049bac..8e82d76d6 100644 --- a/install/tracktor-install.sh +++ b/install/tracktor-install.sh @@ -20,18 +20,26 @@ msg_info "Configuring Tracktor" cd /opt/tracktor $STD npm install $STD npm run build -mkdir /opt/tracktor-data +mkdir -p /opt/tracktor-data/{uploads,logs} HOST_IP=$(hostname -I | awk '{print $1}') cat </opt/tracktor.env NODE_ENV=production -PUBLIC_DEMO_MODE=false DB_PATH=/opt/tracktor-data/tracktor.db -# Replace this URL if using behind reverse proxy for https traffic. Though it is optional and should work without changing -PUBLIC_API_BASE_URL=http://$HOST_IP:3000 -# Here add the reverse proxy url as well to avoid cross errors from the app. -CORS_ORIGINS=http://$HOST_IP:3000 +UPLOADS_DIR="/opt/tracktor-data/uploads" +LOG_DIR="/opt/tracktor-data/logs" +# If server host is not set by default it will run on all interfaces - 0.0.0.0 +# SERVER_HOST="" +SERVER_PORT=3000 PORT=3000 +# Set this if you want to secure your endpoints otherwise default will be "*" +# CORS_ORIGINS="*" +# Set this if you are using backend and frontend separately. For lxc installation this is not needed +# PUBLIC_API_BASE_URL="" +LOG_REQUESTS=true +LOG_LEVEL="info" AUTH_PIN=123456 +# PUBLIC_DEMO_MODE=false +# FORCE_DATA_SEED=false EOF msg_ok "Configured Tracktor" diff --git a/install/urbackupserver-install.sh b/install/urbackupserver-install.sh index 5d96f6122..7c0f97df7 100644 --- a/install/urbackupserver-install.sh +++ b/install/urbackupserver-install.sh @@ -14,9 +14,12 @@ network_check update_os msg_info "Installing Dependencies" -$STD apt install -y coreutils +$STD apt install -y \ + coreutils \ + debconf-utils msg_ok "Installed Dependencies" + msg_info "Installing UrBackup Server" curl -fsSL https://download.opensuse.org/repositories/home:uroni/Debian_12/Release.key | gpg --dearmor -o /usr/share/keyrings/home-uroni.gpg cat </dev/null @@ -27,6 +30,8 @@ Components: Signed-By: /usr/share/keyrings/home-uroni.gpg EOF $STD apt update +mkdir -p /opt/urbackup/backups +echo "urbackup-server urbackup/backuppath string /opt/urbackup/backups" | debconf-set-selections $STD apt install -y urbackup-server msg_ok "Installed UrBackup Server" diff --git a/install/victoriametrics-install.sh b/install/victoriametrics-install.sh index 9b2547211..4b43ebff0 100644 --- a/install/victoriametrics-install.sh +++ b/install/victoriametrics-install.sh @@ -28,8 +28,14 @@ fetch_and_deploy_gh_release "vmutils" "VictoriaMetrics/VictoriaMetrics" "prebuil read -r -p "${TAB3}Would you like to add VictoriaLogs? " prompt if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then - fetch_and_deploy_gh_release "victorialogs" "VictoriaMetrics/VictoriaLogs" "prebuild" "latest" "/opt/victoriametrics" "victoria-logs-linux-amd64*.tar.gz" - fetch_and_deploy_gh_release "vlutils" "VictoriaMetrics/VictoriaLogs" "prebuild" "latest" "/opt/victoriametrics" "vlutils-linux-amd64*.tar.gz" + vmlogs_filename=$(curl -fsSL "https://api.github.com/repos/VictoriaMetrics/VictoriaLogs/releases/latest" | + jq -r '.assets[].name' | + grep -E '^victoria-logs-linux-amd64-v[0-9.]+\.tar\.gz$') + vlutils_filename=$(curl -fsSL "https://api.github.com/repos/VictoriaMetrics/VictoriaLogs/releases/latest" | + jq -r '.assets[].name' | + grep -E '^vlutils-linux-amd64-v[0-9.]+\.tar\.gz$') + fetch_and_deploy_gh_release "victorialogs" "VictoriaMetrics/VictoriaLogs" "prebuild" "latest" "/opt/victoriametrics" "$vmlogs_filename" + fetch_and_deploy_gh_release "vlutils" "VictoriaMetrics/VictoriaLogs" "prebuild" "latest" "/opt/victoriametrics" "$vlutils_filename" fi msg_info "Setup VictoriaMetrics" diff --git a/misc/core.func b/misc/core.func index 71c13764f..ca454d02a 100644 --- a/misc/core.func +++ b/misc/core.func @@ -368,6 +368,51 @@ run_container_safe() { " || __handle_general_error "lxc-attach to CT $ct" } +cleanup_lxc() { + msg_info "Cleaning up" + if is_alpine; then + $STD apk cache clean || true + rm -rf /var/cache/apk/* + else + $STD apt -y autoremove || true + $STD apt -y autoclean || true + $STD apt -y clean || true + fi + + rm -rf /tmp/* /var/tmp/* + + # Remove temp files created by mktemp/tempfile + find /tmp /var/tmp -type f -name 'tmp*' -delete 2>/dev/null || true + find /tmp /var/tmp -type f -name 'tempfile*' -delete 2>/dev/null || true + + find /var/log -type f -exec truncate -s 0 {} + + + # Python pip + if command -v pip &>/dev/null; then pip cache purge || true; fi + # Python uv + if command -v uv &>/dev/null; then uv cache clear || true; fi + # Node.js npm + if command -v npm &>/dev/null; then npm cache clean --force || true; fi + # Node.js yarn + if command -v yarn &>/dev/null; then yarn cache clean || true; fi + # Node.js pnpm + if command -v pnpm &>/dev/null; then pnpm store prune || true; fi + # Go + if command -v go &>/dev/null; then go clean -cache -modcache || true; fi + # Rust cargo + if command -v cargo &>/dev/null; then cargo clean || true; fi + # Ruby gem + if command -v gem &>/dev/null; then gem cleanup || true; fi + # Composer (PHP) + if command -v composer &>/dev/null; then composer clear-cache || true; fi + + if command -v journalctl &>/dev/null; then + $STD journalctl --rotate + $STD journalctl --vacuum-time=10m + fi + msg_ok "Cleaned" +} + check_or_create_swap() { msg_info "Checking for active swap" diff --git a/misc/tools.func b/misc/tools.func index 60bb6b4d4..c67e4de58 100644 --- a/misc/tools.func +++ b/misc/tools.func @@ -3,6 +3,32 @@ # ============================================================================== # HELPER FUNCTIONS FOR PACKAGE MANAGEMENT # ============================================================================== +# +# This file provides unified helper functions for robust package installation +# and repository management across Debian/Ubuntu OS upgrades. +# +# Key Features: +# - Automatic retry logic for transient APT/network failures +# - Unified keyring cleanup from all 3 locations +# - Legacy installation cleanup (nvm, rbenv, rustup) +# - OS-upgrade-safe repository preparation +# - Service pattern matching for multi-version tools +# +# Usage in install scripts: +# source /dev/stdin <<< "$FUNCTIONS" # Load from build.func +# prepare_repository_setup "mysql" +# install_packages_with_retry "mysql-server" "mysql-client" +# +# Quick Reference (Core Helpers): +# cleanup_tool_keyrings() - Remove keyrings from all 3 locations +# stop_all_services() - Stop services by pattern (e.g. "php*-fpm") +# verify_tool_version() - Validate installed version matches expected +# cleanup_legacy_install() - Remove nvm, rbenv, rustup, etc. +# prepare_repository_setup() - Cleanup repos + keyrings + validate APT +# install_packages_with_retry() - Install with 3 retries and APT refresh +# upgrade_packages_with_retry() - Upgrade with 3 retries and APT refresh +# +# ============================================================================== # ------------------------------------------------------------------------------ # Cache installed version to avoid repeated checks @@ -25,6 +51,572 @@ get_cached_version() { } # ------------------------------------------------------------------------------ +# Clean up ALL keyring locations for a tool (unified helper) +# Usage: cleanup_tool_keyrings "mariadb" "mysql" "postgresql" +# ------------------------------------------------------------------------------ +cleanup_tool_keyrings() { + local tool_patterns=("$@") + + for pattern in "${tool_patterns[@]}"; do + rm -f /usr/share/keyrings/${pattern}*.gpg \ + /etc/apt/keyrings/${pattern}*.gpg \ + /etc/apt/trusted.gpg.d/${pattern}*.gpg 2>/dev/null || true + done +} + +# ------------------------------------------------------------------------------ +# Stop and disable all service instances matching a pattern +# Usage: stop_all_services "php*-fpm" "mysql" "mariadb" +# ------------------------------------------------------------------------------ +stop_all_services() { + local service_patterns=("$@") + + for pattern in "${service_patterns[@]}"; do + # Find all matching services + systemctl list-units --type=service --all 2>/dev/null | + grep -oE "${pattern}[^ ]*\.service" | + sort -u | + while read -r service; do + $STD systemctl stop "$service" 2>/dev/null || true + $STD systemctl disable "$service" 2>/dev/null || true + done + done +} + +# ------------------------------------------------------------------------------ +# Verify installed tool version matches expected version +# Returns: 0 if match, 1 if mismatch (with warning) +# Usage: verify_tool_version "nodejs" "22" "$(node -v | grep -oP '^v\K[0-9]+')" +# ------------------------------------------------------------------------------ +verify_tool_version() { + local tool_name="$1" + local expected_version="$2" + local installed_version="$3" + + # Extract major version for comparison + local expected_major="${expected_version%%.*}" + local installed_major="${installed_version%%.*}" + + if [[ "$installed_major" != "$expected_major" ]]; then + msg_warn "$tool_name version mismatch: expected $expected_version, got $installed_version" + return 1 + fi + + return 0 +} + +# ------------------------------------------------------------------------------ +# Clean up legacy installation methods (nvm, rbenv, rustup, etc.) +# Usage: cleanup_legacy_install "nodejs" -> removes nvm +# ------------------------------------------------------------------------------ +cleanup_legacy_install() { + local tool_name="$1" + + case "$tool_name" in + nodejs | node) + if [[ -d "$HOME/.nvm" ]]; then + msg_info "Removing legacy nvm installation" + rm -rf "$HOME/.nvm" "$HOME/.npm" "$HOME/.bower" "$HOME/.config/yarn" 2>/dev/null || true + sed -i '/NVM_DIR/d' "$HOME/.bashrc" "$HOME/.profile" 2>/dev/null || true + msg_ok "Legacy nvm installation removed" + fi + ;; + ruby) + if [[ -d "$HOME/.rbenv" ]]; then + msg_info "Removing legacy rbenv installation" + rm -rf "$HOME/.rbenv" 2>/dev/null || true + sed -i '/rbenv/d' "$HOME/.bashrc" "$HOME/.profile" 2>/dev/null || true + msg_ok "Legacy rbenv installation removed" + fi + ;; + rust) + if [[ -d "$HOME/.cargo" ]] || [[ -d "$HOME/.rustup" ]]; then + msg_info "Removing legacy rustup installation" + rm -rf "$HOME/.cargo" "$HOME/.rustup" 2>/dev/null || true + sed -i '/cargo/d' "$HOME/.bashrc" "$HOME/.profile" 2>/dev/null || true + msg_ok "Legacy rustup installation removed" + fi + ;; + go | golang) + if [[ -d "$HOME/go" ]]; then + msg_info "Removing legacy Go workspace" + # Keep user code, just remove GOPATH env + sed -i '/GOPATH/d' "$HOME/.bashrc" "$HOME/.profile" 2>/dev/null || true + msg_ok "Legacy Go workspace cleaned" + fi + ;; + esac +} + +# ------------------------------------------------------------------------------ +# Unified repository preparation before setup +# Cleans up old repos, keyrings, and ensures APT is working +# Usage: prepare_repository_setup "mariadb" "mysql" +# ------------------------------------------------------------------------------ +prepare_repository_setup() { + local repo_names=("$@") + + # Clean up all old repository files + for repo in "${repo_names[@]}"; do + cleanup_old_repo_files "$repo" + done + + # Clean up all keyrings + cleanup_tool_keyrings "${repo_names[@]}" + + # Ensure APT is in working state + ensure_apt_working || return 1 + + return 0 +} + +# ------------------------------------------------------------------------------ +# Install packages with retry logic +# Usage: install_packages_with_retry "mysql-server" "mysql-client" +# ------------------------------------------------------------------------------ +install_packages_with_retry() { + local packages=("$@") + local max_retries=2 + local retry=0 + + while [[ $retry -le $max_retries ]]; do + if $STD apt install -y "${packages[@]}" 2>/dev/null; then + return 0 + fi + + retry=$((retry + 1)) + if [[ $retry -le $max_retries ]]; then + msg_warn "Package installation failed, retrying ($retry/$max_retries)..." + sleep 2 + $STD apt update 2>/dev/null || true + fi + done + + return 1 +} + +# ------------------------------------------------------------------------------ +# Upgrade specific packages with retry logic +# Usage: upgrade_packages_with_retry "mariadb-server" "mariadb-client" +# ------------------------------------------------------------------------------ +upgrade_packages_with_retry() { + local packages=("$@") + local max_retries=2 + local retry=0 + + while [[ $retry -le $max_retries ]]; do + if $STD apt install --only-upgrade -y "${packages[@]}" 2>/dev/null; then + return 0 + fi + + retry=$((retry + 1)) + if [[ $retry -le $max_retries ]]; then + msg_warn "Package upgrade failed, retrying ($retry/$max_retries)..." + sleep 2 + $STD apt update 2>/dev/null || true + fi + done + + return 1 +} + +# ------------------------------------------------------------------------------ +# Check if tool is already installed and optionally verify exact version +# Returns: 0 if installed (with optional version match), 1 if not installed +# Usage: is_tool_installed "mariadb" "11.4" || echo "Not installed" +# ------------------------------------------------------------------------------ +is_tool_installed() { + local tool_name="$1" + local required_version="${2:-}" + local installed_version="" + + case "$tool_name" in + mariadb) + if command -v mariadb >/dev/null 2>&1; then + installed_version=$(mariadb --version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1) + fi + ;; + mysql) + if command -v mysql >/dev/null 2>&1; then + installed_version=$(mysql --version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1) + fi + ;; + mongodb | mongod) + if command -v mongod >/dev/null 2>&1; then + installed_version=$(mongod --version 2>/dev/null | awk '/db version/{print $3}' | cut -d. -f1,2) + fi + ;; + node | nodejs) + if command -v node >/dev/null 2>&1; then + installed_version=$(node -v 2>/dev/null | grep -oP '^v\K[0-9]+') + fi + ;; + php) + if command -v php >/dev/null 2>&1; then + installed_version=$(php -v 2>/dev/null | awk '/^PHP/{print $2}' | cut -d. -f1,2) + fi + ;; + postgres | postgresql) + if command -v psql >/dev/null 2>&1; then + installed_version=$(psql --version 2>/dev/null | awk '{print $3}' | cut -d. -f1) + fi + ;; + ruby) + if command -v ruby >/dev/null 2>&1; then + installed_version=$(ruby --version 2>/dev/null | awk '{print $2}' | cut -d. -f1,2) + fi + ;; + rust | rustc) + if command -v rustc >/dev/null 2>&1; then + installed_version=$(rustc --version 2>/dev/null | awk '{print $2}') + fi + ;; + go | golang) + if command -v go >/dev/null 2>&1; then + installed_version=$(go version 2>/dev/null | awk '{print $3}' | sed 's/go//') + fi + ;; + clickhouse) + if command -v clickhouse >/dev/null 2>&1; then + installed_version=$(clickhouse --version 2>/dev/null | awk '{print $2}') + fi + ;; + esac + + if [[ -z "$installed_version" ]]; then + return 1 # Not installed + fi + + if [[ -n "$required_version" && "$installed_version" != "$required_version" ]]; then + echo "$installed_version" + return 1 # Version mismatch + fi + + echo "$installed_version" + return 0 # Installed and version matches (if specified) +} + +# ------------------------------------------------------------------------------ +# Remove old tool version completely (purge + cleanup repos) +# Usage: remove_old_tool_version "mariadb" "repository-name" +# ------------------------------------------------------------------------------ +remove_old_tool_version() { + local tool_name="$1" + local repo_name="${2:-$tool_name}" + + case "$tool_name" in + mariadb) + stop_all_services "mariadb" + $STD apt purge -y 'mariadb*' >/dev/null 2>&1 || true + cleanup_tool_keyrings "mariadb" + ;; + mysql) + stop_all_services "mysql" + $STD apt purge -y 'mysql*' >/dev/null 2>&1 || true + rm -rf /var/lib/mysql 2>/dev/null || true + cleanup_tool_keyrings "mysql" + ;; + mongodb) + stop_all_services "mongod" + $STD apt purge -y 'mongodb*' >/dev/null 2>&1 || true + rm -rf /var/lib/mongodb 2>/dev/null || true + cleanup_tool_keyrings "mongodb" + ;; + node | nodejs) + $STD apt purge -y nodejs npm >/dev/null 2>&1 || true + # Clean up npm global modules + if command -v npm >/dev/null 2>&1; then + npm list -g 2>/dev/null | grep -oE '^ \S+' | awk '{print $1}' | while read -r module; do + npm uninstall -g "$module" >/dev/null 2>&1 || true + done + fi + cleanup_legacy_install "nodejs" + cleanup_tool_keyrings "nodesource" + ;; + php) + stop_all_services "php.*-fpm" + $STD apt purge -y 'php*' >/dev/null 2>&1 || true + rm -rf /etc/php 2>/dev/null || true + cleanup_tool_keyrings "deb.sury.org-php" "php" + ;; + postgresql) + stop_all_services "postgresql" + $STD apt purge -y 'postgresql*' >/dev/null 2>&1 || true + # Keep data directory for safety (can be removed manually if needed) + # rm -rf /var/lib/postgresql 2>/dev/null || true + cleanup_tool_keyrings "postgresql" "pgdg" + ;; + java) + $STD apt purge -y 'temurin*' 'adoptium*' 'openjdk*' >/dev/null 2>&1 || true + cleanup_tool_keyrings "adoptium" + ;; + ruby) + cleanup_legacy_install "ruby" + $STD apt purge -y 'ruby*' >/dev/null 2>&1 || true + ;; + rust) + cleanup_legacy_install "rust" + ;; + go | golang) + rm -rf /usr/local/go 2>/dev/null || true + cleanup_legacy_install "golang" + ;; + clickhouse) + stop_all_services "clickhouse-server" + $STD apt purge -y 'clickhouse*' >/dev/null 2>&1 || true + rm -rf /var/lib/clickhouse 2>/dev/null || true + cleanup_tool_keyrings "clickhouse" + ;; + esac + + # Clean up old repository files (both .list and .sources) + cleanup_old_repo_files "$repo_name" + + return 0 +} + +# ------------------------------------------------------------------------------ +# Determine if tool update/upgrade is needed +# Returns: 0 (update needed), 1 (already up-to-date) +# Usage: if should_update_tool "mariadb" "11.4"; then ... fi +# ------------------------------------------------------------------------------ +should_update_tool() { + local tool_name="$1" + local target_version="$2" + local current_version="" + + # Get currently installed version + current_version=$(is_tool_installed "$tool_name" 2>/dev/null) || return 0 # Not installed = needs install + + # If versions are identical, no update needed + if [[ "$current_version" == "$target_version" ]]; then + return 1 # No update needed + fi + + return 0 # Update needed +} + +# ---------------------–---------------------------------------------------------- +# Unified repository management for tools +# Handles adding, updating, and verifying tool repositories +# Usage: manage_tool_repository "mariadb" "11.4" "https://repo..." "GPG_key_url" +# Supports: mariadb, mongodb, nodejs, postgresql, php, mysql +# ------------------------------------------------------------------------------ +manage_tool_repository() { + local tool_name="$1" + local version="$2" + local repo_url="$3" + local gpg_key_url="${4:-}" + local distro_id repo_component suite + + distro_id=$(awk -F= '/^ID=/{print $2}' /etc/os-release | tr -d '"') + + case "$tool_name" in + mariadb) + if [[ -z "$repo_url" || -z "$gpg_key_url" ]]; then + msg_error "MariaDB repository requires repo_url and gpg_key_url" + return 1 + fi + + # Clean old repos first + cleanup_old_repo_files "mariadb" + + # Get suite for fallback handling + local distro_codename + distro_codename=$(awk -F= '/^VERSION_CODENAME=/{print $2}' /etc/os-release) + suite=$(get_fallback_suite "$distro_id" "$distro_codename" "$repo_url/$distro_id") + + # Setup new repository using deb822 format + setup_deb822_repo "mariadb" "$gpg_key_url" "$repo_url/$distro_id" "$suite" "main" "amd64 arm64" || return 1 + return 0 + ;; + + mongodb) + if [[ -z "$repo_url" || -z "$gpg_key_url" ]]; then + msg_error "MongoDB repository requires repo_url and gpg_key_url" + return 1 + fi + + # Clean old repos first + cleanup_old_repo_files "mongodb" + + # Import GPG key + mkdir -p /etc/apt/keyrings + if ! curl -fsSL "$gpg_key_url" | gpg --dearmor --yes -o "/etc/apt/keyrings/mongodb-server-${version}.gpg" 2>/dev/null; then + msg_error "Failed to download MongoDB GPG key" + return 1 + fi + + # Setup repository + local distro_codename + distro_codename=$(awk -F= '/^VERSION_CODENAME=/{print $2}' /etc/os-release) + + # Suite mapping with fallback for newer releases not yet supported by upstream + if [[ "$distro_id" == "debian" ]]; then + case "$distro_codename" in + trixie | forky | sid) + # Testing/unstable releases fallback to latest stable suite + suite="bookworm" + ;; + bookworm) + suite="bookworm" + ;; + bullseye) + suite="bullseye" + ;; + *) + # Unknown release: fallback to latest stable suite + msg_warn "Unknown Debian release '${distro_codename}', using bookworm" + suite="bookworm" + ;; + esac + elif [[ "$distro_id" == "ubuntu" ]]; then + case "$distro_codename" in + oracular | plucky) + # Newer releases fallback to latest LTS + suite="noble" + ;; + noble) + suite="noble" + ;; + jammy) + suite="jammy" + ;; + focal) + suite="focal" + ;; + *) + # Unknown release: fallback to latest LTS + msg_warn "Unknown Ubuntu release '${distro_codename}', using noble" + suite="noble" + ;; + esac + else + # For other distros, try generic fallback + suite=$(get_fallback_suite "$distro_id" "$distro_codename" "$repo_url") + fi + + repo_component="main" + [[ "$distro_id" == "ubuntu" ]] && repo_component="multiverse" + + cat </etc/apt/sources.list.d/mongodb-org-${version}.sources +Types: deb +URIs: ${repo_url} +Suites: ${suite}/mongodb-org/${version} +Components: ${repo_component} +Architectures: amd64 arm64 +Signed-By: /etc/apt/keyrings/mongodb-server-${version}.gpg +EOF + return 0 + ;; + + nodejs) + if [[ -z "$repo_url" || -z "$gpg_key_url" ]]; then + msg_error "Node.js repository requires repo_url and gpg_key_url" + return 1 + fi + + cleanup_old_repo_files "nodesource" + + # NodeSource uses deb822 format with GPG from repo + local distro_codename + distro_codename=$(awk -F= '/^VERSION_CODENAME=/{print $2}' /etc/os-release) + + # Create keyring directory first + mkdir -p /etc/apt/keyrings + + # Download GPG key from NodeSource + curl -fsSL "$gpg_key_url" | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg || { + msg_error "Failed to import NodeSource GPG key" + return 1 + } + + cat </etc/apt/sources.list.d/nodesource.sources +Types: deb +URIs: $repo_url +Suites: nodistro +Components: main +Architectures: amd64 arm64 +Signed-By: /etc/apt/keyrings/nodesource.gpg +EOF + return 0 + ;; + + php) + if [[ -z "$gpg_key_url" ]]; then + msg_error "PHP repository requires gpg_key_url" + return 1 + fi + + cleanup_old_repo_files "php" + + # Download and install keyring + curl -fsSLo /tmp/debsuryorg-archive-keyring.deb "$gpg_key_url" || { + msg_error "Failed to download PHP keyring" + return 1 + } + dpkg -i /tmp/debsuryorg-archive-keyring.deb >/dev/null 2>&1 || { + msg_error "Failed to install PHP keyring" + rm -f /tmp/debsuryorg-archive-keyring.deb + return 1 + } + rm -f /tmp/debsuryorg-archive-keyring.deb + + # Setup repository + local distro_codename + distro_codename=$(awk -F= '/^VERSION_CODENAME=/{print $2}' /etc/os-release) + cat </etc/apt/sources.list.d/php.sources +Types: deb +URIs: https://packages.sury.org/php +Suites: $distro_codename +Components: main +Architectures: amd64 arm64 +Signed-By: /usr/share/keyrings/deb.sury.org-php.gpg +EOF + return 0 + ;; + + postgresql) + if [[ -z "$gpg_key_url" ]]; then + msg_error "PostgreSQL repository requires gpg_key_url" + return 1 + fi + + cleanup_old_repo_files "postgresql" + + # Create keyring directory first + mkdir -p /etc/apt/keyrings + + # Import PostgreSQL key + curl -fsSL "$gpg_key_url" | gpg --dearmor -o /etc/apt/keyrings/postgresql.gpg || { + msg_error "Failed to import PostgreSQL GPG key" + return 1 + } + + # Setup repository + local distro_codename + distro_codename=$(awk -F= '/^VERSION_CODENAME=/{print $2}' /etc/os-release) + cat </etc/apt/sources.list.d/postgresql.sources +Types: deb +URIs: http://apt.postgresql.org/pub/repos/apt +Suites: $distro_codename-pgdg +Components: main +Architectures: amd64 arm64 +Signed-By: /etc/apt/keyrings/postgresql.gpg +EOF + return 0 + ;; + + *) + msg_error "Unknown tool repository: $tool_name" + return 1 + ;; + esac + + return 0 +} + +# ------–---------------------------------------------------------------------- # Unified package upgrade function (with apt update caching) # ------------------------------------------------------------------------------ upgrade_package() { @@ -40,11 +632,16 @@ upgrade_package() { fi if ((current_time - last_update > 300)); then - $STD apt update + $STD apt update || { + msg_warn "APT update failed in upgrade_package - continuing with cached packages" + } echo "$current_time" >"$apt_cache_file" fi - $STD apt install --only-upgrade -y "$package" + $STD apt install --only-upgrade -y "$package" || { + msg_warn "Failed to upgrade $package" + return 1 + } } # ------------------------------------------------------------------------------ @@ -580,13 +1177,13 @@ ensure_apt_working() { cleanup_orphaned_sources # Try to update package lists - if ! apt-get update -qq 2>/dev/null; then + if ! $STD apt update; then # More aggressive cleanup rm -f /etc/apt/sources.list.d/*.sources 2>/dev/null || true cleanup_orphaned_sources # Try again - if ! apt-get update -qq 2>/dev/null; then + if ! $STD apt update; then msg_error "Cannot update package lists - APT is critically broken" return 1 fi @@ -597,6 +1194,7 @@ ensure_apt_working() { # ------------------------------------------------------------------------------ # Standardized deb822 repository setup +# Validates all parameters and fails safely if any are empty # ------------------------------------------------------------------------------ setup_deb822_repo() { local name="$1" @@ -606,6 +1204,12 @@ setup_deb822_repo() { local component="${5:-main}" local architectures="${6:-amd64 arm64}" + # Validate required parameters + if [[ -z "$name" || -z "$gpg_url" || -z "$repo_url" || -z "$suite" ]]; then + msg_error "setup_deb822_repo: missing required parameters (name=$name, gpg=$gpg_url, repo=$repo_url, suite=$suite)" + return 1 + fi + # Cleanup old configs for this app cleanup_old_repo_files "$name" @@ -613,11 +1217,14 @@ setup_deb822_repo() { cleanup_orphaned_sources # Ensure keyring directory exists - mkdir -p /etc/apt/keyrings + mkdir -p /etc/apt/keyrings || { + msg_error "Failed to create /etc/apt/keyrings directory" + return 1 + } # Download GPG key (with --yes to avoid interactive prompts) - curl -fsSL "$gpg_url" | gpg --dearmor --yes -o "/etc/apt/keyrings/${name}.gpg" || { - msg_error "Failed to download or import GPG key for ${name}" + curl -fsSL "$gpg_url" | gpg --dearmor --yes -o "/etc/apt/keyrings/${name}.gpg" 2>/dev/null || { + msg_error "Failed to download or import GPG key for ${name} from $gpg_url" return 1 } @@ -939,11 +1546,8 @@ create_self_signed_cert() { return 0 fi - $STD apt update || { - msg_error "Failed to update package list" - return 1 - } - $STD apt install -y openssl || { + # Use ensure_dependencies for cleaner handling + ensure_dependencies openssl || { msg_error "Failed to install OpenSSL" return 1 } @@ -1419,9 +2023,6 @@ function import_local_ip() { # ------------------------------------------------------------------------------ function setup_adminer() { - local CACHED_VERSION - CACHED_VERSION=$(get_cached_version "adminer") - if grep -qi alpine /etc/os-release; then msg_info "Setup Adminer (Alpine)" mkdir -p /var/www/localhost/htdocs/adminer @@ -1456,14 +2057,31 @@ function setup_adminer() { # - Installs to /usr/local/bin/composer # - Removes old binaries/symlinks in /usr/bin, /bin, /root/.composer, etc. # - Ensures /usr/local/bin is in PATH (permanent) +# - Auto-updates to latest version # ------------------------------------------------------------------------------ function setup_composer() { local COMPOSER_BIN="/usr/local/bin/composer" - local CACHED_VERSION - CACHED_VERSION=$(get_cached_version "composer") export COMPOSER_ALLOW_SUPERUSER=1 + # Get currently installed version + local INSTALLED_VERSION="" + if [[ -x "$COMPOSER_BIN" ]]; then + INSTALLED_VERSION=$("$COMPOSER_BIN" --version 2>/dev/null | awk '{print $3}') + fi + + # Scenario 1: Already installed - just self-update + if [[ -n "$INSTALLED_VERSION" ]]; then + msg_info "Update Composer $INSTALLED_VERSION" + $STD "$COMPOSER_BIN" self-update --no-interaction || true + local UPDATED_VERSION + UPDATED_VERSION=$("$COMPOSER_BIN" --version 2>/dev/null | awk '{print $3}') + cache_installed_version "composer" "$UPDATED_VERSION" + msg_ok "Update Composer $UPDATED_VERSION" + return 0 + fi + + # Scenario 2: Fresh install msg_info "Setup Composer" for old in /usr/bin/composer /bin/composer /root/.composer/vendor/bin/composer; do @@ -1523,8 +2141,12 @@ function setup_ffmpeg() { local VERSION="${FFMPEG_VERSION:-latest}" local TYPE="${FFMPEG_TYPE:-full}" local BIN_PATH="/usr/local/bin/ffmpeg" - local CACHED_VERSION - CACHED_VERSION=$(get_cached_version "ffmpeg") + + # Get currently installed version + local INSTALLED_VERSION="" + if command -v ffmpeg &>/dev/null; then + INSTALLED_VERSION=$(ffmpeg -version 2>/dev/null | head -n1 | awk '{print $3}') + fi msg_info "Setup FFmpeg ${VERSION} ($TYPE)" @@ -1545,11 +2167,11 @@ function setup_ffmpeg() { cp "$EXTRACTED_DIR/ffmpeg" "$BIN_PATH" cp "$EXTRACTED_DIR/ffprobe" /usr/local/bin/ffprobe chmod +x "$BIN_PATH" /usr/local/bin/ffprobe - local FINAL_VERSION=$($BIN_PATH -version | head -n1 | awk '{print $3}') + local FINAL_VERSION=$($BIN_PATH -version 2>/dev/null | head -n1 | awk '{print $3}') rm -rf "$TMP_DIR" cache_installed_version "ffmpeg" "$FINAL_VERSION" ensure_usr_local_bin_persist - msg_ok "Setup FFmpeg" + [[ -n "$INSTALLED_VERSION" ]] && msg_ok "Upgrade FFmpeg $INSTALLED_VERSION → $FINAL_VERSION" || msg_ok "Setup FFmpeg $FINAL_VERSION" return 0 fi @@ -1557,16 +2179,22 @@ function setup_ffmpeg() { # Auto-detect latest stable version if none specified if [[ "$VERSION" == "latest" || -z "$VERSION" ]]; then - VERSION=$(curl -fsSL "https://api.github.com/repos/${GITHUB_REPO}/tags" | - jq -r '.[].name' | - grep -E '^n[0-9]+\.[0-9]+\.[0-9]+$' | - sort -V | tail -n1) + local ffmpeg_tags + ffmpeg_tags=$(curl -fsSL --max-time 15 "https://api.github.com/repos/${GITHUB_REPO}/tags" 2>/dev/null || echo "") + + if [[ -z "$ffmpeg_tags" ]]; then + msg_warn "Could not fetch FFmpeg versions from GitHub, trying binary fallback" + VERSION="" # Will trigger binary fallback below + else + VERSION=$(echo "$ffmpeg_tags" | jq -r '.[].name' 2>/dev/null | + grep -E '^n[0-9]+\.[0-9]+\.[0-9]+$' | + sort -V | tail -n1 || echo "") + fi fi if [[ -z "$VERSION" ]]; then - msg_error "Could not determine FFmpeg version" - rm -rf "$TMP_DIR" - return 1 + msg_info "Could not determine FFmpeg source version, using pre-built binary" + VERSION="" # Will use binary fallback fi # Dependency selection @@ -1595,14 +2223,43 @@ function setup_ffmpeg() { ensure_dependencies "${DEPS[@]}" - curl -fsSL "https://github.com/${GITHUB_REPO}/archive/refs/tags/${VERSION}.tar.gz" -o "$TMP_DIR/ffmpeg.tar.gz" || { - msg_error "Failed to download FFmpeg source" + # Try to download source if VERSION is set + if [[ -n "$VERSION" ]]; then + curl -fsSL "https://github.com/${GITHUB_REPO}/archive/refs/tags/${VERSION}.tar.gz" -o "$TMP_DIR/ffmpeg.tar.gz" || { + msg_warn "Failed to download FFmpeg source ${VERSION}, falling back to pre-built binary" + VERSION="" + } + fi + + # If no source download (either VERSION empty or download failed), use binary + if [[ -z "$VERSION" ]]; then + msg_info "Setup FFmpeg from pre-built binary" + curl -fsSL https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz -o "$TMP_DIR/ffmpeg.tar.xz" || { + msg_error "Failed to download FFmpeg pre-built binary" + rm -rf "$TMP_DIR" + return 1 + } + + tar -xJf "$TMP_DIR/ffmpeg.tar.xz" -C "$TMP_DIR" || { + msg_error "Failed to extract FFmpeg binary archive" + rm -rf "$TMP_DIR" + return 1 + } + + if ! cp "$TMP_DIR/ffmpeg-"*/ffmpeg /usr/local/bin/ffmpeg 2>/dev/null; then + msg_error "Failed to install FFmpeg binary" + rm -rf "$TMP_DIR" + return 1 + fi + + cache_installed_version "ffmpeg" "static" rm -rf "$TMP_DIR" - return 1 - } + msg_ok "Setup FFmpeg from pre-built binary" + return 0 + fi tar -xzf "$TMP_DIR/ffmpeg.tar.gz" -C "$TMP_DIR" || { - msg_error "Failed to extract FFmpeg" + msg_error "Failed to extract FFmpeg source" rm -rf "$TMP_DIR" return 1 } @@ -1656,7 +2313,7 @@ function setup_ffmpeg() { echo "/usr/local/lib" >/etc/ld.so.conf.d/ffmpeg.conf $STD ldconfig - ldconfig -p | grep libavdevice >/dev/null || { + ldconfig -p 2>/dev/null | grep libavdevice >/dev/null || { msg_error "libavdevice not registered with dynamic linker" rm -rf "$TMP_DIR" return 1 @@ -1669,11 +2326,11 @@ function setup_ffmpeg() { fi local FINAL_VERSION - FINAL_VERSION=$(ffmpeg -version | head -n1 | awk '{print $3}') + FINAL_VERSION=$(ffmpeg -version 2>/dev/null | head -n1 | awk '{print $3}') rm -rf "$TMP_DIR" cache_installed_version "ffmpeg" "$FINAL_VERSION" ensure_usr_local_bin_persist - msg_ok "Setup FFmpeg" + [[ -n "$INSTALLED_VERSION" ]] && msg_ok "Upgrade FFmpeg $INSTALLED_VERSION → $FINAL_VERSION" || msg_ok "Setup FFmpeg $FINAL_VERSION" } # ------------------------------------------------------------------------------ @@ -1698,42 +2355,48 @@ function setup_go() { ;; esac - # Determine version - if [[ -z "${GO_VERSION:-}" || "${GO_VERSION}" == "latest" ]]; then - GO_VERSION=$(curl -fsSL https://go.dev/VERSION?m=text | head -n1 | sed 's/^go//') - if [[ -z "$GO_VERSION" ]]; then + # Resolve "latest" version + local GO_VERSION="${GO_VERSION:-latest}" + if [[ "$GO_VERSION" == "latest" ]]; then + GO_VERSION=$(curl -fsSL https://go.dev/VERSION?m=text 2>/dev/null | head -n1 | sed 's/^go//') || { msg_error "Could not determine latest Go version" return 1 - fi + } + [[ -z "$GO_VERSION" ]] && { + msg_error "Latest Go version is empty" + return 1 + } fi local GO_BIN="/usr/local/bin/go" local GO_INSTALL_DIR="/usr/local/go" - local CACHED_VERSION - CACHED_VERSION=$(get_cached_version "go") + # Get currently installed version + local CURRENT_VERSION="" if [[ -x "$GO_BIN" ]]; then - local CURRENT_VERSION - CURRENT_VERSION=$("$GO_BIN" version | awk '{print $3}' | sed 's/go//') - if [[ "$CURRENT_VERSION" == "$GO_VERSION" ]]; then - if [[ "$CACHED_VERSION" == "$GO_VERSION" ]]; then - return 0 - fi - cache_installed_version "go" "$GO_VERSION" - return 0 - else - rm -rf "$GO_INSTALL_DIR" - fi + CURRENT_VERSION=$("$GO_BIN" version 2>/dev/null | awk '{print $3}' | sed 's/go//') fi - msg_info "Setup Go $GO_VERSION" + # Scenario 1: Already at target version + if [[ -n "$CURRENT_VERSION" && "$CURRENT_VERSION" == "$GO_VERSION" ]]; then + cache_installed_version "go" "$GO_VERSION" + return 0 + fi + + # Scenario 2: Different version or not installed + if [[ -n "$CURRENT_VERSION" && "$CURRENT_VERSION" != "$GO_VERSION" ]]; then + msg_info "Upgrade Go from $CURRENT_VERSION to $GO_VERSION" + remove_old_tool_version "go" + else + msg_info "Setup Go $GO_VERSION" + fi local TARBALL="go${GO_VERSION}.linux-${ARCH}.tar.gz" local URL="https://go.dev/dl/${TARBALL}" local TMP_TAR=$(mktemp) curl -fsSL "$URL" -o "$TMP_TAR" || { - msg_error "Failed to download $TARBALL" + msg_error "Failed to download Go $GO_VERSION" rm -f "$TMP_TAR" return 1 } @@ -1743,6 +2406,7 @@ function setup_go() { rm -f "$TMP_TAR" return 1 } + ln -sf /usr/local/go/bin/go /usr/local/bin/go ln -sf /usr/local/go/bin/gofmt /usr/local/bin/gofmt rm -f "$TMP_TAR" @@ -1763,35 +2427,53 @@ function setup_go() { function setup_gs() { local TMP_DIR=$(mktemp -d) local CURRENT_VERSION=$(gs --version 2>/dev/null || echo "0") - local CACHED_VERSION - CACHED_VERSION=$(get_cached_version "ghostscript") ensure_dependencies jq local RELEASE_JSON - RELEASE_JSON=$(curl -fsSL https://api.github.com/repos/ArtifexSoftware/ghostpdl-downloads/releases/latest) + RELEASE_JSON=$(curl -fsSL --max-time 15 https://api.github.com/repos/ArtifexSoftware/ghostpdl-downloads/releases/latest 2>/dev/null || echo "") + + if [[ -z "$RELEASE_JSON" ]]; then + msg_warn "Cannot fetch latest Ghostscript version from GitHub API" + # Try to get from current version + if command -v gs &>/dev/null; then + gs --version | head -n1 + cache_installed_version "ghostscript" "$CURRENT_VERSION" + return 0 + fi + msg_error "Cannot determine Ghostscript version and no existing installation found" + return 1 + fi local LATEST_VERSION LATEST_VERSION=$(echo "$RELEASE_JSON" | jq -r '.tag_name' | sed 's/^gs//') local LATEST_VERSION_DOTTED LATEST_VERSION_DOTTED=$(echo "$RELEASE_JSON" | jq -r '.name' | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+') if [[ -z "$LATEST_VERSION" || -z "$LATEST_VERSION_DOTTED" ]]; then - msg_error "Could not determine latest Ghostscript version" + msg_warn "Could not determine latest Ghostscript version from GitHub - checking system" + # Fallback: try to use system version or return error + if [[ "$CURRENT_VERSION" == "0" ]]; then + msg_error "Ghostscript not installed and cannot determine latest version" + rm -rf "$TMP_DIR" + return 1 + fi rm -rf "$TMP_DIR" - return 1 + return 0 fi - if dpkg --compare-versions "$CURRENT_VERSION" ge "$LATEST_VERSION_DOTTED" 2>/dev/null; then - if [[ "$CACHED_VERSION" == "$LATEST_VERSION_DOTTED" ]]; then - rm -rf "$TMP_DIR" - return 0 - fi + # Scenario 1: Already at latest version + if [[ -n "$LATEST_VERSION_DOTTED" ]] && dpkg --compare-versions "$CURRENT_VERSION" ge "$LATEST_VERSION_DOTTED" 2>/dev/null; then cache_installed_version "ghostscript" "$LATEST_VERSION_DOTTED" rm -rf "$TMP_DIR" return 0 fi - msg_info "Setup Ghostscript $LATEST_VERSION_DOTTED" + # Scenario 2: New install or upgrade + if [[ "$CURRENT_VERSION" != "0" && "$CURRENT_VERSION" != "$LATEST_VERSION_DOTTED" ]]; then + msg_info "Upgrade Ghostscript from $CURRENT_VERSION to $LATEST_VERSION_DOTTED" + else + msg_info "Setup Ghostscript $LATEST_VERSION_DOTTED" + fi curl -fsSL "https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs${LATEST_VERSION}/ghostscript-${LATEST_VERSION_DOTTED}.tar.gz" -o "$TMP_DIR/ghostscript.tar.gz" || { msg_error "Failed to download Ghostscript" @@ -1805,6 +2487,13 @@ function setup_gs() { return 1 fi + # Verify directory exists before cd + if [[ ! -d "$TMP_DIR/ghostscript-${LATEST_VERSION_DOTTED}" ]]; then + msg_error "Ghostscript source directory not found: $TMP_DIR/ghostscript-${LATEST_VERSION_DOTTED}" + rm -rf "$TMP_DIR" + return 1 + fi + cd "$TMP_DIR/ghostscript-${LATEST_VERSION_DOTTED}" || { msg_error "Failed to enter Ghostscript source directory" rm -rf "$TMP_DIR" @@ -1869,21 +2558,26 @@ function setup_hwaccel() { # Detect GPU vendor (Intel, AMD, NVIDIA) local gpu_vendor - gpu_vendor=$(lspci | grep -Ei 'vga|3d|display' | grep -Eo 'Intel|AMD|NVIDIA' | head -n1) + gpu_vendor=$(lspci 2>/dev/null | grep -Ei 'vga|3d|display' | grep -Eo 'Intel|AMD|NVIDIA' | head -n1 || echo "") # Detect CPU vendor (relevant for AMD APUs) local cpu_vendor - cpu_vendor=$(lscpu | grep -i 'Vendor ID' | awk '{print $3}') + cpu_vendor=$(lscpu 2>/dev/null | grep -i 'Vendor ID' | awk '{print $3}' || echo "") if [[ -z "$gpu_vendor" && -z "$cpu_vendor" ]]; then msg_error "No GPU or CPU vendor detected (missing lspci/lscpu output)" return 1 fi - # Detect OS + # Detect OS with fallbacks local os_id os_codename - os_id=$(grep -oP '(?<=^ID=).+' /etc/os-release | tr -d '"') - os_codename=$(grep -oP '(?<=^VERSION_CODENAME=).+' /etc/os-release | tr -d '"') + os_id=$(grep -oP '(?<=^ID=).+' /etc/os-release 2>/dev/null | tr -d '"' || grep '^ID=' /etc/os-release 2>/dev/null | cut -d'=' -f2 | tr -d '"' || echo "debian") + os_codename=$(grep -oP '(?<=^VERSION_CODENAME=).+' /etc/os-release 2>/dev/null | tr -d '"' || grep '^VERSION_CODENAME=' /etc/os-release 2>/dev/null | cut -d'=' -f2 | tr -d '"' || echo "unknown") + + # Validate os_id + if [[ -z "$os_id" ]]; then + os_id="debian" + fi # Determine if we are on a VM or LXC local in_ct="${CTTYPE:-0}" @@ -1891,34 +2585,55 @@ function setup_hwaccel() { case "$gpu_vendor" in Intel) if [[ "$os_id" == "ubuntu" ]]; then - $STD apt -y install intel-opencl-icd || msg_error "Failed to install intel-opencl-icd" + $STD apt -y install intel-opencl-icd || { + msg_error "Failed to install intel-opencl-icd" + return 1 + } else - fetch_and_deploy_gh_release "intel-igc-core-2" "intel/intel-graphics-compiler" "binary" "latest" "" "intel-igc-core-2_*_amd64.deb" - fetch_and_deploy_gh_release "intel-igc-opencl-2" "intel/intel-graphics-compiler" "binary" "latest" "" "intel-igc-opencl-2_*_amd64.deb" - fetch_and_deploy_gh_release "intel-libgdgmm12" "intel/compute-runtime" "binary" "latest" "" "libigdgmm12_*_amd64.deb" - fetch_and_deploy_gh_release "intel-opencl-icd" "intel/compute-runtime" "binary" "latest" "" "intel-opencl-icd_*_amd64.deb" + # For Debian: fetch Intel GPU drivers from GitHub + fetch_and_deploy_gh_release "" "intel/intel-graphics-compiler" "binary" "latest" "" "intel-igc-core-2_*_amd64.deb" || { + msg_warn "Failed to deploy Intel IGC core 2" + } + fetch_and_deploy_gh_release "" "intel/intel-graphics-compiler" "binary" "latest" "" "intel-igc-opencl-2_*_amd64.deb" || { + msg_warn "Failed to deploy Intel IGC OpenCL 2" + } + fetch_and_deploy_gh_release "" "intel/compute-runtime" "binary" "latest" "" "libigdgmm12_*_amd64.deb" || { + msg_warn "Failed to deploy Intel GDGMM12" + } + fetch_and_deploy_gh_release "" "intel/compute-runtime" "binary" "latest" "" "intel-opencl-icd_*_amd64.deb" || { + msg_warn "Failed to deploy Intel OpenCL ICD" + } fi - $STD apt -y install va-driver-all ocl-icd-libopencl1 vainfo intel-gpu-tools || msg_error "Failed to install GPU dependencies" + $STD apt -y install va-driver-all ocl-icd-libopencl1 vainfo intel-gpu-tools || { + msg_error "Failed to install Intel GPU dependencies" + return 1 + } ;; AMD) - $STD apt -y install mesa-va-drivers mesa-vdpau-drivers mesa-opencl-icd vainfo clinfo || msg_error "Failed to install AMD GPU dependencies" + $STD apt -y install mesa-va-drivers mesa-vdpau-drivers mesa-opencl-icd vainfo clinfo || { + msg_error "Failed to install AMD GPU dependencies" + return 1 + } # For AMD CPUs without discrete GPU (APUs) - if [[ "$cpu_vendor" == "AuthenticAMD" && "$gpu_vendor" != "AMD" ]]; then + if [[ "$cpu_vendor" == "AuthenticAMD" && -n "$gpu_vendor" ]]; then $STD apt -y install libdrm-amdgpu1 firmware-amd-graphics || true fi ;; NVIDIA) - # NVIDIA needs manual driver setup + # NVIDIA needs manual driver setup - skip for now + msg_info "NVIDIA GPU detected - manual driver setup required" ;; *) # If no discrete GPU, but AMD CPU (e.g., Ryzen APU) if [[ "$cpu_vendor" == "AuthenticAMD" ]]; then - $STD apt -y install mesa-opencl-icd ocl-icd-libopencl1 clinfo || msg_error "Failed to install Mesa OpenCL stack" + $STD apt -y install mesa-opencl-icd ocl-icd-libopencl1 clinfo || { + msg_error "Failed to install Mesa OpenCL stack" + return 1 + } else - msg_error "No supported GPU vendor detected" - return 1 + msg_warn "No supported GPU vendor detected - skipping GPU acceleration" fi ;; esac @@ -1931,6 +2646,7 @@ function setup_hwaccel() { $STD adduser "$(id -u -n)" render fi + cache_installed_version "hwaccel" "1.0" msg_ok "Setup Hardware Acceleration" } @@ -1947,20 +2663,12 @@ function setup_hwaccel() { # ------------------------------------------------------------------------------ function setup_imagemagick() { local TMP_DIR=$(mktemp -d) - local VERSION="" local BINARY_PATH="/usr/local/bin/magick" - local CACHED_VERSION - CACHED_VERSION=$(get_cached_version "imagemagick") + # Get currently installed version + local INSTALLED_VERSION="" if command -v magick &>/dev/null; then - VERSION=$(magick -version | awk '/^Version/ {print $3}') - if [[ "$CACHED_VERSION" == "$VERSION" ]]; then - rm -rf "$TMP_DIR" - return 0 - fi - cache_installed_version "imagemagick" "$VERSION" - rm -rf "$TMP_DIR" - return 0 + INSTALLED_VERSION=$(magick -version | awk '/^Version/ {print $3}') fi msg_info "Setup ImageMagick" @@ -2026,11 +2734,17 @@ function setup_imagemagick() { return 1 fi - VERSION=$("$BINARY_PATH" -version | awk '/^Version/ {print $3}') + local FINAL_VERSION + FINAL_VERSION=$("$BINARY_PATH" -version | awk '/^Version/ {print $3}') rm -rf "$TMP_DIR" - cache_installed_version "imagemagick" "$VERSION" + cache_installed_version "imagemagick" "$FINAL_VERSION" ensure_usr_local_bin_persist - msg_ok "Setup ImageMagick" + + if [[ -n "$INSTALLED_VERSION" ]]; then + msg_ok "Upgrade ImageMagick $INSTALLED_VERSION → $FINAL_VERSION" + else + msg_ok "Setup ImageMagick $FINAL_VERSION" + fi } # ------------------------------------------------------------------------------ @@ -2051,20 +2765,16 @@ function setup_java() { DISTRO_CODENAME=$(awk -F= '/VERSION_CODENAME/ { print $2 }' /etc/os-release) local DESIRED_PACKAGE="temurin-${JAVA_VERSION}-jdk" - # Check cached version - local CACHED_VERSION - CACHED_VERSION=$(get_cached_version "temurin-jdk") + # Prepare repository (cleanup + validation) + prepare_repository_setup "adoptium" || { + msg_error "Failed to prepare Adoptium repository" + return 1 + } - # Add repo nur wenn nötig + # Add repo if needed if [[ ! -f /etc/apt/sources.list.d/adoptium.sources ]]; then - # Cleanup old repository files - cleanup_old_repo_files "adoptium" - - # Use helper function to get fallback suite local SUITE SUITE=$(get_fallback_suite "$DISTRO_ID" "$DISTRO_CODENAME" "https://packages.adoptium.net/artifactory/deb") - - # Use standardized repo setup setup_deb822_repo \ "adoptium" \ "https://packages.adoptium.net/artifactory/api/gpg/key/public" \ @@ -2074,33 +2784,50 @@ function setup_java() { "amd64 arm64" fi + # Get currently installed version local INSTALLED_VERSION="" - if dpkg -l | grep -q "temurin-.*-jdk"; then - INSTALLED_VERSION=$(dpkg -l | awk '/temurin-.*-jdk/{print $2}' | grep -oP 'temurin-\K[0-9]+') + if dpkg -l | grep -q "temurin-.*-jdk" 2>/dev/null; then + INSTALLED_VERSION=$(dpkg -l 2>/dev/null | awk '/temurin-.*-jdk/{print $2}' | grep -oP 'temurin-\K[0-9]+' | head -n1 || echo "") fi - if [[ "$INSTALLED_VERSION" == "$JAVA_VERSION" ]]; then - if [[ "$CACHED_VERSION" == "$JAVA_VERSION" ]]; then - # Already at correct version, just upgrade if available - upgrade_package "$DESIRED_PACKAGE" - else - $STD apt update - $STD apt install --only-upgrade -y "$DESIRED_PACKAGE" - cache_installed_version "temurin-jdk" "$JAVA_VERSION" - fi - else - msg_info "Setup Temurin JDK $JAVA_VERSION" - if [[ -n "$INSTALLED_VERSION" ]]; then - $STD apt purge -y "temurin-${INSTALLED_VERSION}-jdk" - fi + # Validate INSTALLED_VERSION is not empty if matched + local JDK_COUNT=$(dpkg -l 2>/dev/null | grep -c "temurin-.*-jdk" || echo "0") + if [[ -z "$INSTALLED_VERSION" && "$JDK_COUNT" -gt 0 ]]; then + msg_warn "Found Temurin JDK but cannot determine version" + INSTALLED_VERSION="0" + fi - $STD apt install -y "$DESIRED_PACKAGE" || { - msg_error "Failed to install Temurin JDK $JAVA_VERSION" + # Scenario 1: Already at correct version + if [[ "$INSTALLED_VERSION" == "$JAVA_VERSION" ]]; then + msg_info "Update Temurin JDK $JAVA_VERSION" + ensure_apt_working || return 1 + upgrade_packages_with_retry "$DESIRED_PACKAGE" || { + msg_error "Failed to update Temurin JDK" return 1 } cache_installed_version "temurin-jdk" "$JAVA_VERSION" - msg_ok "Setup Temurin JDK $JAVA_VERSION" + msg_ok "Update Temurin JDK $JAVA_VERSION" + return 0 fi + + # Scenario 2: Different version - remove old and install new + if [[ -n "$INSTALLED_VERSION" ]]; then + msg_info "Upgrade Temurin JDK from $INSTALLED_VERSION to $JAVA_VERSION" + $STD apt purge -y "temurin-${INSTALLED_VERSION}-jdk" || true + else + msg_info "Setup Temurin JDK $JAVA_VERSION" + fi + + ensure_apt_working || return 1 + + # Install with retry logic + install_packages_with_retry "$DESIRED_PACKAGE" || { + msg_error "Failed to install Temurin JDK $JAVA_VERSION" + return 1 + } + + cache_installed_version "temurin-jdk" "$JAVA_VERSION" + msg_ok "Setup Temurin JDK $JAVA_VERSION" } # ------------------------------------------------------------------------------ @@ -2117,15 +2844,20 @@ function setup_local_ip_helper() { local IP_FILE="/run/local-ip.env" local DISPATCHER_SCRIPT="/etc/networkd-dispatcher/routable.d/10-update-local-ip.sh" + # Check if already set up + if [[ -f "$SCRIPT_PATH" && -f "$DISPATCHER_SCRIPT" ]]; then + msg_info "Update Local IP Helper" + cache_installed_version "local-ip-helper" "1.0" + msg_ok "Update Local IP Helper" + else + msg_info "Setup Local IP Helper" + fi + mkdir -p "$BASE_DIR" # Install networkd-dispatcher if not present if ! dpkg -s networkd-dispatcher >/dev/null 2>&1; then - $STD apt update || { - msg_error "Failed to update package list" - return 1 - } - $STD apt install -y networkd-dispatcher || { + ensure_dependencies networkd-dispatcher || { msg_error "Failed to install networkd-dispatcher" return 1 } @@ -2184,7 +2916,12 @@ $SCRIPT_PATH EOF chmod +x "$DISPATCHER_SCRIPT" - systemctl enable -q --now networkd-dispatcher.service + systemctl enable -q --now networkd-dispatcher.service || { + msg_warn "Failed to enable networkd-dispatcher service" + } + + cache_installed_version "local-ip-helper" "1.0" + msg_ok "Setup Local IP Helper" } # ------------------------------------------------------------------------------ @@ -2201,68 +2938,80 @@ EOF setup_mariadb() { local MARIADB_VERSION="${MARIADB_VERSION:-latest}" - local DISTRO_ID DISTRO_CODENAME - DISTRO_ID=$(awk -F= '/^ID=/{print $2}' /etc/os-release | tr -d '"') - DISTRO_CODENAME=$(awk -F= '/^VERSION_CODENAME=/{print $2}' /etc/os-release) - - if ! curl -fsI http://mirror.mariadb.org/repo/ >/dev/null; then - msg_error "MariaDB mirror not reachable" - return 1 - fi + # Resolve "latest" to actual version if [[ "$MARIADB_VERSION" == "latest" ]]; then - MARIADB_VERSION=$(curl -fsSL http://mirror.mariadb.org/repo/ | - grep -Eo '[0-9]+\.[0-9]+\.[0-9]+/' | - grep -vE 'rc/|rolling/' | - sed 's|/||' | - sort -Vr | - head -n1) - if [[ -z "$MARIADB_VERSION" ]]; then - msg_error "Could not determine latest GA MariaDB version" - return 1 - fi - fi - - local CURRENT_VERSION="" - if command -v mariadb >/dev/null; then - CURRENT_VERSION=$(mariadb --version | grep -oE '[0-9]+\.[0-9]+\.[0-9]+') - fi - - local CACHED_VERSION - CACHED_VERSION=$(get_cached_version "mariadb") - - if [[ "$CURRENT_VERSION" == "$MARIADB_VERSION" ]]; then - if [[ "$CACHED_VERSION" == "$MARIADB_VERSION" ]]; then - upgrade_package mariadb-server - upgrade_package mariadb-client + if ! curl -fsI --max-time 10 http://mirror.mariadb.org/repo/ >/dev/null 2>&1; then + msg_warn "MariaDB mirror not reachable - trying cached package list fallback" + # Fallback: try to use a known stable version + MARIADB_VERSION="12.0" else - $STD apt update || { - msg_error "Failed to update package list" - return 1 - } - $STD apt install --only-upgrade -y mariadb-server mariadb-client || { - msg_error "Failed to upgrade MariaDB" - return 1 - } - cache_installed_version "mariadb" "$MARIADB_VERSION" + MARIADB_VERSION=$(curl -fsSL --max-time 15 http://mirror.mariadb.org/repo/ 2>/dev/null | + grep -Eo '[0-9]+\.[0-9]+\.[0-9]+/' | + grep -vE 'rc/|rolling/' | + sed 's|/||' | + sort -Vr | + head -n1 || echo "") + + if [[ -z "$MARIADB_VERSION" ]]; then + msg_warn "Could not parse latest GA MariaDB version from mirror - using fallback" + MARIADB_VERSION="12.0" + fi fi + fi + + # Get currently installed version + local CURRENT_VERSION="" + CURRENT_VERSION=$(is_tool_installed "mariadb" 2>/dev/null) || true + + # Scenario 1: Already installed at target version - just update packages + if [[ -n "$CURRENT_VERSION" && "$CURRENT_VERSION" == "$MARIADB_VERSION" ]]; then + msg_info "Update MariaDB $MARIADB_VERSION" + + # Ensure APT is working + ensure_apt_working || return 1 + + # Check if repository needs to be refreshed + if [[ -f /etc/apt/sources.list.d/mariadb.sources ]]; then + local REPO_VERSION="" + REPO_VERSION=$(grep -oP 'repo/\K[0-9]+\.[0-9]+' /etc/apt/sources.list.d/mariadb.sources 2>/dev/null || echo "") + if [[ -n "$REPO_VERSION" && "$REPO_VERSION" != "${MARIADB_VERSION%.*}" ]]; then + msg_warn "Repository version mismatch, updating..." + manage_tool_repository "mariadb" "$MARIADB_VERSION" "http://mirror.mariadb.org/repo/$MARIADB_VERSION" \ + "https://mariadb.org/mariadb_release_signing_key.asc" || { + msg_error "Failed to update MariaDB repository" + return 1 + } + fi + fi + + # Perform upgrade with retry logic + ensure_apt_working || return 1 + upgrade_packages_with_retry "mariadb-server" "mariadb-client" || { + msg_error "Failed to upgrade MariaDB packages" + return 1 + } + cache_installed_version "mariadb" "$MARIADB_VERSION" + msg_ok "Update MariaDB $MARIADB_VERSION" return 0 fi - msg_info "Setup MariaDB $MARIADB_VERSION" - - if [[ -n "$CURRENT_VERSION" ]]; then - $STD systemctl stop mariadb >/dev/null 2>&1 || true - $STD apt purge -y 'mariadb*' || true + # Scenario 2: Different version installed - clean upgrade + if [[ -n "$CURRENT_VERSION" && "$CURRENT_VERSION" != "$MARIADB_VERSION" ]]; then + msg_info "Upgrade MariaDB from $CURRENT_VERSION to $MARIADB_VERSION" + remove_old_tool_version "mariadb" fi - # Ensure APT is working before proceeding - ensure_apt_working || return 1 + # Scenario 3: Fresh install or version change + msg_info "Setup MariaDB $MARIADB_VERSION" - # Cleanup old repository files - cleanup_old_repo_files "mariadb" + # Prepare repository (cleanup + validation) + prepare_repository_setup "mariadb" || { + msg_error "Failed to prepare MariaDB repository" + return 1 + } - # Install required dependencies first (MariaDB needs these from main repos) + # Install required dependencies first local mariadb_deps=() for dep in gawk rsync socat libdbi-perl pv; do if apt-cache search "^${dep}$" 2>/dev/null | grep -q .; then @@ -2274,33 +3023,34 @@ setup_mariadb() { $STD apt install -y "${mariadb_deps[@]}" 2>/dev/null || true fi - # Use helper function to get fallback suite - local SUITE - SUITE=$(get_fallback_suite "$DISTRO_ID" "$DISTRO_CODENAME" "http://mirror.mariadb.org/repo/${MARIADB_VERSION}/${DISTRO_ID}") - - # Use standardized repo setup - setup_deb822_repo \ - "mariadb" \ - "https://mariadb.org/mariadb_release_signing_key.asc" \ - "http://mirror.mariadb.org/repo/${MARIADB_VERSION}/${DISTRO_ID}" \ - "$SUITE" \ - "main" \ - "amd64 arm64" + # Setup repository + manage_tool_repository "mariadb" "$MARIADB_VERSION" "http://mirror.mariadb.org/repo/$MARIADB_VERSION" \ + "https://mariadb.org/mariadb_release_signing_key.asc" || { + msg_error "Failed to setup MariaDB repository" + return 1 + } + # Set debconf selections for all potential versions local MARIADB_MAJOR_MINOR MARIADB_MAJOR_MINOR=$(echo "$MARIADB_VERSION" | awk -F. '{print $1"."$2}') if [[ -n "$MARIADB_MAJOR_MINOR" ]]; then echo "mariadb-server-$MARIADB_MAJOR_MINOR mariadb-server/feedback boolean false" | debconf-set-selections fi - DEBIAN_FRONTEND=noninteractive $STD apt install -y mariadb-server mariadb-client || { + # Install packages with retry logic + export DEBIAN_FRONTEND=noninteractive + if ! install_packages_with_retry "mariadb-server" "mariadb-client"; then + # Fallback: try without specific version + msg_warn "Failed to install MariaDB packages from upstream repo, trying distro fallback..." cleanup_old_repo_files "mariadb" - $STD apt update - DEBIAN_FRONTEND=noninteractive $STD apt install -y mariadb-server mariadb-client || { - msg_error "Failed to install MariaDB packages" + $STD apt update || { + msg_warn "APT update also failed, continuing with cache" + } + install_packages_with_retry "mariadb-server" "mariadb-client" || { + msg_error "Failed to install MariaDB packages (both upstream and distro)" return 1 } - } + fi cache_installed_version "mariadb" "$MARIADB_VERSION" msg_ok "Setup MariaDB $MARIADB_VERSION" @@ -2335,11 +3085,9 @@ function setup_mongodb() { case "$DISTRO_ID" in ubuntu) MONGO_BASE_URL="https://repo.mongodb.org/apt/ubuntu" - REPO_COMPONENT="multiverse" ;; debian) MONGO_BASE_URL="https://repo.mongodb.org/apt/debian" - REPO_COMPONENT="main" ;; *) msg_error "Unsupported distribution: $DISTRO_ID" @@ -2347,127 +3095,81 @@ function setup_mongodb() { ;; esac + # Get currently installed version local INSTALLED_VERSION="" - if command -v mongod >/dev/null 2>&1; then - INSTALLED_VERSION=$(mongod --version | awk '/db version/{print $3}' | cut -d. -f1,2) - fi + INSTALLED_VERSION=$(is_tool_installed "mongodb" 2>/dev/null) || true - local CACHED_VERSION - CACHED_VERSION=$(get_cached_version "mongodb") + # Scenario 1: Already at target version - just update packages + if [[ -n "$INSTALLED_VERSION" && "$INSTALLED_VERSION" == "$MONGO_VERSION" ]]; then + msg_info "Update MongoDB $MONGO_VERSION" - if [[ "$INSTALLED_VERSION" == "$MONGO_VERSION" ]]; then - if [[ "$CACHED_VERSION" == "$MONGO_VERSION" ]]; then - upgrade_package mongodb-org - else - $STD apt update || { - msg_error "Failed to update package list" - return 1 - } - $STD apt install --only-upgrade -y mongodb-org || { - msg_error "Failed to upgrade MongoDB" - return 1 - } - cache_installed_version "mongodb" "$MONGO_VERSION" - fi + ensure_apt_working || return 1 + + # Perform upgrade with retry logic + upgrade_packages_with_retry "mongodb-org" || { + msg_error "Failed to upgrade MongoDB" + return 1 + } + cache_installed_version "mongodb" "$MONGO_VERSION" + msg_ok "Update MongoDB $MONGO_VERSION" return 0 fi - msg_info "Setup MongoDB $MONGO_VERSION" - - if [[ -n "$INSTALLED_VERSION" ]]; then - $STD systemctl stop mongod 2>/dev/null || true - $STD apt purge -y mongodb-org 2>/dev/null || true + # Scenario 2: Different version installed - clean upgrade + if [[ -n "$INSTALLED_VERSION" && "$INSTALLED_VERSION" != "$MONGO_VERSION" ]]; then + msg_info "Upgrade MongoDB from $INSTALLED_VERSION to $MONGO_VERSION" + remove_old_tool_version "mongodb" + else + msg_info "Setup MongoDB $MONGO_VERSION" fi - cleanup_old_repo_files "mongodb-org-${MONGO_VERSION}" cleanup_orphaned_sources - # Map distro codenames to MongoDB-supported suites - local SUITE - if [[ "$DISTRO_ID" == "debian" ]]; then - case "$DISTRO_CODENAME" in - trixie | forky | sid) - # Debian 13+ and testing/unstable use Bookworm (MongoDB doesn't support newer) - SUITE="bookworm" - ;; - bookworm) - SUITE="bookworm" - ;; - bullseye) - SUITE="bullseye" - ;; - buster) - SUITE="buster" - ;; - *) - # Fallback: try bookworm for unknown Debian releases - msg_warn "Unknown Debian release '${DISTRO_CODENAME}', using bookworm" - SUITE="bookworm" - ;; - esac - elif [[ "$DISTRO_ID" == "ubuntu" ]]; then - case "$DISTRO_CODENAME" in - oracular | plucky) - # Ubuntu 24.10+ uses noble - SUITE="noble" - ;; - noble) - SUITE="noble" - ;; - jammy) - SUITE="jammy" - ;; - focal) - SUITE="focal" - ;; - *) - # Fallback: try noble for unknown Ubuntu releases - msg_warn "Unknown Ubuntu release '${DISTRO_CODENAME}', using noble" - SUITE="noble" - ;; - esac - fi - - # Verify MongoDB repository is available (MongoDB has nested structure) - if ! curl -fsSL --max-time 10 "${MONGO_BASE_URL}/dists/${SUITE}/mongodb-org/${MONGO_VERSION}/Release" &>/dev/null; then - msg_error "MongoDB ${MONGO_VERSION} repository not available for ${DISTRO_ID}-${SUITE}" - msg_error "Please check: ${MONGO_BASE_URL}/dists/${SUITE}/mongodb-org/${MONGO_VERSION}/" - return 1 - fi - - mkdir -p /etc/apt/keyrings - if ! curl -fsSL "https://www.mongodb.org/static/pgp/server-${MONGO_VERSION}.asc" | - gpg --dearmor --yes -o "/etc/apt/keyrings/mongodb-server-${MONGO_VERSION}.gpg"; then - msg_error "Failed to download or import MongoDB GPG key" - return 1 - fi - - cat </etc/apt/sources.list.d/mongodb-org-${MONGO_VERSION}.sources -Types: deb -URIs: ${MONGO_BASE_URL} -Suites: ${SUITE}/mongodb-org/${MONGO_VERSION} -Components: ${REPO_COMPONENT} -Architectures: amd64 arm64 -Signed-By: /etc/apt/keyrings/mongodb-server-${MONGO_VERSION}.gpg -EOF - - $STD apt update || { - msg_error "APT update failed — invalid MongoDB repo for ${DISTRO_ID}-${DISTRO_CODENAME}? (Suite: ${SUITE})" + # Prepare repository (cleanup + validation) + prepare_repository_setup "mongodb" || { + msg_error "Failed to prepare MongoDB repository" return 1 } - $STD apt install -y mongodb-org || { + # Setup repository + manage_tool_repository "mongodb" "$MONGO_VERSION" "$MONGO_BASE_URL" \ + "https://www.mongodb.org/static/pgp/server-${MONGO_VERSION}.asc" || { + msg_error "Failed to setup MongoDB repository" + return 1 + } + + # Wait for repo to settle + $STD apt update || { + msg_error "APT update failed — invalid MongoDB repo for ${DISTRO_ID}-${DISTRO_CODENAME}?" + return 1 + } + + # Install MongoDB with retry logic + install_packages_with_retry "mongodb-org" || { msg_error "Failed to install MongoDB packages" return 1 } + # Verify MongoDB was installed correctly + if ! command -v mongod >/dev/null 2>&1; then + msg_error "MongoDB binary not found after installation" + return 1 + fi + mkdir -p /var/lib/mongodb chown -R mongodb:mongodb /var/lib/mongodb - $STD systemctl enable mongod + $STD systemctl enable mongod || { + msg_warn "Failed to enable mongod service" + } safe_service_restart mongod - cache_installed_version "mongodb" "$MONGO_VERSION" + # Verify MongoDB version + local INSTALLED_VERSION + INSTALLED_VERSION=$(mongod --version 2>/dev/null | grep -oP 'db version v\K[0-9]+\.[0-9]+' | head -n1 || echo "0.0") + verify_tool_version "MongoDB" "$MONGO_VERSION" "$INSTALLED_VERSION" || true + + cache_installed_version "mongodb" "$MONGO_VERSION" msg_ok "Setup MongoDB $MONGO_VERSION" } @@ -2486,59 +3188,52 @@ EOF function setup_mysql() { local MYSQL_VERSION="${MYSQL_VERSION:-8.0}" - local CURRENT_VERSION="" - local NEED_INSTALL=false local DISTRO_ID DISTRO_CODENAME DISTRO_ID=$(awk -F= '/^ID=/{print $2}' /etc/os-release | tr -d '"') DISTRO_CODENAME=$(awk -F= '/^VERSION_CODENAME=/{print $2}' /etc/os-release) - if command -v mysql >/dev/null; then - CURRENT_VERSION="$(mysql --version | grep -oP '[0-9]+\.[0-9]+' | head -n1)" - if [[ "$CURRENT_VERSION" != "$MYSQL_VERSION" ]]; then - NEED_INSTALL=true - else - if apt list --upgradable 2>/dev/null | grep -q '^mysql-server/'; then - $STD apt update || { - msg_error "Failed to update package list" - return 1 - } - $STD apt install --only-upgrade -y mysql-server || { - msg_error "Failed to upgrade MySQL" - return 1 - } - fi - return - fi - else - NEED_INSTALL=true + # Get currently installed version + local CURRENT_VERSION="" + CURRENT_VERSION=$(is_tool_installed "mysql" 2>/dev/null) || true + + # Scenario 1: Already at target version - just update packages + if [[ -n "$CURRENT_VERSION" && "$CURRENT_VERSION" == "$MYSQL_VERSION" ]]; then + msg_info "Update MySQL $MYSQL_VERSION" + + ensure_apt_working || return 1 + + # Perform upgrade with retry logic (non-fatal if fails) + upgrade_packages_with_retry "mysql-server" "mysql-client" || true + + cache_installed_version "mysql" "$MYSQL_VERSION" + msg_ok "Update MySQL $MYSQL_VERSION" + return 0 fi - if [[ "$NEED_INSTALL" == true ]]; then + # Scenario 2: Different version installed - clean upgrade + if [[ -n "$CURRENT_VERSION" && "$CURRENT_VERSION" != "$MYSQL_VERSION" ]]; then + msg_info "Upgrade MySQL from $CURRENT_VERSION to $MYSQL_VERSION" + remove_old_tool_version "mysql" + else msg_info "Setup MySQL $MYSQL_VERSION" + fi - cleanup_old_repo_files "mysql" + # Prepare repository (cleanup + validation) + prepare_repository_setup "mysql" || { + msg_error "Failed to prepare MySQL repository" + return 1 + } - local SUITE - if [[ "$DISTRO_ID" == "debian" ]]; then - case "$DISTRO_CODENAME" in - bookworm | bullseye) SUITE="$DISTRO_CODENAME" ;; - trixie | forky | sid) SUITE="bookworm" ;; - *) SUITE="bookworm" ;; - esac - else - SUITE=$(get_fallback_suite "$DISTRO_ID" "$DISTRO_CODENAME" "https://repo.mysql.com/apt/${DISTRO_ID}") + # Debian 13+ Fix: MySQL 8.0 incompatible with libaio1t64, use 8.4 LTS + if [[ "$DISTRO_ID" == "debian" && "$DISTRO_CODENAME" =~ ^(trixie|forky|sid)$ ]]; then + msg_info "Debian ${DISTRO_CODENAME} detected → using MySQL 8.4 LTS (libaio1t64 compatible)" + + if ! curl -fsSL https://repo.mysql.com/RPM-GPG-KEY-mysql-2023 | gpg --dearmor -o /etc/apt/keyrings/mysql.gpg 2>/dev/null; then + msg_error "Failed to import MySQL GPG key" + return 1 fi - $STD systemctl stop mysql 2>/dev/null || true - if dpkg -l 2>/dev/null | grep -q "^ii.*mysql-server"; then - $STD apt purge -y mysql-server* mysql-client* mysql-common mysql-community-* 2>/dev/null || true - fi - - # --- Debian 13+ Fix: MySQL 8.0 incompatible with libaio1t64 --- - if [[ "$DISTRO_ID" == "debian" && "$DISTRO_CODENAME" =~ ^(trixie|forky|sid)$ ]]; then - msg_info "Debian ${DISTRO_CODENAME} detected → using MySQL 8.4 LTS (libaio1t64)" - curl -fsSL https://repo.mysql.com/RPM-GPG-KEY-mysql-2023 | gpg --dearmor -o /etc/apt/keyrings/mysql.gpg - cat >/etc/apt/sources.list.d/mysql.sources <<'EOF' + cat >/etc/apt/sources.list.d/mysql.sources <<'EOF' Types: deb URIs: https://repo.mysql.com/apt/debian/ Suites: bookworm @@ -2546,56 +3241,81 @@ Components: mysql-8.4-lts Architectures: amd64 arm64 Signed-By: /etc/apt/keyrings/mysql.gpg EOF + + $STD apt update || { + msg_error "Failed to update APT for MySQL 8.4 LTS" + return 1 + } + + # Install with retry logic + if ! install_packages_with_retry "mysql-community-server" "mysql-community-client"; then + msg_warn "MySQL 8.4 LTS installation failed – falling back to MariaDB" + cleanup_old_repo_files "mysql" $STD apt update - if ! $STD apt install -y mysql-community-server mysql-community-client; then - msg_error "MySQL 8.4 LTS installation failed – falling back to MariaDB" - $STD apt install -y mariadb-server mariadb-client - fi - msg_ok "Setup Database Engine (MySQL 8.4 LTS / MariaDB)" - return - fi - # ------------------------------------------------------------- - - setup_deb822_repo \ - "mysql" \ - "https://repo.mysql.com/RPM-GPG-KEY-mysql-2023" \ - "https://repo.mysql.com/apt/${DISTRO_ID}" \ - "$SUITE" \ - "mysql-${MYSQL_VERSION}" \ - "amd64 arm64" - - export DEBIAN_FRONTEND=noninteractive - if ! $STD apt update; then - msg_error "APT update failed for MySQL repository" - return 1 - fi - - local mysql_install_success=false - if apt-cache search "^mysql-server$" 2>/dev/null | grep -q . && $STD apt install -y mysql-server mysql-client 2>/dev/null; then - mysql_install_success=true - fi - if [[ "$mysql_install_success" == false ]] && apt-cache search "^mysql-community-server$" 2>/dev/null | grep -q . && $STD apt install -y mysql-community-server mysql-community-client 2>/dev/null; then - mysql_install_success=true - fi - if [[ "$mysql_install_success" == false ]] && apt-cache search "^mysql$" 2>/dev/null | grep -q . && $STD apt install -y mysql 2>/dev/null; then - mysql_install_success=true - fi - if [[ "$mysql_install_success" == false ]]; then - msg_error "MySQL ${MYSQL_VERSION} package not available for suite ${SUITE}" - return 1 - fi - - if ! command -v mysql >/dev/null 2>&1; then - hash -r - if ! command -v mysql >/dev/null 2>&1; then - msg_error "MySQL installed but mysql command still not found" + install_packages_with_retry "mariadb-server" "mariadb-client" || { + msg_error "Failed to install database engine (MySQL/MariaDB fallback)" return 1 - fi + } + msg_ok "Setup Database Engine (MariaDB fallback on Debian ${DISTRO_CODENAME})" + return 0 fi - cache_installed_version "mysql" "$MYSQL_VERSION" - msg_ok "Setup MySQL $MYSQL_VERSION" + cache_installed_version "mysql" "8.4" + msg_ok "Setup MySQL 8.4 LTS (Debian ${DISTRO_CODENAME})" + return 0 fi + + # Standard setup for other distributions + local SUITE + if [[ "$DISTRO_ID" == "debian" ]]; then + case "$DISTRO_CODENAME" in + bookworm | bullseye) SUITE="$DISTRO_CODENAME" ;; + *) SUITE="bookworm" ;; + esac + else + SUITE=$(get_fallback_suite "$DISTRO_ID" "$DISTRO_CODENAME" "https://repo.mysql.com/apt/${DISTRO_ID}") + fi + + # Setup repository + manage_tool_repository "mysql" "$MYSQL_VERSION" "https://repo.mysql.com/apt/${DISTRO_ID}" \ + "https://repo.mysql.com/RPM-GPG-KEY-mysql-2023" || { + msg_error "Failed to setup MySQL repository" + return 1 + } + + ensure_apt_working || return 1 + + # Try multiple package names with retry logic + export DEBIAN_FRONTEND=noninteractive + local mysql_install_success=false + + if apt-cache search "^mysql-server$" 2>/dev/null | grep -q . && + install_packages_with_retry "mysql-server" "mysql-client"; then + mysql_install_success=true + elif apt-cache search "^mysql-community-server$" 2>/dev/null | grep -q . && + install_packages_with_retry "mysql-community-server" "mysql-community-client"; then + mysql_install_success=true + elif apt-cache search "^mysql$" 2>/dev/null | grep -q . && + install_packages_with_retry "mysql"; then + mysql_install_success=true + fi + + if [[ "$mysql_install_success" == false ]]; then + msg_error "MySQL ${MYSQL_VERSION} package not available for suite ${SUITE}" + return 1 + fi + + # Verify mysql command is accessible + if ! command -v mysql >/dev/null 2>&1; then + hash -r + if ! command -v mysql >/dev/null 2>&1; then + msg_error "MySQL installed but mysql command still not found" + return 1 + fi + fi + + cache_installed_version "mysql" "$MYSQL_VERSION" + msg_ok "Setup MySQL $MYSQL_VERSION" } # ------------------------------------------------------------------------------ @@ -2613,70 +3333,106 @@ EOF function setup_nodejs() { local NODE_VERSION="${NODE_VERSION:-22}" local NODE_MODULE="${NODE_MODULE:-}" + + # ALWAYS clean up legacy installations first (nvm, etc.) to prevent conflicts + cleanup_legacy_install "nodejs" + + # Get currently installed version local CURRENT_NODE_VERSION="" - local NEED_NODE_INSTALL=false - - # Check if Node.js is already installed - if command -v node >/dev/null; then - CURRENT_NODE_VERSION="$(node -v | grep -oP '^v\K[0-9]+')" - if [[ "$CURRENT_NODE_VERSION" != "$NODE_VERSION" ]]; then - msg_info "Old Node.js $CURRENT_NODE_VERSION found, replacing with $NODE_VERSION" - NEED_NODE_INSTALL=true - fi - else - msg_info "Setup Node.js $NODE_VERSION" - NEED_NODE_INSTALL=true - fi + CURRENT_NODE_VERSION=$(is_tool_installed "nodejs" 2>/dev/null) || true + # Ensure jq is available for JSON parsing if ! command -v jq &>/dev/null; then - $STD apt-get update - $STD apt-get install -y jq || { + $STD apt update + $STD apt install -y jq || { msg_error "Failed to install jq" return 1 } fi - # Install Node.js if required - if [[ "$NEED_NODE_INSTALL" == true ]]; then + # Scenario 1: Already installed at target version - just update packages/modules + if [[ -n "$CURRENT_NODE_VERSION" && "$CURRENT_NODE_VERSION" == "$NODE_VERSION" ]]; then + msg_info "Update Node.js $NODE_VERSION" + + ensure_apt_working || return 1 + + # Just update npm to latest + $STD npm install -g npm@latest 2>/dev/null || true + + cache_installed_version "nodejs" "$NODE_VERSION" + msg_ok "Update Node.js $NODE_VERSION" + else + # Scenario 2: Different version installed - clean upgrade + if [[ -n "$CURRENT_NODE_VERSION" && "$CURRENT_NODE_VERSION" != "$NODE_VERSION" ]]; then + msg_info "Upgrade Node.js from $CURRENT_NODE_VERSION to $NODE_VERSION" + remove_old_tool_version "nodejs" + else + msg_info "Setup Node.js $NODE_VERSION" + fi + + # Remove ALL Debian nodejs packages BEFORE adding NodeSource repo + if dpkg -l 2>/dev/null | grep -qE "^ii.*(nodejs|libnode|node-cjs|node-acorn|node-balanced|node-brace|node-minimatch|node-undici|node-xtend|node-corepack)"; then + msg_info "Removing Debian-packaged Node.js and dependencies" + $STD apt purge -y nodejs nodejs-doc libnode* node-* 2>/dev/null || true + $STD apt autoremove -y 2>/dev/null || true + $STD apt clean 2>/dev/null || true + fi + + # Remove any APT pinning (not needed) + rm -f /etc/apt/preferences.d/nodesource 2>/dev/null || true + + # Prepare repository (cleanup + validation) + prepare_repository_setup "nodesource" || { + msg_error "Failed to prepare Node.js repository" + return 1 + } + + # Setup NodeSource repository + manage_tool_repository "nodejs" "$NODE_VERSION" "https://deb.nodesource.com/node_${NODE_VERSION}.x" "https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key" || { + msg_error "Failed to setup Node.js repository" + return 1 + } + + # CRITICAL: Force APT cache refresh AFTER repository setup + # This ensures NodeSource is the only nodejs source in APT cache + $STD apt update + + # Install dependencies (NodeSource is now the only nodejs source) ensure_dependencies curl ca-certificates gnupg - if [[ -n "$CURRENT_NODE_VERSION" ]]; then - $STD apt-get purge -y nodejs npm || true - fi - - cleanup_old_repo_files "nodesource" - - # NodeSource uses deb822 format with "nodistro" - setup_deb822_repo \ - "nodesource" \ - "https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key" \ - "https://deb.nodesource.com/node_${NODE_VERSION}.x" \ - "nodistro" \ - "main" \ - "amd64 arm64" - - sleep 2 - if ! apt-get update >/dev/null 2>&1; then - msg_warn "APT update failed – retrying in 5s" - sleep 5 - if ! apt-get update >/dev/null 2>&1; then - msg_error "Failed to update APT repositories after adding NodeSource" - return 1 - fi - fi - - if ! apt-get install -y nodejs >/dev/null 2>&1; then + # Install Node.js from NodeSource + install_packages_with_retry "nodejs" || { msg_error "Failed to install Node.js ${NODE_VERSION} from NodeSource" return 1 + } + + # Verify Node.js was installed correctly + if ! command -v node >/dev/null 2>&1; then + msg_error "Node.js binary not found after installation" + return 1 fi - # Update to latest npm - $STD npm install -g npm@latest || { - msg_error "Failed to update npm to latest version" - } + local INSTALLED_NODE_VERSION + INSTALLED_NODE_VERSION=$(node -v 2>/dev/null | grep -oP '^v\K[0-9]+' || echo "0") + verify_tool_version "Node.js" "$NODE_VERSION" "$INSTALLED_NODE_VERSION" || true + + # Verify npm is available (should come with NodeSource nodejs) + if ! command -v npm >/dev/null 2>&1; then + msg_error "npm not found after Node.js installation - repository issue?" + return 1 + fi + + # Update to latest npm (with version check to avoid incompatibility) + local NPM_VERSION + NPM_VERSION=$(npm -v 2>/dev/null || echo "0") + if [[ "$NPM_VERSION" != "0" ]]; then + $STD npm install -g npm@latest 2>/dev/null || { + msg_warn "Failed to update npm to latest version (continuing with bundled npm $NPM_VERSION)" + } + fi cache_installed_version "nodejs" "$NODE_VERSION" - msg_ok "Setup Node.js ${NODE_VERSION}" + msg_ok "Setup Node.js $NODE_VERSION" fi export NODE_OPTIONS="--max-old-space-size=4096" @@ -2693,6 +3449,7 @@ function setup_nodejs() { # Install global Node modules if [[ -n "$NODE_MODULE" ]]; then IFS=',' read -ra MODULES <<<"$NODE_MODULE" + local failed_modules=0 for mod in "${MODULES[@]}"; do local MODULE_NAME MODULE_REQ_VERSION MODULE_INSTALLED_VERSION if [[ "$mod" == @*/*@* ]]; then @@ -2710,30 +3467,37 @@ function setup_nodejs() { fi # Check if the module is already installed - if npm list -g --depth=0 "$MODULE_NAME" >/dev/null 2>&1; then - MODULE_INSTALLED_VERSION="$(npm list -g --depth=0 "$MODULE_NAME" | grep "$MODULE_NAME@" | awk -F@ '{print $2}' | tr -d '[:space:]')" + if $STD npm list -g --depth=0 "$MODULE_NAME" 2>&1 | grep -q "$MODULE_NAME@"; then + MODULE_INSTALLED_VERSION="$($STD npm list -g --depth=0 "$MODULE_NAME" 2>&1 | grep "$MODULE_NAME@" | awk -F@ '{print $2}' | tr -d '[:space:]')" if [[ "$MODULE_REQ_VERSION" != "latest" && "$MODULE_REQ_VERSION" != "$MODULE_INSTALLED_VERSION" ]]; then msg_info "Updating $MODULE_NAME from v$MODULE_INSTALLED_VERSION to v$MODULE_REQ_VERSION" - if ! $STD npm install -g "${MODULE_NAME}@${MODULE_REQ_VERSION}"; then - msg_error "Failed to update $MODULE_NAME to version $MODULE_REQ_VERSION" - return 1 + if ! $STD npm install -g "${MODULE_NAME}@${MODULE_REQ_VERSION}" 2>/dev/null; then + msg_warn "Failed to update $MODULE_NAME to version $MODULE_REQ_VERSION" + ((failed_modules++)) + continue fi elif [[ "$MODULE_REQ_VERSION" == "latest" ]]; then msg_info "Updating $MODULE_NAME to latest version" - if ! $STD npm install -g "${MODULE_NAME}@latest"; then - msg_error "Failed to update $MODULE_NAME to latest version" - return 1 + if ! $STD npm install -g "${MODULE_NAME}@latest" 2>/dev/null; then + msg_warn "Failed to update $MODULE_NAME to latest version" + ((failed_modules++)) + continue fi fi else msg_info "Installing $MODULE_NAME@$MODULE_REQ_VERSION" - if ! $STD npm install -g "${MODULE_NAME}@${MODULE_REQ_VERSION}"; then - msg_error "Failed to install $MODULE_NAME@$MODULE_REQ_VERSION" - return 1 + if ! $STD npm install -g "${MODULE_NAME}@${MODULE_REQ_VERSION}" 2>/dev/null; then + msg_warn "Failed to install $MODULE_NAME@$MODULE_REQ_VERSION" + ((failed_modules++)) + continue fi fi done - msg_ok "Installed Node.js modules: $NODE_MODULE" + if [[ $failed_modules -eq 0 ]]; then + msg_ok "Installed Node.js modules: $NODE_MODULE" + else + msg_warn "Installed Node.js modules with $failed_modules failure(s): $NODE_MODULE" + fi fi } @@ -2785,47 +3549,51 @@ function setup_php() { # Get current PHP-CLI version local CURRENT_PHP="" - if command -v php >/dev/null 2>&1; then - CURRENT_PHP=$(php -v 2>/dev/null | awk '/^PHP/{print $2}' | cut -d. -f1,2) - fi + CURRENT_PHP=$(is_tool_installed "php" 2>/dev/null) || true - msg_info "Setup PHP $PHP_VERSION" + # Scenario 1: Already at target version - just update packages + if [[ -n "$CURRENT_PHP" && "$CURRENT_PHP" == "$PHP_VERSION" ]]; then + msg_info "Update PHP $PHP_VERSION" - if [[ -n "$CURRENT_PHP" && "$CURRENT_PHP" != "$PHP_VERSION" ]]; then - $STD apt purge -y "php${CURRENT_PHP//./}"* || true - fi + # Ensure Sury repo is available + if [[ ! -f /etc/apt/sources.list.d/php.sources ]]; then + manage_tool_repository "php" "$PHP_VERSION" "" "https://packages.sury.org/debsuryorg-archive-keyring.deb" || { + msg_error "Failed to setup PHP repository" + return 1 + } + fi - # Ensure Sury repo is available - if [[ ! -f /etc/apt/sources.list.d/php.sources ]]; then - # Cleanup old repository files - cleanup_old_repo_files "php" + ensure_apt_working || return 1 - $STD curl -fsSLo /tmp/debsuryorg-archive-keyring.deb https://packages.sury.org/debsuryorg-archive-keyring.deb || { - msg_error "Failed to download PHP repository keyring" - return 1 - } - $STD dpkg -i /tmp/debsuryorg-archive-keyring.deb || { - msg_error "Failed to install PHP repository keyring" - rm -f /tmp/debsuryorg-archive-keyring.deb + # Perform upgrade with retry logic (non-fatal if fails) + upgrade_packages_with_retry "php${PHP_VERSION}" || true + + cache_installed_version "php" "$PHP_VERSION" + msg_ok "Update PHP $PHP_VERSION" + else + # Scenario 2: Different version installed - clean upgrade + if [[ -n "$CURRENT_PHP" && "$CURRENT_PHP" != "$PHP_VERSION" ]]; then + msg_info "Upgrade PHP from $CURRENT_PHP to $PHP_VERSION" + # Stop and disable ALL PHP-FPM versions + stop_all_services "php.*-fpm" + remove_old_tool_version "php" + else + msg_info "Setup PHP $PHP_VERSION" + fi + + # Prepare repository (cleanup + validation) + prepare_repository_setup "php" "deb.sury.org-php" || { + msg_error "Failed to prepare PHP repository" return 1 } - # Use helper function to get fallback suite - local SUITE - SUITE=$(get_fallback_suite "$DISTRO_ID" "$DISTRO_CODENAME" "https://packages.sury.org/php") - - cat </etc/apt/sources.list.d/php.sources -Types: deb -URIs: https://packages.sury.org/php/ -Suites: $SUITE -Components: main -Architectures: amd64 arm64 -Signed-By: /usr/share/keyrings/deb.sury.org-php.gpg -EOF - $STD apt update || { - msg_error "APT update failed for PHP repository" + # Setup Sury repository + manage_tool_repository "php" "$PHP_VERSION" "" "https://packages.sury.org/debsuryorg-archive-keyring.deb" || { + msg_error "Failed to setup PHP repository" return 1 } + + ensure_apt_working || return 1 fi # Build module list @@ -2842,28 +3610,22 @@ EOF # install apache2 with PHP support if requested if [[ "$PHP_APACHE" == "YES" ]]; then - if ! dpkg -l | grep -q "libapache2-mod-php${PHP_VERSION}"; then - $STD apt install -y apache2 libapache2-mod-php${PHP_VERSION} || { + if ! dpkg -l 2>/dev/null | grep -q "libapache2-mod-php${PHP_VERSION}"; then + install_packages_with_retry "apache2" "libapache2-mod-php${PHP_VERSION}" || { msg_error "Failed to install Apache with PHP module" return 1 } fi fi - # setup / update PHP modules - $STD apt install -y $MODULE_LIST || { + # Install PHP packages with retry logic + install_packages_with_retry $MODULE_LIST || { msg_error "Failed to install PHP packages" return 1 } cache_installed_version "php" "$PHP_VERSION" - # optional stop old PHP-FPM service - if [[ "$PHP_FPM" == "YES" && -n "$CURRENT_PHP" && "$CURRENT_PHP" != "$PHP_VERSION" ]]; then - $STD systemctl stop php"${CURRENT_PHP}"-fpm || true - $STD systemctl disable php"${CURRENT_PHP}"-fpm || true - fi - - # Patch all relevant php.ini files (silent) + # Patch all relevant php.ini files local PHP_INI_PATHS=("/etc/php/${PHP_VERSION}/cli/php.ini") [[ "$PHP_FPM" == "YES" ]] && PHP_INI_PATHS+=("/etc/php/${PHP_VERSION}/fpm/php.ini") [[ "$PHP_APACHE" == "YES" ]] && PHP_INI_PATHS+=("/etc/php/${PHP_VERSION}/apache2/php.ini") @@ -2876,7 +3638,7 @@ EOF fi done - # patch Apache configuration if needed + # Patch Apache configuration if needed if [[ "$PHP_APACHE" == "YES" ]]; then for mod in $(ls /etc/apache2/mods-enabled/ 2>/dev/null | grep -E '^php[0-9]\.[0-9]\.conf$' | sed 's/\.conf//'); do if [[ "$mod" != "php${PHP_VERSION}" ]]; then @@ -2888,7 +3650,7 @@ EOF safe_service_restart apache2 || true fi - # enable and restart PHP-FPM if requested + # Enable and restart PHP-FPM if requested if [[ "$PHP_FPM" == "YES" ]]; then if systemctl list-unit-files | grep -q "php${PHP_VERSION}-fpm.service"; then $STD systemctl enable php${PHP_VERSION}-fpm @@ -2911,120 +3673,141 @@ EOF # # Variables: # PG_VERSION - Major PostgreSQL version (e.g. 15, 16) (default: 16) -# PG_MODULES - Comma-separated list of extensions (e.g. "postgis,contrib") -# ------------------------------------------------------------------------------ function setup_postgresql() { local PG_VERSION="${PG_VERSION:-16}" local PG_MODULES="${PG_MODULES:-}" - local CURRENT_PG_VERSION="" local DISTRO_ID DISTRO_CODENAME - local NEED_PG_INSTALL=false DISTRO_ID=$(awk -F= '/^ID=/{print $2}' /etc/os-release | tr -d '"') DISTRO_CODENAME=$(awk -F= '/^VERSION_CODENAME=/{print $2}' /etc/os-release) + # Get currently installed version + local CURRENT_PG_VERSION="" if command -v psql >/dev/null; then - CURRENT_PG_VERSION="$(psql -V | awk '{print $3}' | cut -d. -f1)" - [[ "$CURRENT_PG_VERSION" != "$PG_VERSION" ]] && NEED_PG_INSTALL=true - else - NEED_PG_INSTALL=true + CURRENT_PG_VERSION="$(psql -V 2>/dev/null | awk '{print $3}' | cut -d. -f1)" fi - if [[ "$NEED_PG_INSTALL" == true ]]; then - msg_info "Setup PostgreSQL $PG_VERSION" - - if [[ -n "$CURRENT_PG_VERSION" ]]; then - $STD runuser -u postgres -- pg_dumpall >/var/lib/postgresql/backup_$(date +%F)_v${CURRENT_PG_VERSION}.sql - $STD systemctl stop postgresql - fi - - # Cleanup old repository files - cleanup_old_repo_files "pgdg" - - # PostgreSQL PGDG repository uses special suite naming - # For unstable/testing Debian, we need to check what's actually available - local SUITE - case "$DISTRO_CODENAME" in - trixie | forky | sid) - # Try trixie-pgdg first, fallback to bookworm-pgdg if not available - if verify_repo_available "https://apt.postgresql.org/pub/repos/apt" "trixie-pgdg"; then - SUITE="trixie-pgdg" - else - SUITE="bookworm-pgdg" - fi - ;; - *) - # Use helper function for stable releases - SUITE=$(get_fallback_suite "$DISTRO_ID" "$DISTRO_CODENAME" "https://apt.postgresql.org/pub/repos/apt") - # PGDG uses special suite naming: ${SUITE}-pgdg - SUITE="${SUITE}-pgdg" - ;; - esac - - # Use standardized repo setup - setup_deb822_repo \ - "pgdg" \ - "https://www.postgresql.org/media/keys/ACCC4CF8.asc" \ - "https://apt.postgresql.org/pub/repos/apt" \ - "$SUITE" \ - "main" \ - "amd64 arm64" - - # Update apt - if ! $STD apt update; then - msg_error "APT update failed for PostgreSQL repository" - return 1 - fi - - # Try multiple PostgreSQL package patterns - local pg_install_success=false - - # First, ensure ssl-cert is available (PostgreSQL dependency) - if apt-cache search "^ssl-cert$" 2>/dev/null | grep -q .; then - $STD apt install -y ssl-cert 2>/dev/null || true - fi - - # First try: postgresql-X (common in most repos) - if apt-cache search "^postgresql-${PG_VERSION}$" 2>/dev/null | grep -q . && $STD apt install -y "postgresql-${PG_VERSION}" "postgresql-client-${PG_VERSION}" 2>/dev/null; then - pg_install_success=true - fi - - # Second try: postgresql-server-X (some repos use this) - if [[ "$pg_install_success" == false ]] && apt-cache search "^postgresql-server-${PG_VERSION}$" 2>/dev/null | grep -q . && $STD apt install -y "postgresql-server-${PG_VERSION}" "postgresql-client-${PG_VERSION}" 2>/dev/null; then - pg_install_success=true - fi - - # Third try: just postgresql (any version) - if [[ "$pg_install_success" == false ]] && apt-cache search "^postgresql$" 2>/dev/null | grep -q . && $STD apt install -y postgresql postgresql-client 2>/dev/null; then - pg_install_success=true - fi - - if [[ "$pg_install_success" == false ]]; then - msg_error "PostgreSQL package not available for suite ${SUITE}" - return 1 - fi - - # Verify installation - if ! command -v psql >/dev/null 2>&1; then - msg_error "PostgreSQL installed but psql command not found" - return 1 - fi - - if [[ -n "$CURRENT_PG_VERSION" ]]; then - $STD apt purge -y "postgresql-${CURRENT_PG_VERSION}" "postgresql-client-${CURRENT_PG_VERSION}" 2>/dev/null || true - $STD runuser -u postgres -- psql /dev/null || true - fi - - $STD systemctl enable --now postgresql 2>/dev/null || true - - # Add PostgreSQL binaries to PATH for the install script - if ! grep -q '/usr/lib/postgresql' /etc/environment 2>/dev/null; then - echo 'PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/lib/postgresql/'"${PG_VERSION}"'/bin"' >/etc/environment - fi + # Scenario 1: Already at correct version + if [[ "$CURRENT_PG_VERSION" == "$PG_VERSION" ]]; then + msg_info "Update PostgreSQL $PG_VERSION" + ensure_apt_working || return 1 + # Perform upgrade with retry logic (non-fatal if fails) + upgrade_packages_with_retry "postgresql-${PG_VERSION}" "postgresql-client-${PG_VERSION}" 2>/dev/null || true cache_installed_version "postgresql" "$PG_VERSION" - msg_ok "Setup PostgreSQL $PG_VERSION" + msg_ok "Update PostgreSQL $PG_VERSION" + + # Still install modules if specified + if [[ -n "$PG_MODULES" ]]; then + IFS=',' read -ra MODULES <<<"$PG_MODULES" + for module in "${MODULES[@]}"; do + $STD apt install -y "postgresql-${PG_VERSION}-${module}" 2>/dev/null || true + done + fi + return 0 fi + # Scenario 2: Different version - backup, remove old, install new + if [[ -n "$CURRENT_PG_VERSION" ]]; then + msg_info "Upgrade PostgreSQL from $CURRENT_PG_VERSION to $PG_VERSION" + msg_info "Creating backup of PostgreSQL $CURRENT_PG_VERSION databases..." + $STD runuser -u postgres -- pg_dumpall >/var/lib/postgresql/backup_$(date +%F)_v${CURRENT_PG_VERSION}.sql || { + msg_error "Failed to backup PostgreSQL databases" + return 1 + } + $STD systemctl stop postgresql || true + $STD apt purge -y "postgresql-${CURRENT_PG_VERSION}" "postgresql-client-${CURRENT_PG_VERSION}" 2>/dev/null || true + else + msg_info "Setup PostgreSQL $PG_VERSION" + fi + + # Scenario 3: Fresh install or after removal - setup repo and install + prepare_repository_setup "pgdg" "postgresql" || { + msg_error "Failed to prepare PostgreSQL repository" + return 1 + } + + local SUITE + case "$DISTRO_CODENAME" in + trixie | forky | sid) + if verify_repo_available "https://apt.postgresql.org/pub/repos/apt" "trixie-pgdg"; then + SUITE="trixie-pgdg" + else + SUITE="bookworm-pgdg" + fi + ;; + *) + SUITE=$(get_fallback_suite "$DISTRO_ID" "$DISTRO_CODENAME" "https://apt.postgresql.org/pub/repos/apt") + SUITE="${SUITE}-pgdg" + ;; + esac + + setup_deb822_repo \ + "pgdg" \ + "https://www.postgresql.org/media/keys/ACCC4CF8.asc" \ + "https://apt.postgresql.org/pub/repos/apt" \ + "$SUITE" \ + "main" \ + "amd64 arm64" + + if ! $STD apt update; then + msg_error "APT update failed for PostgreSQL repository" + return 1 + fi + + # Install ssl-cert dependency if available + if apt-cache search "^ssl-cert$" 2>/dev/null | grep -q .; then + $STD apt install -y ssl-cert 2>/dev/null || true + fi + + # Try multiple PostgreSQL package patterns with retry logic + local pg_install_success=false + + if apt-cache search "^postgresql-${PG_VERSION}$" 2>/dev/null | grep -q . && + install_packages_with_retry "postgresql-${PG_VERSION}" "postgresql-client-${PG_VERSION}"; then + pg_install_success=true + fi + + if [[ "$pg_install_success" == false ]] && + apt-cache search "^postgresql-server-${PG_VERSION}$" 2>/dev/null | grep -q . && + $STD apt install -y "postgresql-server-${PG_VERSION}" "postgresql-client-${PG_VERSION}" 2>/dev/null; then + pg_install_success=true + fi + + if [[ "$pg_install_success" == false ]] && + apt-cache search "^postgresql$" 2>/dev/null | grep -q . && + $STD apt install -y postgresql postgresql-client 2>/dev/null; then + pg_install_success=true + fi + + if [[ "$pg_install_success" == false ]]; then + msg_error "PostgreSQL package not available for suite ${SUITE}" + return 1 + fi + + if ! command -v psql >/dev/null 2>&1; then + msg_error "PostgreSQL installed but psql command not found" + return 1 + fi + + # Restore database backup if we upgraded from previous version + if [[ -n "$CURRENT_PG_VERSION" ]]; then + msg_info "Restoring PostgreSQL databases from backup..." + $STD runuser -u postgres -- psql /dev/null || { + msg_warn "Failed to restore database backup - this may be expected for major version upgrades" + } + fi + + $STD systemctl enable --now postgresql 2>/dev/null || true + + # Add PostgreSQL binaries to PATH + if ! grep -q '/usr/lib/postgresql' /etc/environment 2>/dev/null; then + echo 'PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/lib/postgresql/'"${PG_VERSION}"'/bin"' >/etc/environment + fi + + cache_installed_version "postgresql" "$PG_VERSION" + msg_ok "Setup PostgreSQL $PG_VERSION" + + # Install optional modules if [[ -n "$PG_MODULES" ]]; then IFS=',' read -ra MODULES <<<"$PG_MODULES" for module in "${MODULES[@]}"; do @@ -3053,16 +3836,31 @@ function setup_ruby() { local RBENV_BIN="$RBENV_DIR/bin/rbenv" local PROFILE_FILE="$HOME/.profile" local TMP_DIR=$(mktemp -d) - local CACHED_VERSION - CACHED_VERSION=$(get_cached_version "ruby") - msg_info "Setup Ruby $RUBY_VERSION" + # Get currently installed Ruby version + local CURRENT_RUBY_VERSION="" + if [[ -x "$RBENV_BIN" ]]; then + CURRENT_RUBY_VERSION=$("$RBENV_BIN" global 2>/dev/null || echo "") + fi + + # Scenario 1: Already at correct Ruby version + if [[ "$CURRENT_RUBY_VERSION" == "$RUBY_VERSION" ]]; then + msg_info "Update Ruby $RUBY_VERSION" + cache_installed_version "ruby" "$RUBY_VERSION" + msg_ok "Update Ruby $RUBY_VERSION" + return 0 + fi + + # Scenario 2: Different version - reinstall + if [[ -n "$CURRENT_RUBY_VERSION" ]]; then + msg_info "Upgrade Ruby from $CURRENT_RUBY_VERSION to $RUBY_VERSION" + else + msg_info "Setup Ruby $RUBY_VERSION" + fi - # Ensure APT is working before installing dependencies ensure_apt_working || return 1 - # Install build dependencies - with fallback for different Debian versions - # In Trixie: libreadline6-dev -> libreadline-dev, libncurses5-dev -> libncurses-dev + # Install build dependencies with fallbacks local ruby_deps=() local dep_variations=( "jq" @@ -3083,13 +3881,10 @@ function setup_ruby() { for dep_pattern in "${dep_variations[@]}"; do if [[ "$dep_pattern" == *"|"* ]]; then - # Try multiple variations IFS='|' read -ra variations <<<"$dep_pattern" - local found=false for var in "${variations[@]}"; do if apt-cache search "^${var}$" 2>/dev/null | grep -q .; then ruby_deps+=("$var") - found=true break fi done @@ -3104,70 +3899,98 @@ function setup_ruby() { $STD apt install -y "${ruby_deps[@]}" 2>/dev/null || true else msg_error "No Ruby build dependencies available" - return 1 - fi - - local RBENV_RELEASE - RBENV_RELEASE=$(curl -fsSL https://api.github.com/repos/rbenv/rbenv/releases/latest | jq -r '.tag_name' | sed 's/^v//') - if [[ -z "$RBENV_RELEASE" ]]; then - msg_error "Failed to fetch latest rbenv version" rm -rf "$TMP_DIR" return 1 fi - curl -fsSL "https://github.com/rbenv/rbenv/archive/refs/tags/v${RBENV_RELEASE}.tar.gz" -o "$TMP_DIR/rbenv.tar.gz" || { - msg_error "Failed to download rbenv" - rm -rf "$TMP_DIR" - return 1 - } + # Download and build rbenv if needed + if [[ ! -x "$RBENV_BIN" ]]; then + local RBENV_RELEASE + local rbenv_json + rbenv_json=$(curl -fsSL --max-time 15 https://api.github.com/repos/rbenv/rbenv/releases/latest 2>/dev/null || echo "") - tar -xzf "$TMP_DIR/rbenv.tar.gz" -C "$TMP_DIR" || { - msg_error "Failed to extract rbenv" - rm -rf "$TMP_DIR" - return 1 - } + if [[ -z "$rbenv_json" ]]; then + msg_error "Failed to fetch latest rbenv version from GitHub" + rm -rf "$TMP_DIR" + return 1 + fi - mkdir -p "$RBENV_DIR" - cp -r "$TMP_DIR/rbenv-${RBENV_RELEASE}/." "$RBENV_DIR/" - cd "$RBENV_DIR" && src/configure && $STD make -C src || { - msg_error "Failed to build rbenv" - rm -rf "$TMP_DIR" - return 1 - } + RBENV_RELEASE=$(echo "$rbenv_json" | jq -r '.tag_name' 2>/dev/null | sed 's/^v//' || echo "") - local RUBY_BUILD_RELEASE - RUBY_BUILD_RELEASE=$(curl -fsSL https://api.github.com/repos/rbenv/ruby-build/releases/latest | jq -r '.tag_name' | sed 's/^v//') - if [[ -z "$RUBY_BUILD_RELEASE" ]]; then - msg_error "Failed to fetch latest ruby-build version" - rm -rf "$TMP_DIR" - return 1 + if [[ -z "$RBENV_RELEASE" ]]; then + msg_error "Could not parse rbenv version from GitHub response" + rm -rf "$TMP_DIR" + return 1 + fi + + curl -fsSL "https://github.com/rbenv/rbenv/archive/refs/tags/v${RBENV_RELEASE}.tar.gz" -o "$TMP_DIR/rbenv.tar.gz" || { + msg_error "Failed to download rbenv" + rm -rf "$TMP_DIR" + return 1 + } + + tar -xzf "$TMP_DIR/rbenv.tar.gz" -C "$TMP_DIR" || { + msg_error "Failed to extract rbenv" + rm -rf "$TMP_DIR" + return 1 + } + + mkdir -p "$RBENV_DIR" + cp -r "$TMP_DIR/rbenv-${RBENV_RELEASE}/." "$RBENV_DIR/" + (cd "$RBENV_DIR" && src/configure && $STD make -C src) || { + msg_error "Failed to build rbenv" + rm -rf "$TMP_DIR" + return 1 + } + + # Setup profile + if ! grep -q 'rbenv init' "$PROFILE_FILE" 2>/dev/null; then + echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >>"$PROFILE_FILE" + echo 'eval "$(rbenv init -)"' >>"$PROFILE_FILE" + fi fi - curl -fsSL "https://github.com/rbenv/ruby-build/archive/refs/tags/v${RUBY_BUILD_RELEASE}.tar.gz" -o "$TMP_DIR/ruby-build.tar.gz" || { - msg_error "Failed to download ruby-build" - rm -rf "$TMP_DIR" - return 1 - } + # Install ruby-build plugin + if [[ ! -d "$RBENV_DIR/plugins/ruby-build" ]]; then + local RUBY_BUILD_RELEASE + local ruby_build_json + ruby_build_json=$(curl -fsSL --max-time 15 https://api.github.com/repos/rbenv/ruby-build/releases/latest 2>/dev/null || echo "") - tar -xzf "$TMP_DIR/ruby-build.tar.gz" -C "$TMP_DIR" || { - msg_error "Failed to extract ruby-build" - rm -rf "$TMP_DIR" - return 1 - } + if [[ -z "$ruby_build_json" ]]; then + msg_error "Failed to fetch latest ruby-build version from GitHub" + rm -rf "$TMP_DIR" + return 1 + fi - mkdir -p "$RBENV_DIR/plugins/ruby-build" - cp -r "$TMP_DIR/ruby-build-${RUBY_BUILD_RELEASE}/." "$RBENV_DIR/plugins/ruby-build/" - echo "$RUBY_BUILD_RELEASE" >"$RBENV_DIR/plugins/ruby-build/RUBY_BUILD_version.txt" + RUBY_BUILD_RELEASE=$(echo "$ruby_build_json" | jq -r '.tag_name' 2>/dev/null | sed 's/^v//' || echo "") - if ! grep -q 'rbenv init' "$PROFILE_FILE"; then - echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >>"$PROFILE_FILE" - echo 'eval "$(rbenv init -)"' >>"$PROFILE_FILE" + if [[ -z "$RUBY_BUILD_RELEASE" ]]; then + msg_error "Could not parse ruby-build version from GitHub response" + rm -rf "$TMP_DIR" + return 1 + fi + + curl -fsSL "https://github.com/rbenv/ruby-build/archive/refs/tags/v${RUBY_BUILD_RELEASE}.tar.gz" -o "$TMP_DIR/ruby-build.tar.gz" || { + msg_error "Failed to download ruby-build" + rm -rf "$TMP_DIR" + return 1 + } + + tar -xzf "$TMP_DIR/ruby-build.tar.gz" -C "$TMP_DIR" || { + msg_error "Failed to extract ruby-build" + rm -rf "$TMP_DIR" + return 1 + } + + mkdir -p "$RBENV_DIR/plugins/ruby-build" + cp -r "$TMP_DIR/ruby-build-${RUBY_BUILD_RELEASE}/." "$RBENV_DIR/plugins/ruby-build/" fi + # Setup PATH and install Ruby version export PATH="$RBENV_DIR/bin:$PATH" - eval "$("$RBENV_BIN" init - bash)" + eval "$("$RBENV_BIN" init - bash)" 2>/dev/null || true - if ! "$RBENV_BIN" versions --bare | grep -qx "$RUBY_VERSION"; then + if ! "$RBENV_BIN" versions --bare 2>/dev/null | grep -qx "$RUBY_VERSION"; then $STD "$RBENV_BIN" install "$RUBY_VERSION" || { msg_error "Failed to install Ruby $RUBY_VERSION" rm -rf "$TMP_DIR" @@ -3175,14 +3998,18 @@ function setup_ruby() { } fi - "$RBENV_BIN" global "$RUBY_VERSION" + "$RBENV_BIN" global "$RUBY_VERSION" || { + msg_error "Failed to set Ruby $RUBY_VERSION as global version" + rm -rf "$TMP_DIR" + return 1 + } + hash -r + # Install Rails if requested if [[ "$RUBY_INSTALL_RAILS" == "true" ]]; then $STD gem install rails || { - msg_error "Failed to install Rails" - rm -rf "$TMP_DIR" - return 1 + msg_warn "Failed to install Rails - Ruby installation successful" } fi @@ -3210,100 +4037,79 @@ function setup_clickhouse() { DISTRO_ID=$(awk -F= '/^ID=/{print $2}' /etc/os-release | tr -d '"') DISTRO_CODENAME=$(awk -F= '/^VERSION_CODENAME=/{print $2}' /etc/os-release) - # Determine latest version if needed + # Resolve "latest" version if [[ "$CLICKHOUSE_VERSION" == "latest" ]]; then - # Try multiple methods to get the latest version - CLICKHOUSE_VERSION=$(curl -fsSL https://packages.clickhouse.com/tgz/stable/ 2>/dev/null | + CLICKHOUSE_VERSION=$(curl -fsSL --max-time 15 https://packages.clickhouse.com/tgz/stable/ 2>/dev/null | grep -oP 'clickhouse-common-static-\K[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' | - sort -V | - tail -n1) + sort -V | tail -n1 || echo "") - # Fallback: Try GitHub releases API + # Fallback to GitHub API if package server failed if [[ -z "$CLICKHOUSE_VERSION" ]]; then - CLICKHOUSE_VERSION=$(curl -fsSL https://api.github.com/repos/ClickHouse/ClickHouse/releases/latest 2>/dev/null | - grep -oP '"tag_name":\s*"v\K[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' | - head -n1) + CLICKHOUSE_VERSION=$(curl -fsSL --max-time 15 https://api.github.com/repos/ClickHouse/ClickHouse/releases/latest 2>/dev/null | + grep -oP '"tag_name":\s*"v\K[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' | head -n1 || echo "") fi - # Final fallback: Parse HTML more liberally - if [[ -z "$CLICKHOUSE_VERSION" ]]; then - CLICKHOUSE_VERSION=$(curl -fsSL https://packages.clickhouse.com/tgz/stable/ 2>/dev/null | - grep -oP '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+(?=/clickhouse)' | - sort -V | - tail -n1) - fi - - if [[ -z "$CLICKHOUSE_VERSION" ]]; then - msg_error "Could not determine latest ClickHouse version" + [[ -z "$CLICKHOUSE_VERSION" ]] && { + msg_error "Could not determine latest ClickHouse version from any source" return 1 - fi + } fi + # Get currently installed version local CURRENT_VERSION="" if command -v clickhouse-server >/dev/null 2>&1; then CURRENT_VERSION=$(clickhouse-server --version 2>/dev/null | grep -oP 'version \K[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' | head -n1) fi - local CACHED_VERSION - CACHED_VERSION=$(get_cached_version "clickhouse") + # Scenario 1: Already at target version - just update packages + if [[ -n "$CURRENT_VERSION" && "$CURRENT_VERSION" == "$CLICKHOUSE_VERSION" ]]; then + msg_info "Update ClickHouse $CLICKHOUSE_VERSION" + ensure_apt_working || return 1 - # Check if already at target version - if [[ "$CURRENT_VERSION" == "$CLICKHOUSE_VERSION" ]]; then - if [[ "$CACHED_VERSION" == "$CLICKHOUSE_VERSION" ]]; then - upgrade_package clickhouse-server - upgrade_package clickhouse-client - else - msg_info "Setup ClickHouse $CLICKHOUSE_VERSION" - $STD apt update || { - msg_error "Failed to update package list" - return 1 - } - $STD apt install --only-upgrade -y clickhouse-server clickhouse-client || { - msg_error "Failed to upgrade ClickHouse" - return 1 - } - cache_installed_version "clickhouse" "$CLICKHOUSE_VERSION" - msg_ok "Setup ClickHouse $CLICKHOUSE_VERSION" - fi + # Perform upgrade with retry logic (non-fatal if fails) + upgrade_packages_with_retry "clickhouse-server" "clickhouse-client" || true + cache_installed_version "clickhouse" "$CLICKHOUSE_VERSION" + msg_ok "Update ClickHouse $CLICKHOUSE_VERSION" return 0 fi - msg_info "Setup ClickHouse $CLICKHOUSE_VERSION" - - # Stop existing service if upgrading - if [[ -n "$CURRENT_VERSION" ]]; then - $STD systemctl stop clickhouse-server || true + # Scenario 2: Different version - clean upgrade + if [[ -n "$CURRENT_VERSION" && "$CURRENT_VERSION" != "$CLICKHOUSE_VERSION" ]]; then + msg_info "Upgrade ClickHouse from $CURRENT_VERSION to $CLICKHOUSE_VERSION" + stop_all_services "clickhouse-server" + remove_old_tool_version "clickhouse" + else + msg_info "Setup ClickHouse $CLICKHOUSE_VERSION" fi - # Cleanup old repository files - cleanup_old_repo_files "clickhouse" - - # Ensure dependencies ensure_dependencies apt-transport-https ca-certificates dirmngr gnupg - # ClickHouse uses 'stable' instead of distro codenames - local SUITE="stable" + # Prepare repository (cleanup + validation) + prepare_repository_setup "clickhouse" || { + msg_error "Failed to prepare ClickHouse repository" + return 1 + } - # Use standardized repo setup + # Setup repository (ClickHouse uses 'stable' suite) setup_deb822_repo \ "clickhouse" \ "https://packages.clickhouse.com/rpm/lts/repodata/repomd.xml.key" \ "https://packages.clickhouse.com/deb" \ - "$SUITE" \ + "stable" \ "main" \ "amd64 arm64" - # Update and install ClickHouse packages + # Install packages with retry logic export DEBIAN_FRONTEND=noninteractive - if ! $STD apt update; then + $STD apt update || { msg_error "APT update failed for ClickHouse repository" return 1 - fi + } - if ! $STD apt install -y clickhouse-server clickhouse-client; then + install_packages_with_retry "clickhouse-server" "clickhouse-client" || { msg_error "Failed to install ClickHouse packages" return 1 - fi + } # Verify installation if ! command -v clickhouse-server >/dev/null 2>&1; then @@ -3311,16 +4117,16 @@ function setup_clickhouse() { return 1 fi - # Create data directory if it doesn't exist + # Setup data directory mkdir -p /var/lib/clickhouse - - # Check if clickhouse user exists before chown if id clickhouse >/dev/null 2>&1; then chown -R clickhouse:clickhouse /var/lib/clickhouse fi # Enable and start service - $STD systemctl enable clickhouse-server + $STD systemctl enable clickhouse-server || { + msg_warn "Failed to enable clickhouse-server service" + } safe_service_restart clickhouse-server || true cache_installed_version "clickhouse" "$CLICKHOUSE_VERSION" @@ -3348,11 +4154,16 @@ function setup_rust() { local RUST_TOOLCHAIN="${RUST_TOOLCHAIN:-stable}" local RUST_CRATES="${RUST_CRATES:-}" local CARGO_BIN="${HOME}/.cargo/bin" - local CACHED_VERSION - CACHED_VERSION=$(get_cached_version "rust") + # Get currently installed version + local CURRENT_VERSION="" + if command -v rustc &>/dev/null; then + CURRENT_VERSION=$(rustc --version 2>/dev/null | awk '{print $2}') + fi + + # Scenario 1: Rustup not installed - fresh install if ! command -v rustup &>/dev/null; then - msg_info "Setup Rust" + msg_info "Setup Rust ($RUST_TOOLCHAIN)" curl -fsSL https://sh.rustup.rs | $STD sh -s -- -y --default-toolchain "$RUST_TOOLCHAIN" || { msg_error "Failed to install Rust" return 1 @@ -3363,21 +4174,23 @@ function setup_rust() { cache_installed_version "rust" "$RUST_VERSION" msg_ok "Setup Rust $RUST_VERSION" else - msg_info "Setup Rust" + # Scenario 2: Rustup already installed - update/maintain + msg_info "Update Rust ($RUST_TOOLCHAIN)" $STD rustup install "$RUST_TOOLCHAIN" || { - msg_error "Failed to install Rust toolchain" + msg_error "Failed to install Rust toolchain $RUST_TOOLCHAIN" return 1 } $STD rustup default "$RUST_TOOLCHAIN" || { msg_error "Failed to set default Rust toolchain" return 1 } - $STD rustup update "$RUST_TOOLCHAIN" + $STD rustup update "$RUST_TOOLCHAIN" || true local RUST_VERSION=$(rustc --version 2>/dev/null | awk '{print $2}') cache_installed_version "rust" "$RUST_VERSION" - msg_ok "Setup Rust $RUST_VERSION" + msg_ok "Update Rust $RUST_VERSION" fi + # Install global crates if [[ -n "$RUST_CRATES" ]]; then IFS=',' read -ra CRATES <<<"$RUST_CRATES" for crate in "${CRATES[@]}"; do @@ -3415,108 +4228,158 @@ function setup_rust() { function setup_uv() { local UV_BIN="/usr/local/bin/uv" + local UVX_BIN="/usr/local/bin/uvx" local TMP_DIR=$(mktemp -d) local CACHED_VERSION + + # trap for TMP Cleanup + trap "rm -rf '$TMP_DIR'" EXIT + CACHED_VERSION=$(get_cached_version "uv") + # Architecture Detection local ARCH=$(uname -m) - local UV_TAR + local OS_TYPE="" + local UV_TAR="" + + if grep -qi "alpine" /etc/os-release; then + OS_TYPE="musl" + else + OS_TYPE="gnu" + fi case "$ARCH" in x86_64) - if grep -qi "alpine" /etc/os-release; then - UV_TAR="uv-x86_64-unknown-linux-musl.tar.gz" - else - UV_TAR="uv-x86_64-unknown-linux-gnu.tar.gz" - fi + UV_TAR="uv-x86_64-unknown-linux-${OS_TYPE}.tar.gz" ;; aarch64) - if grep -qi "alpine" /etc/os-release; then - UV_TAR="uv-aarch64-unknown-linux-musl.tar.gz" - else - UV_TAR="uv-aarch64-unknown-linux-gnu.tar.gz" - fi + UV_TAR="uv-aarch64-unknown-linux-${OS_TYPE}.tar.gz" + ;; + i686) + UV_TAR="uv-i686-unknown-linux-${OS_TYPE}.tar.gz" ;; *) - msg_error "Unsupported architecture: $ARCH" - rm -rf "$TMP_DIR" + msg_error "Unsupported architecture: $ARCH (supported: x86_64, aarch64, i686)" return 1 ;; esac ensure_dependencies jq + # Fetch latest version + local releases_json + releases_json=$(curl -fsSL --max-time 15 \ + "https://api.github.com/repos/astral-sh/uv/releases/latest" 2>/dev/null || echo "") + + if [[ -z "$releases_json" ]]; then + msg_error "Could not fetch latest uv version from GitHub API" + return 1 + fi + local LATEST_VERSION - LATEST_VERSION=$(curl -fsSL https://api.github.com/repos/astral-sh/uv/releases/latest | - jq -r '.tag_name' | sed 's/^v//') + LATEST_VERSION=$(echo "$releases_json" | jq -r '.tag_name' 2>/dev/null | sed 's/^v//') if [[ -z "$LATEST_VERSION" ]]; then - msg_error "Could not fetch latest uv version" - rm -rf "$TMP_DIR" + msg_error "Could not parse uv version from GitHub API response" return 1 fi + # Get currently installed version + local INSTALLED_VERSION="" if [[ -x "$UV_BIN" ]]; then - local INSTALLED_VERSION - INSTALLED_VERSION=$($UV_BIN -V 2>/dev/null | awk '{print $2}') - if [[ "$INSTALLED_VERSION" == "$LATEST_VERSION" ]]; then - if [[ "$CACHED_VERSION" == "$LATEST_VERSION" ]]; then - rm -rf "$TMP_DIR" - return 0 - fi - cache_installed_version "uv" "$LATEST_VERSION" - rm -rf "$TMP_DIR" - return 0 - fi + INSTALLED_VERSION=$("$UV_BIN" --version 2>/dev/null | awk '{print $2}') fi - msg_info "Setup uv $LATEST_VERSION" + # Scenario 1: Already at latest version + if [[ -n "$INSTALLED_VERSION" && "$INSTALLED_VERSION" == "$LATEST_VERSION" ]]; then + cache_installed_version "uv" "$LATEST_VERSION" - local UV_URL="https://github.com/astral-sh/uv/releases/latest/download/${UV_TAR}" - curl -fsSL "$UV_URL" -o "$TMP_DIR/uv.tar.gz" || { - msg_error "Failed to download uv" - rm -rf "$TMP_DIR" + # Check if uvx is needed and missing + if [[ "${USE_UVX:-NO}" == "YES" ]] && [[ ! -x "$UVX_BIN" ]]; then + msg_info "Installing uvx wrapper" + _install_uvx_wrapper || return 1 + msg_ok "uvx wrapper installed" + fi + + return 0 + fi + + # Scenario 2: New install or upgrade + if [[ -n "$INSTALLED_VERSION" && "$INSTALLED_VERSION" != "$LATEST_VERSION" ]]; then + msg_info "Upgrade uv from $INSTALLED_VERSION to $LATEST_VERSION" + else + msg_info "Setup uv $LATEST_VERSION" + fi + + local UV_URL="https://github.com/astral-sh/uv/releases/download/${LATEST_VERSION}/${UV_TAR}" + + $STD curl -fsSL "$UV_URL" -o "$TMP_DIR/uv.tar.gz" || { + msg_error "Failed to download uv from $UV_URL" return 1 } - tar -xzf "$TMP_DIR/uv.tar.gz" -C "$TMP_DIR" || { + # Extract + $STD tar -xzf "$TMP_DIR/uv.tar.gz" -C "$TMP_DIR" || { msg_error "Failed to extract uv" - rm -rf "$TMP_DIR" return 1 } - install -m 755 "$TMP_DIR"/*/uv "$UV_BIN" || { + # Find and install uv binary (tarball extracts to uv-VERSION-ARCH/ directory) + local UV_BINARY=$(find "$TMP_DIR" -name "uv" -type f -executable | head -n1) + if [[ ! -f "$UV_BINARY" ]]; then + msg_error "Could not find uv binary in extracted tarball" + return 1 + fi + + $STD install -m 755 "$UV_BINARY" "$UV_BIN" || { msg_error "Failed to install uv binary" - rm -rf "$TMP_DIR" return 1 } - rm -rf "$TMP_DIR" ensure_usr_local_bin_persist export PATH="/usr/local/bin:$PATH" - $STD uv python update-shell || true + # Optional: Install uvx wrapper + if [[ "${USE_UVX:-NO}" == "YES" ]]; then + msg_info "Installing uvx wrapper" + _install_uvx_wrapper || { + msg_error "Failed to install uvx wrapper" + return 1 + } + msg_ok "uvx wrapper installed" + fi + + # Optional: Generate shell completions + $STD uv generate-shell-completion bash >/etc/bash_completion.d/uv 2>/dev/null || true + $STD uv generate-shell-completion zsh >/usr/share/zsh/site-functions/_uv 2>/dev/null || true + + # Optional: Install specific Python version if requested + if [[ -n "${PYTHON_VERSION:-}" ]]; then + msg_info "Installing Python $PYTHON_VERSION via uv" + $STD uv python install "$PYTHON_VERSION" || { + msg_error "Failed to install Python $PYTHON_VERSION" + return 1 + } + msg_ok "Python $PYTHON_VERSION installed" + fi + cache_installed_version "uv" "$LATEST_VERSION" msg_ok "Setup uv $LATEST_VERSION" +} - if [[ -n "${PYTHON_VERSION:-}" ]]; then - local VERSION_MATCH - VERSION_MATCH=$(uv python list --only-downloads | - grep -E "^cpython-${PYTHON_VERSION//./\\.}\.[0-9]+-linux" | - cut -d'-' -f2 | sort -V | tail -n1) +# Helper function to install uvx wrapper +_install_uvx_wrapper() { + local UVX_BIN="/usr/local/bin/uvx" - if [[ -z "$VERSION_MATCH" ]]; then - msg_error "No matching Python $PYTHON_VERSION.x version found" - return 1 - fi + cat >"$UVX_BIN" <<'EOF' +#!/bin/bash +# uvx - Run Python applications from PyPI as command-line tools +# Wrapper for: uv tool run +exec /usr/local/bin/uv tool run "$@" +EOF - if ! uv python list | grep -q "cpython-${VERSION_MATCH}-linux.*uv/python"; then - $STD uv python install "$VERSION_MATCH" || { - msg_error "Failed to install Python $VERSION_MATCH" - return 1 - } - fi - fi + chmod +x "$UVX_BIN" + return 0 } # ------------------------------------------------------------------------------ @@ -3532,42 +4395,55 @@ function setup_yq() { local TMP_DIR=$(mktemp -d) local BINARY_PATH="/usr/local/bin/yq" local GITHUB_REPO="mikefarah/yq" - local CURRENT_VERSION="" - local CACHED_VERSION - CACHED_VERSION=$(get_cached_version "yq") ensure_dependencies jq ensure_usr_local_bin_persist + # Remove non-mikefarah implementations if command -v yq &>/dev/null; then if ! yq --version 2>&1 | grep -q 'mikefarah'; then rm -f "$(command -v yq)" - else - CURRENT_VERSION=$(yq --version 2>/dev/null | awk '{print $NF}' | sed 's/^v//') fi fi local LATEST_VERSION - LATEST_VERSION=$(curl -fsSL "https://api.github.com/repos/${GITHUB_REPO}/releases/latest" | - jq -r '.tag_name' | sed 's/^v//') + local releases_json + releases_json=$(curl -fsSL --max-time 15 "https://api.github.com/repos/${GITHUB_REPO}/releases/latest" 2>/dev/null || echo "") - if [[ -z "$LATEST_VERSION" ]]; then - msg_error "Could not determine latest yq version" + if [[ -z "$releases_json" ]]; then + msg_error "Could not fetch latest yq version from GitHub API" rm -rf "$TMP_DIR" return 1 fi - if [[ -n "$CURRENT_VERSION" && "$CURRENT_VERSION" == "$LATEST_VERSION" ]]; then - if [[ "$CACHED_VERSION" == "$LATEST_VERSION" ]]; then - rm -rf "$TMP_DIR" - return 0 - fi + LATEST_VERSION=$(echo "$releases_json" | jq -r '.tag_name' 2>/dev/null | sed 's/^v//' || echo "") + + if [[ -z "$LATEST_VERSION" ]]; then + msg_error "Could not parse yq version from GitHub API response" + rm -rf "$TMP_DIR" + return 1 + fi + + # Get currently installed version + local INSTALLED_VERSION="" + if command -v yq &>/dev/null && yq --version 2>&1 | grep -q 'mikefarah'; then + INSTALLED_VERSION=$(yq --version 2>/dev/null | awk '{print $NF}' | sed 's/^v//') + fi + + # Scenario 1: Already at latest version + if [[ -n "$INSTALLED_VERSION" && "$INSTALLED_VERSION" == "$LATEST_VERSION" ]]; then cache_installed_version "yq" "$LATEST_VERSION" rm -rf "$TMP_DIR" return 0 fi - msg_info "Setup yq $LATEST_VERSION" + # Scenario 2: New install or upgrade + if [[ -n "$INSTALLED_VERSION" && "$INSTALLED_VERSION" != "$LATEST_VERSION" ]]; then + msg_info "Upgrade yq from $INSTALLED_VERSION to $LATEST_VERSION" + else + msg_info "Setup yq $LATEST_VERSION" + fi + curl -fsSL "https://github.com/${GITHUB_REPO}/releases/download/v${LATEST_VERSION}/yq_linux_amd64" -o "$TMP_DIR/yq" || { msg_error "Failed to download yq" rm -rf "$TMP_DIR" @@ -3575,13 +4451,11 @@ function setup_yq() { } chmod +x "$TMP_DIR/yq" - mv "$TMP_DIR/yq" "$BINARY_PATH" - - if [[ ! -x "$BINARY_PATH" ]]; then + mv "$TMP_DIR/yq" "$BINARY_PATH" || { msg_error "Failed to install yq" rm -rf "$TMP_DIR" return 1 - fi + } rm -rf "$TMP_DIR" hash -r diff --git a/vm/docker-vm.sh b/vm/docker-vm.sh index 2cb92d934..f291c50d8 100644 --- a/vm/docker-vm.sh +++ b/vm/docker-vm.sh @@ -497,6 +497,8 @@ if ! command -v virt-customize &>/dev/null; then msg_info "Installing Pre-Requisite libguestfs-tools onto Host" apt-get -qq update >/dev/null apt-get -qq install libguestfs-tools lsb-release -y >/dev/null + # Workaround for Proxmox VE 9.0 libguestfs issue + apt-get -qq install dhcpcd-base -y >/dev/null 2>&1 || true msg_ok "Installed libguestfs-tools successfully" fi