Compare commits

...

50 Commits

Author SHA1 Message Date
Sam Heinz
6f62656c96 Replace tools.func call that checks arch 2026-03-07 15:55:21 +10:00
Sam Heinz
087f817bf6 misc scripts: add support for arm64 2026-03-07 15:44:44 +10:00
community-scripts-pr-app[bot]
5c2cf61455 Update CHANGELOG.md (#12636)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-07 00:20:28 +00:00
community-scripts-pr-app[bot]
10b47eae33 chore: update github-versions.json (#12635)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-07 00:20:03 +00:00
community-scripts-pr-app[bot]
c61b0e766a Update CHANGELOG.md (#12629)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-06 20:54:29 +00:00
Slaviša Arežina
9ff1d088c5 Semaphore: Move from BoltDB to SQLite (#12624)
* Fix

* start

* Apply suggestion from @tremor021
2026-03-06 21:53:47 +01:00
community-scripts-pr-app[bot]
be803ced6f Update CHANGELOG.md (#12626)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-06 20:07:11 +00:00
Slaviša Arežina
5949e9e32e Fix (#12625) 2026-03-06 21:06:45 +01:00
community-scripts-pr-app[bot]
bb3276bbbd Update CHANGELOG.md (#12623)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-06 19:44:23 +00:00
Aurélien
b7a09989cb fix(node-red): restart service after update (#12621) 2026-03-06 20:43:58 +01:00
community-scripts-pr-app[bot]
039d046649 chore: update github-versions.json (#12622)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-06 18:13:22 +00:00
community-scripts-pr-app[bot]
58301651e4 Update CHANGELOG.md (#12618)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-06 15:17:25 +00:00
Tobias
b848c2d1bf wealthfolio: update cors (#12617)
* Update wealthfolio-install.sh

* Update wealthfolio.sh
2026-03-06 16:17:00 +01:00
CanbiZ (MickLesk)
9e2bb23d35 fix(wealthfolio): pin to v3.0.3 due to breaking changes 2026-03-06 14:16:54 +01:00
CanbiZ (MickLesk)
eb848fd70f databasus: make fetch_and_deploy_from_url accept empty dir
Pass an explicit empty second argument when downloading MongoDB tools and update fetch_and_deploy_from_url to default the directory parameter to an empty string. This avoids unset/ambiguous directory handling at the call site and ensures the function has a defined directory variable even when none is provided.
2026-03-06 14:11:57 +01:00
community-scripts-pr-app[bot]
176fffff0b Update CHANGELOG.md (#12616)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-06 13:04:52 +00:00
Slaviša Arežina
14e13edeef Add better update handling (#12611) 2026-03-06 14:04:23 +01:00
community-scripts-pr-app[bot]
4f70196444 chore: update github-versions.json (#12613)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-06 12:10:47 +00:00
community-scripts-pr-app[bot]
acc715de82 Update CHANGELOG.md (#12610)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-06 09:21:14 +00:00
Slaviša Arežina
5bfb5f486f RustDesk Server: Switch to updated repository (#12083)
* switch repo

* Add info about Alpine admin password and script usage

---------

Co-authored-by: CanbiZ (MickLesk) <47820557+MickLesk@users.noreply.github.com>
2026-03-06 10:20:46 +01:00
Michel Roegl-Brunner
6fbd785a87 Change runner to self-hosted for PR checks 2026-03-06 09:09:56 +01:00
community-scripts-pr-app[bot]
75b1c63884 chore: update github-versions.json (#12608)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-06 06:16:34 +00:00
community-scripts-pr-app[bot]
ad0808008a Update CHANGELOG.md (#12607)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-06 00:25:50 +00:00
community-scripts-pr-app[bot]
fcf75b06bf chore: update github-versions.json (#12606)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-06 00:25:26 +00:00
community-scripts-pr-app[bot]
b8d47cdce3 Update CHANGELOG.md (#12604)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-05 21:30:45 +00:00
Copilot
8301f04b58 fluid-calendar: add build-essential to install and update dependencies (#12602)
* Initial plan

* fix: add build-essential dependency to fluid-calendar install script

Co-authored-by: MickLesk <47820557+MickLesk@users.noreply.github.com>

* fix: add ensure_dependencies build-essential in update_script

Co-authored-by: MickLesk <47820557+MickLesk@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: MickLesk <47820557+MickLesk@users.noreply.github.com>
2026-03-05 22:30:20 +01:00
community-scripts-pr-app[bot]
34942ac799 chore: update github-versions.json (#12600)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-05 18:38:18 +00:00
community-scripts-pr-app[bot]
599f11683d Update CHANGELOG.md (#12599)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-05 18:10:05 +00:00
community-scripts-pr-app[bot]
55c699f841 Update CHANGELOG.md (#12598)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-05 18:00:27 +00:00
CanbiZ (MickLesk)
3a7f922d90 remove(suwayomiserver): remove due to inactivity (#12596)
Removed due to very low usage (3 installs in 120 days).
An alternative will be provided. Thanks for your understanding.
2026-03-05 18:57:51 +01:00
Chris
352716319f Refactor: BentoPDF (#12597)
* Refactor BentoPDF

* preserve .env.production if it exists

* Increase CPU cores to 2
2026-03-05 18:53:15 +01:00
community-scripts-pr-app[bot]
5162f13372 Update .app files (#12591)
Co-authored-by: GitHub Actions <github-actions[bot]@users.noreply.github.com>
2026-03-05 16:06:55 +01:00
community-scripts-pr-app[bot]
cbe8cc82c6 Update CHANGELOG.md (#12595)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-05 14:59:13 +00:00
community-scripts-pr-app[bot]
c02010ea58 Update date in json (#12594)
Co-authored-by: GitHub Actions <github-actions[bot]@users.noreply.github.com>
2026-03-05 14:59:10 +00:00
community-scripts-pr-app[bot]
45e39b21ec Update CHANGELOG.md (#12593)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-05 14:58:59 +00:00
push-app-to-main[bot]
7cbaf9c055 ddclient (#12587)
Co-authored-by: push-app-to-main[bot] <203845782+push-app-to-main[bot]@users.noreply.github.com>
2026-03-05 15:58:47 +01:00
community-scripts-pr-app[bot]
555f18d8df Update CHANGELOG.md (#12592)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-05 14:58:36 +00:00
push-app-to-main[bot]
f915c68a4b Netbird (#12585)
Co-authored-by: push-app-to-main[bot] <203845782+push-app-to-main[bot]@users.noreply.github.com>
Co-authored-by: CanbiZ (MickLesk) <47820557+MickLesk@users.noreply.github.com>
Co-authored-by: Tobias <96661824+CrazyWolf13@users.noreply.github.com>
2026-03-05 15:58:10 +01:00
community-scripts-pr-app[bot]
da9ddcb382 Update CHANGELOG.md (#12590)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-05 14:56:31 +00:00
Slaviša Arežina
55e6283075 Tianji: Fix the bug introduced by the refactor (#12564) 2026-03-05 15:56:02 +01:00
community-scripts-pr-app[bot]
e56b9dce35 Update CHANGELOG.md (#12589)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-05 14:28:32 +00:00
community-scripts-pr-app[bot]
363be950f0 Update CHANGELOG.md (#12588)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-05 14:28:09 +00:00
CanbiZ (MickLesk)
0f1a06ca32 core: add var_os / var_version to whitelist for app.vars (#12576)
Include var_os and var_version in VAR_WHITELIST across load_vars_file, default_var_settings, and the global whitelist declaration. Also emit sanitized var_os and var_version in _build_current_app_vars_tmp so they are included in generated app variable output and can be recognized/persisted by the build tooling.
2026-03-05 15:28:07 +01:00
CanbiZ (MickLesk)
24957ea881 fix(powerdns): use 'launch=' instead of 'launch+=' for gsqlite3 backend (#12579)
PowerDNS 5.x requires a parent 'launch=' directive before any
incremental 'launch+=' can be used. Since the install script
comments out the default 'launch=' in pdns.conf, the 'launch+='
in gsqlite3.conf fails with:
  Fatal error: Incremental setting 'launch' without a parent

Use 'launch=gsqlite3' (non-incremental) since gsqlite3 is the
only backend needed.
2026-03-05 15:27:40 +01:00
community-scripts-pr-app[bot]
0be065bbef Update .app files (#12583)
Co-authored-by: GitHub Actions <github-actions[bot]@users.noreply.github.com>
2026-03-05 14:13:16 +01:00
community-scripts-pr-app[bot]
10118f4350 Update CHANGELOG.md (#12584)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-05 12:51:11 +00:00
community-scripts-pr-app[bot]
ac435455a0 Update CHANGELOG.md (#12582)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-05 12:50:46 +00:00
community-scripts-pr-app[bot]
929cd08718 Update date in json (#12581)
Co-authored-by: GitHub Actions <github-actions[bot]@users.noreply.github.com>
2026-03-05 12:50:42 +00:00
push-app-to-main[bot]
299e7bfabe Papra (#12577)
* Add papra (ct)

* Update papra.sh

* Enhance update_script with configuration backup

Added backup and restore of configuration during update process.

* Update install/papra-install.sh

Co-authored-by: Slaviša Arežina <58952836+tremor021@users.noreply.github.com>

* Format

---------

Co-authored-by: push-app-to-main[bot] <203845782+push-app-to-main[bot]@users.noreply.github.com>
Co-authored-by: CanbiZ (MickLesk) <47820557+MickLesk@users.noreply.github.com>
Co-authored-by: Slaviša Arežina <58952836+tremor021@users.noreply.github.com>
Co-authored-by: tremor021 <arezina.slavisa@gmail.com>
2026-03-05 13:50:20 +01:00
community-scripts-pr-app[bot]
3465f053f5 chore: update github-versions.json (#12580)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-05 12:12:38 +00:00
43 changed files with 1217 additions and 484 deletions

View File

@@ -8,7 +8,7 @@ on:
jobs:
check-new-script:
if: github.repository == 'community-scripts/ProxmoxVE'
runs-on: coolify-runner
runs-on: self-hosted
permissions:
pull-requests: write
contents: read

View File

@@ -410,8 +410,54 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
</details>
## 2026-03-07
## 2026-03-06
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- RustDesk Server: Fix update script [@tremor021](https://github.com/tremor021) ([#12625](https://github.com/community-scripts/ProxmoxVE/pull/12625))
- [Node-RED] Restart service after update [@Aurelien30000](https://github.com/Aurelien30000) ([#12621](https://github.com/community-scripts/ProxmoxVE/pull/12621))
- wealthfolio: update cors [@CrazyWolf13](https://github.com/CrazyWolf13) ([#12617](https://github.com/community-scripts/ProxmoxVE/pull/12617))
- CryptPad: Better update handling [@tremor021](https://github.com/tremor021) ([#12611](https://github.com/community-scripts/ProxmoxVE/pull/12611))
- #### ✨ New Features
- RustDesk Server: Switch to updated repository [@tremor021](https://github.com/tremor021) ([#12083](https://github.com/community-scripts/ProxmoxVE/pull/12083))
- #### 💥 Breaking Changes
- Semaphore: Move from BoltDB to SQLite [@tremor021](https://github.com/tremor021) ([#12624](https://github.com/community-scripts/ProxmoxVE/pull/12624))
## 2026-03-05
### 🆕 New Scripts
- ddclient ([#12587](https://github.com/community-scripts/ProxmoxVE/pull/12587))
- Netbird ([#12585](https://github.com/community-scripts/ProxmoxVE/pull/12585))
- Papra ([#12577](https://github.com/community-scripts/ProxmoxVE/pull/12577))
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- fluid-calendar: add build-essential to install and update dependencies [@Copilot](https://github.com/Copilot) ([#12602](https://github.com/community-scripts/ProxmoxVE/pull/12602))
- Refactor: BentoPDF [@vhsdream](https://github.com/vhsdream) ([#12597](https://github.com/community-scripts/ProxmoxVE/pull/12597))
- Tianji: Fix the bug introduced by the refactor [@tremor021](https://github.com/tremor021) ([#12564](https://github.com/community-scripts/ProxmoxVE/pull/12564))
- PowerDNS: use 'launch=' instead of 'launch+=' for gsqlite3 backend [@MickLesk](https://github.com/MickLesk) ([#12579](https://github.com/community-scripts/ProxmoxVE/pull/12579))
### 🗑️ Deleted Scripts
- Suwayomi-Server: remove due to inactivity and very low usage [@MickLesk](https://github.com/MickLesk) ([#12596](https://github.com/community-scripts/ProxmoxVE/pull/12596))
### 💾 Core
- #### 🔧 Refactor
- core: add var_os / var_version to whitelist for app.vars [@MickLesk](https://github.com/MickLesk) ([#12576](https://github.com/community-scripts/ProxmoxVE/pull/12576))
## 2026-03-04
### 🚀 Updated Scripts

View File

@@ -31,6 +31,10 @@ function update_script() {
msg_info "Updating Node-RED"
$STD npm install -g --unsafe-perm node-red
msg_ok "Updated Node-RED"
msg_info "Restarting Node-RED"
$STD rc-service nodered restart
msg_ok "Restarted Node-RED"
msg_ok "Updated successfully!"
exit 0
}

View File

@@ -27,21 +27,21 @@ function update_script() {
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) }')
RELEASE=$(curl -s https://api.github.com/repos/rustdesk/rustdesk-server/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }')
RELEASE=$(curl -s https://api.github.com/repos/lejianwen/rustdesk-server/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }')
if [ "${RELEASE}" != "$(cat ~/.rustdesk-server 2>/dev/null)" ] || [ ! -f ~/.rustdesk-server ]; then
msg_info "Updating RustDesk Server to v${RELEASE}"
$STD apk -U upgrade
$STD service rustdesk-server-hbbs stop
$STD service rustdesk-server-hbbr stop
temp_file1=$(mktemp)
curl -fsSL "https://github.com/rustdesk/rustdesk-server/releases/download/${RELEASE}/rustdesk-server-linux-amd64.zip" -o "$temp_file1"
curl -fsSL "https://github.com/lejianwen/rustdesk-server/releases/download/${RELEASE}/rustdesk-server-linux-amd64.zip" -o "$temp_file1"
$STD unzip "$temp_file1"
cp -r amd64/* /opt/rustdesk-server/
echo "${RELEASE}" >~/.rustdesk-server
$STD service rustdesk-server-hbbs start
$STD service rustdesk-server-hbbr start
rm -rf amd64
rm -f $temp_file1
rm -f "$temp_file1"
msg_ok "Updated RustDesk Server"
else
msg_ok "No update required. ${APP} is already at v${RELEASE}"
@@ -56,7 +56,7 @@ function update_script() {
echo "${APIRELEASE}" >~/.rustdesk-api
$STD service rustdesk-api start
rm -rf release
rm -f $temp_file2
rm -f "$temp_file2"
msg_ok "Updated RustDesk API"
else
msg_ok "No update required. RustDesk API is already at v${APIRELEASE}"

View File

@@ -7,7 +7,7 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
APP="BentoPDF"
var_tags="${var_tags:-pdf-editor}"
var_cpu="${var_cpu:-1}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-4096}"
var_disk="${var_disk:-4}"
var_os="${var_os:-debian}"
@@ -35,16 +35,32 @@ function update_script() {
systemctl stop bentopdf
msg_ok "Stopped Service"
[[ -f /opt/bentopdf/.env.production ]] && cp /opt/bentopdf/.env.production /opt/production.env
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
$STD npm install http-server -g
if [[ -f /opt/production.env ]]; then
mv /opt/production.env ./.env.production
else
cp ./.env.example ./.env.production
fi
export NODE_OPTIONS="--max-old-space-size=3072"
export SIMPLE_MODE=true
$STD npm run build -- --mode production
export VITE_USE_CDN=true
$STD npm run build:all
msg_ok "Updated BentoPDF"
msg_info "Starting Service"
if grep -q '8080' /etc/systemd/system/bentopdf.service; then
sed -i -e 's|/bentopdf|/bentopdf/dist|' \
-e 's|npx.*|npx http-server -g -b -d false -r --no-dotfiles|' \
/etc/systemd/system/bentopdf.service
systemctl daemon-reload
fi
systemctl start bentopdf
msg_ok "Started Service"
msg_ok "Updated successfully!"

View File

@@ -33,17 +33,23 @@ function update_script() {
systemctl stop cryptpad
msg_info "Stopped Service"
msg_info "Backing up configuration"
msg_info "Creating backup"
[ -f /opt/cryptpad/config/config.js ] && mv /opt/cryptpad/config/config.js /opt/
msg_ok "Backed up configuration"
for dir in blob block customize data datastore www/common/onlyoffice/dist onlyoffice-conf; do
[ -d "/opt/cryptpad/${dir}" ] && mv "/opt/cryptpad/${dir}" "/tmp/cryptpad_${dir//\//_}"
done
msg_ok "Created backup"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "cryptpad" "cryptpad/cryptpad" "tarball"
msg_info "Restoring configuration"
msg_info "Restoring backup"
mv /opt/config.js /opt/cryptpad/config/
msg_ok "Configuration restored"
for dir in blob block customize data datastore www/common/onlyoffice/dist onlyoffice-conf; do
[ -d "/tmp/cryptpad_${dir//\//_}" ] && mv "/tmp/cryptpad_${dir//\//_}" "/opt/cryptpad/${dir}"
done
msg_ok "Restored backup"
msg_info "Updating CryptaPad"
msg_info "Updating CryptPad"
cd /opt/cryptpad
$STD npm ci
$STD npm run install:components

46
ct/ddclient.sh Normal file
View File

@@ -0,0 +1,46 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: mitchscobell
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://ddclient.net/
APP="ddclient"
var_tags="${var_tags:-network}"
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 [[ ! -f /etc/ddclient.conf ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
msg_info "Updating ddclient"
$STD apt update
$STD apt install --only-upgrade -y ddclient
$STD systemctl restart ddclient
msg_ok "Updated ddclient"
msg_ok "Updated successfully!"
exit
}
start
build_container
description
msg_ok "Completed successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"

View File

@@ -29,6 +29,7 @@ function update_script() {
exit
fi
ensure_dependencies build-essential
NODE_VERSION="24" setup_nodejs
if check_for_gh_release "fluid-calendar" "dotnetfactory/fluid-calendar"; then

6
ct/headers/ddclient Normal file
View File

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

6
ct/headers/netbird Normal file
View File

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

6
ct/headers/papra Normal file
View File

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

View File

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

47
ct/netbird.sh Normal file
View File

@@ -0,0 +1,47 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: TechHutTV
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://netbird.io/
APP="NetBird"
var_tags="${var_tags:-network;vpn}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-512}"
var_disk="${var_disk:-4}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
var_tun="${var_tun:-yes}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -f /etc/netbird/config.json ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
msg_info "Updating Netbird"
$STD apt update
$STD apt upgrade -y
msg_ok "Updated successfully!"
exit
}
start
build_container
description
msg_ok "Completed successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access NetBird by entering the container and running:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}netbird up${CL}"

68
ct/papra.sh Normal file
View File

@@ -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-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/papra-hq/papra
APP="Papra"
var_tags="${var_tags:-document-management}"
var_cpu="${var_cpu:-2}"
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/papra ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "papra" "papra-hq/papra"; then
msg_info "Stopping Service"
systemctl stop papra
msg_ok "Stopped Service"
msg_info "Backing up Configuration"
cp /opt/papra/apps/papra-server/.env /opt/papra_env.bak
msg_ok "Backed up Configuration"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "papra" "papra-hq/papra" "tarball"
msg_info "Building Application"
cd /opt/papra
cp /opt/papra_env.bak /opt/papra/apps/papra-server/.env
$STD pnpm install --frozen-lockfile
$STD pnpm --filter "@papra/app-client..." run build
$STD pnpm --filter "@papra/app-server..." run build
ln -sf /opt/papra/apps/papra-client/dist /opt/papra/apps/papra-server/public
rm -f /opt/papra_env.bak
msg_ok "Built Application"
msg_info "Starting Service"
systemctl start papra
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}:1221${CL}"

View File

@@ -29,9 +29,7 @@ function update_script() {
exit
fi
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
if check_for_gh_release "rustdesk-api"; then
msg_info "Stopping Service"
systemctl stop rustdesk-hbbr
systemctl stop rustdesk-hbbs
@@ -40,13 +38,13 @@ function update_script() {
fi
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"
fetch_and_deploy_gh_release "rustdesk-utils" "rustdesk/rustdesk-server" "binary" "latest" "/opt/rustdesk" "rustdesk-server-utils*amd64.deb"
fetch_and_deploy_gh_release "rustdesk-hbbr" "lejianwen/rustdesk-server" "binary" "latest" "/opt/rustdesk" "rustdesk-server-hbbr*amd64.deb"
fetch_and_deploy_gh_release "rustdesk-hbbs" "lejianwen/rustdesk-server" "binary" "latest" "/opt/rustdesk" "rustdesk-server-hbbs*amd64.deb"
fetch_and_deploy_gh_release "rustdesk-utils" "lejianwen/rustdesk-server" "binary" "latest" "/opt/rustdesk" "rustdesk-server-utils*amd64.deb"
fetch_and_deploy_gh_release "rustdesk-api" "lejianwen/rustdesk-api" "binary" "latest" "/opt/rustdesk" "rustdesk-api-server*amd64.deb"
msg_info "Starting services"
systemctl start -q rustdesk-* --all
systemctl start -q rustdesk-*
msg_ok "Services started"
msg_ok "Updated successfully!"

View File

@@ -28,6 +28,34 @@ function update_script() {
msg_error "No ${APP} Installation Found!"
exit
fi
if [[ -f /opt/semaphore/semaphore_db.bolt ]]; then
msg_warn "WARNING: Due to bugs with BoltDB database, update script will move your application"
msg_warn "to use SQLite database instead. Unfortunately, this will reset your application and make it a fresh"
msg_warn "installation. All your data will be lost!"
echo ""
read -r -p "${TAB3}Do you want to continue? (y/N): " CONFIRM
if [[ ! "$CONFIRM" =~ ^[Yy]$ ]]; then
exit 0
else
msg_info "Moving from BoltDB to SQLite"
systemctl stop semaphore
rm -rf /opt/semaphore/semaphore_db.bolt
sed -i \
-e 's|"bolt": {|"sqlite": {|' \
-e 's|/semaphore_db.bolt"|/database.sqlite"|' \
-e '/semaphore_db.bolt/d' \
-e '/"dialect"/d' \
-e '/^ },$/a\ "dialect": "sqlite",' \
/opt/semaphore/config.json
SEM_PW=$(cat ~/semaphore.creds)
systemctl start semaphore
$STD semaphore user add --admin --login admin --email admin@helper-scripts.com --name Administrator --password "${SEM_PW}" --config /opt/semaphore/config.json
msg_ok "Moved from BoltDB to SQLite"
fi
fi
if check_for_gh_release "semaphore" "semaphoreui/semaphore"; then
msg_info "Stopping Service"
systemctl stop semaphore

View File

@@ -1,56 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: Slaviša Arežina (tremor021)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/Suwayomi/Suwayomi-Server
APP="SuwayomiServer"
var_tags="${var_tags:-media;manga}"
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_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/bin/suwayomi-server ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "suwayomi-server" "Suwayomi/Suwayomi-Server"; then
JAVA_VERSION=21 setup_java
msg_info "Stopping Service"
systemctl stop suwayomi-server
msg_info "Stopped Service"
fetch_and_deploy_gh_release "suwayomi-server" "Suwayomi/Suwayomi-Server" "binary"
msg_info "Starting Service"
systemctl start suwayomi-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}:4567${CL}"

View File

@@ -29,6 +29,10 @@ function update_script() {
exit
fi
if grep -q '^WF_CORS_ALLOW_ORIGINS=\*$' /opt/wealthfolio/.env; then
sed -i "s|^WF_CORS_ALLOW_ORIGINS=\*$|WF_CORS_ALLOW_ORIGINS=http://${LOCAL_IP}:8080|" /opt/wealthfolio/.env
fi
if check_for_gh_release "wealthfolio" "afadil/wealthfolio"; then
msg_info "Stopping Service"
systemctl stop wealthfolio

View File

@@ -19,7 +19,7 @@
"type": "default",
"script": "ct/bentopdf.sh",
"resources": {
"cpu": 1,
"cpu": 2,
"ram": 4096,
"hdd": 4,
"os": "debian",

View File

@@ -0,0 +1,44 @@
{
"name": "ddclient",
"slug": "ddclient",
"categories": [
4
],
"date_created": "2026-03-05",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": null,
"documentation": "https://ddclient.net/",
"website": "https://ddclient.net/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/ddclient.webp",
"config_path": "/etc/ddclient.conf",
"description": "ddclient is a Perl client used to update dynamic DNS entries for accounts on a wide range of dynamic DNS service providers. It supports multiple protocols and providers, allowing automatic IP address updates for your domain names.",
"install_methods": [
{
"type": "default",
"script": "ct/ddclient.sh",
"resources": {
"cpu": 1,
"ram": 512,
"hdd": 2,
"os": "debian",
"version": "13"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"type": "info",
"text": "After installation, edit `/etc/ddclient.conf` with your dynamic DNS provider credentials"
},
{
"type": "info",
"text": "Sample configuration is created for Namecheap but can be modified for other providers"
}
]
}

View File

@@ -1,5 +1,5 @@
{
"generated": "2026-03-05T06:17:38Z",
"generated": "2026-03-07T00:19:56Z",
"versions": [
{
"slug": "2fauth",
@@ -151,9 +151,9 @@
{
"slug": "booklore",
"repo": "booklore-app/BookLore",
"version": "v2.0.5",
"version": "v2.0.6",
"pinned": false,
"date": "2026-03-01T16:13:13Z"
"date": "2026-03-06T19:16:29Z"
},
{
"slug": "bookstack",
@@ -193,9 +193,9 @@
{
"slug": "checkmate",
"repo": "bluewave-labs/Checkmate",
"version": "v3.5.0",
"version": "v3.5.1",
"pinned": false,
"date": "2026-03-04T19:51:22Z"
"date": "2026-03-06T21:18:36Z"
},
{
"slug": "cleanuparr",
@@ -214,9 +214,9 @@
{
"slug": "comfyui",
"repo": "comfyanonymous/ComfyUI",
"version": "v0.15.1",
"version": "v0.16.3",
"pinned": false,
"date": "2026-02-26T22:01:35Z"
"date": "2026-03-05T23:18:25Z"
},
{
"slug": "commafeed",
@@ -270,9 +270,9 @@
{
"slug": "databasus",
"repo": "databasus/databasus",
"version": "v3.16.4",
"version": "v3.17.0",
"pinned": false,
"date": "2026-03-01T08:20:17Z"
"date": "2026-03-06T07:07:22Z"
},
{
"slug": "dawarich",
@@ -284,9 +284,9 @@
{
"slug": "discopanel",
"repo": "nickheyer/discopanel",
"version": "v1.0.37",
"version": "v2.0.0",
"pinned": false,
"date": "2026-02-18T08:53:43Z"
"date": "2026-03-06T08:19:39Z"
},
{
"slug": "dispatcharr",
@@ -326,9 +326,9 @@
{
"slug": "drawio",
"repo": "jgraph/drawio",
"version": "v29.5.2",
"version": "v29.6.1",
"pinned": false,
"date": "2026-02-22T10:36:14Z"
"date": "2026-03-06T09:14:17Z"
},
{
"slug": "duplicati",
@@ -382,9 +382,9 @@
{
"slug": "firefly",
"repo": "firefly-iii/firefly-iii",
"version": "v6.5.3",
"version": "v6.5.4",
"pinned": false,
"date": "2026-03-04T06:53:02Z"
"date": "2026-03-06T09:07:56Z"
},
{
"slug": "fladder",
@@ -452,9 +452,9 @@
{
"slug": "gitea-mirror",
"repo": "RayLabsHQ/gitea-mirror",
"version": "v3.12.2",
"version": "v3.12.4",
"pinned": false,
"date": "2026-03-05T04:26:50Z"
"date": "2026-03-06T05:02:40Z"
},
{
"slug": "glance",
@@ -501,9 +501,9 @@
{
"slug": "grocy",
"repo": "grocy/grocy",
"version": "v4.5.0",
"version": "v4.6.0",
"pinned": false,
"date": "2025-03-28T19:02:22Z"
"date": "2026-03-06T17:35:19Z"
},
{
"slug": "guardian",
@@ -550,9 +550,9 @@
{
"slug": "homarr",
"repo": "homarr-labs/homarr",
"version": "v1.54.0",
"version": "v1.55.0",
"pinned": false,
"date": "2026-02-27T19:38:50Z"
"date": "2026-03-06T19:40:16Z"
},
{
"slug": "homebox",
@@ -606,16 +606,16 @@
{
"slug": "invoiceninja",
"repo": "invoiceninja/invoiceninja",
"version": "v5.12.69",
"version": "v5.12.70",
"pinned": false,
"date": "2026-02-26T22:23:32Z"
"date": "2026-03-06T01:53:38Z"
},
{
"slug": "jackett",
"repo": "Jackett/Jackett",
"version": "v0.24.1287",
"version": "v0.24.1292",
"pinned": false,
"date": "2026-03-05T05:49:33Z"
"date": "2026-03-06T05:57:21Z"
},
{
"slug": "jellystat",
@@ -641,9 +641,9 @@
{
"slug": "kapowarr",
"repo": "Casvt/Kapowarr",
"version": "V1.2.0",
"version": "V1.3.0",
"pinned": false,
"date": "2025-04-16T14:55:28Z"
"date": "2026-03-06T16:38:21Z"
},
{
"slug": "karakeep",
@@ -662,9 +662,9 @@
{
"slug": "keycloak",
"repo": "keycloak/keycloak",
"version": "26.5.4",
"version": "26.5.5",
"pinned": false,
"date": "2026-02-20T09:19:45Z"
"date": "2026-03-05T15:40:30Z"
},
{
"slug": "kima-hub",
@@ -872,9 +872,9 @@
{
"slug": "metube",
"repo": "alexta69/metube",
"version": "2026.03.03",
"version": "2026.03.06",
"pinned": false,
"date": "2026-03-03T19:15:55Z"
"date": "2026-03-06T13:52:56Z"
},
{
"slug": "miniflux",
@@ -1110,9 +1110,9 @@
{
"slug": "photoprism",
"repo": "photoprism/photoprism",
"version": "251130-b3068414c",
"version": "260305-fad9d5395",
"pinned": false,
"date": "2025-12-01T05:07:31Z"
"date": "2026-03-05T20:25:12Z"
},
{
"slug": "pihole-exporter",
@@ -1138,9 +1138,9 @@
{
"slug": "pocketbase",
"repo": "pocketbase/pocketbase",
"version": "v0.36.5",
"version": "v0.36.6",
"pinned": false,
"date": "2026-02-21T11:45:32Z"
"date": "2026-03-06T08:07:09Z"
},
{
"slug": "pocketid",
@@ -1229,9 +1229,9 @@
{
"slug": "pulse",
"repo": "rcourtman/Pulse",
"version": "v5.1.18",
"version": "v5.1.21",
"pinned": false,
"date": "2026-03-03T22:09:15Z"
"date": "2026-03-06T12:13:08Z"
},
{
"slug": "pve-scripts-local",
@@ -1285,9 +1285,9 @@
{
"slug": "rclone",
"repo": "rclone/rclone",
"version": "v1.73.1",
"version": "v1.73.2",
"pinned": false,
"date": "2026-02-17T18:27:21Z"
"date": "2026-03-06T20:42:26Z"
},
{
"slug": "rdtclient",
@@ -1306,9 +1306,9 @@
{
"slug": "recyclarr",
"repo": "recyclarr/recyclarr",
"version": "v8.3.2",
"version": "v8.4.0",
"pinned": false,
"date": "2026-02-25T22:39:51Z"
"date": "2026-03-06T01:25:59Z"
},
{
"slug": "reitti",
@@ -1333,10 +1333,10 @@
},
{
"slug": "rustdeskserver",
"repo": "rustdesk/rustdesk-server",
"version": "1.1.15",
"repo": "lejianwen/rustdesk-server",
"version": "v0.1.2",
"pinned": false,
"date": "2026-01-12T05:38:30Z"
"date": "2025-09-01T02:52:30Z"
},
{
"slug": "rustypaste",
@@ -1355,9 +1355,9 @@
{
"slug": "scanopy",
"repo": "scanopy/scanopy",
"version": "v0.14.11",
"version": "v0.14.14",
"pinned": false,
"date": "2026-03-02T08:48:42Z"
"date": "2026-03-06T06:50:38Z"
},
{
"slug": "scraparr",
@@ -1369,9 +1369,9 @@
{
"slug": "seaweedfs",
"repo": "seaweedfs/seaweedfs",
"version": "4.14",
"version": "4.15",
"pinned": false,
"date": "2026-03-05T04:49:27Z"
"date": "2026-03-05T06:30:30Z"
},
{
"slug": "seelf",
@@ -1390,9 +1390,9 @@
{
"slug": "semaphore",
"repo": "semaphoreui/semaphore",
"version": "v2.17.15",
"version": "v2.17.16",
"pinned": false,
"date": "2026-02-28T09:04:40Z"
"date": "2026-03-05T12:39:05Z"
},
{
"slug": "shelfmark",
@@ -1411,9 +1411,9 @@
{
"slug": "silverbullet",
"repo": "silverbulletmd/silverbullet",
"version": "2.4.1",
"version": "2.5.2",
"pinned": false,
"date": "2026-01-16T12:08:28Z"
"date": "2026-03-06T12:20:58Z"
},
{
"slug": "slskd",
@@ -1467,16 +1467,16 @@
{
"slug": "sportarr",
"repo": "Sportarr/Sportarr",
"version": "v4.0.985.1060",
"version": "v4.0.986.1061",
"pinned": false,
"date": "2026-03-04T01:00:04Z"
"date": "2026-03-06T01:04:24Z"
},
{
"slug": "stirling-pdf",
"repo": "Stirling-Tools/Stirling-PDF",
"version": "v2.6.0",
"version": "v2.7.0",
"pinned": false,
"date": "2026-03-03T20:46:42Z"
"date": "2026-03-06T11:21:47Z"
},
{
"slug": "streamlink-webui",
@@ -1593,9 +1593,9 @@
{
"slug": "traefik",
"repo": "traefik/traefik",
"version": "v3.6.9",
"version": "v3.6.10",
"pinned": false,
"date": "2026-02-23T17:21:17Z"
"date": "2026-03-06T15:08:35Z"
},
{
"slug": "trilium",
@@ -1698,9 +1698,9 @@
{
"slug": "wallos",
"repo": "ellite/Wallos",
"version": "v4.6.1",
"version": "v4.6.2",
"pinned": false,
"date": "2026-02-10T21:06:46Z"
"date": "2026-03-05T22:18:06Z"
},
{
"slug": "wanderer",
@@ -1741,7 +1741,7 @@
"slug": "wealthfolio",
"repo": "afadil/wealthfolio",
"version": "v3.0.3",
"pinned": false,
"pinned": true,
"date": "2026-03-03T21:47:55Z"
},
{
@@ -1838,9 +1838,9 @@
{
"slug": "zwave-js-ui",
"repo": "zwave-js/zwave-js-ui",
"version": "v11.13.0",
"version": "v11.14.0",
"pinned": false,
"date": "2026-03-04T15:09:54Z"
"date": "2026-03-06T09:34:32Z"
}
]
}

View File

@@ -0,0 +1,50 @@
{
"name": "NetBird",
"slug": "netbird",
"categories": [4],
"date_created": "2026-03-05",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": null,
"documentation": "https://docs.netbird.io/",
"website": "https://netbird.io/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/netbird.webp",
"config_path": "/etc/netbird/config.json",
"description": "NetBird is an open source VPN management platform that creates secure peer-to-peer networks using WireGuard. It enables secure connectivity between devices anywhere in the world without complex firewall configurations or port forwarding. NetBird offers features like zero-configuration networking, SSO integration, access control policies, and a centralized management dashboard. It's designed to be simple to deploy and manage, making it ideal for connecting remote teams, securing IoT devices, or building secure infrastructure networks.",
"install_methods": [
{
"type": "default",
"script": "ct/netbird.sh",
"resources": {
"cpu": 1,
"ram": 512,
"hdd": 4,
"os": "debian",
"version": "13"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "The NetBird client (agent) allows a peer to join a pre-existing NetBird deployment. If a NetBird deployment is not yet available, there are both managed and self-hosted options available.",
"type": "info"
},
{
"text": "After installation, enter the container and run `netbird` to view the commands.",
"type": "info"
},
{
"text": "Use a Setup Key from your NetBird dashboard or SSO login to authenticate during setup or in the container.",
"type": "info"
},
{
"text": "Check connection status with `netbird status`.",
"type": "info"
}
]
}

View File

@@ -0,0 +1,56 @@
{
"name": "Papra",
"slug": "papra",
"categories": [
12
],
"date_created": "2026-03-05",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 1221,
"documentation": "https://github.com/CorentinTh/papra",
"website": "https://github.com/CorentinTh/papra",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/papra.webp",
"config_path": "/opt/papra/.env",
"description": "Papra is a modern, self-hosted document management system with full-text search, OCR support, and automatic document processing. Built with Node.js and featuring a clean web interface for organizing and managing your documents.",
"install_methods": [
{
"type": "default",
"script": "ct/papra.sh",
"resources": {
"cpu": 2,
"ram": 2048,
"hdd": 10,
"os": "debian",
"version": "13"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "First visit will prompt you to create an account",
"type": "info"
},
{
"text": "Tesseract OCR is pre-installed for all languages",
"type": "info"
},
{
"text": "Documents are stored in /opt/papra/app-data/documents",
"type": "info"
},
{
"text": "Ingestion folder available at /opt/papra/ingestion for automatic document import",
"type": "info"
},
{
"text": "Email functionality runs in dry-run mode by default",
"type": "warning"
}
]
}

View File

@@ -54,6 +54,10 @@
{
"text": "To see admin password on Alpine, type `cat ~/rustdesk.creds` inside LXC.",
"type": "info"
},
{
"text": "This script uses hbbs/hbbr builds from `lejianwen/rustdesk-server` (instead of the official repo) for full compatibility with the RustDesk API (SSO/OAuth). See `https://github.com/community-scripts/ProxmoxVE/issues/12079`.",
"type": "info"
}
]
}

View File

@@ -33,7 +33,7 @@
},
"notes": [
{
"text": "This instance uses BoltDB",
"text": "This instance uses SQLite",
"type": "info"
},
{

View File

@@ -1,40 +0,0 @@
{
"name": "Suwayomi-Server",
"slug": "suwayomi-server",
"categories": [
13
],
"date_created": "2025-08-01",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 4567,
"documentation": "https://github.com/Suwayomi/Suwayomi-Server/wiki",
"website": "https://github.com/Suwayomi/Suwayomi-Server",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/suwayomi.webp",
"config_path": "",
"description": "A free and open source manga reader server that runs extensions built for Mihon (Tachiyomi).",
"install_methods": [
{
"type": "default",
"script": "ct/suwayomiserver.sh",
"resources": {
"cpu": 1,
"ram": 1024,
"hdd": 4,
"os": "debian",
"version": "13"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "This application can be conflicting with Kaspersky products. You maybe need to disable Kaspersky in order to use this application.",
"type": "info"
}
]
}

View File

@@ -13,17 +13,17 @@ setting_up_container
network_check
update_os
RELEASE=$(curl -s https://api.github.com/repos/rustdesk/rustdesk-server/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }')
RELEASE=$(curl -s https://api.github.com/repos/lejianwen/rustdesk-server/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }')
msg_info "Installing RustDesk Server v${RELEASE}"
temp_file1=$(mktemp)
curl -fsSL "https://github.com/rustdesk/rustdesk-server/releases/download/${RELEASE}/rustdesk-server-linux-amd64.zip" -o "$temp_file1"
curl -fsSL "https://github.com/lejianwen/rustdesk-server/releases/download/${RELEASE}/rustdesk-server-linux-amd64.zip" -o "$temp_file1"
$STD unzip "$temp_file1"
mv amd64 /opt/rustdesk-server
mkdir -p /root/.config/rustdesk
cd /opt/rustdesk-server
./rustdesk-utils genkeypair > /tmp/rustdesk_keys.txt
grep "Public Key" /tmp/rustdesk_keys.txt | awk '{print $3}' > /root/.config/rustdesk/id_ed25519.pub
grep "Secret Key" /tmp/rustdesk_keys.txt | awk '{print $3}' > /root/.config/rustdesk/id_ed25519
./rustdesk-utils genkeypair >/tmp/rustdesk_keys.txt
grep "Public Key" /tmp/rustdesk_keys.txt | awk '{print $3}' >/root/.config/rustdesk/id_ed25519.pub
grep "Secret Key" /tmp/rustdesk_keys.txt | awk '{print $3}' >/root/.config/rustdesk/id_ed25519
chmod 600 /root/.config/rustdesk/id_ed25519
chmod 644 /root/.config/rustdesk/id_ed25519.pub
rm /tmp/rustdesk_keys.txt

View File

@@ -19,8 +19,12 @@ fetch_and_deploy_gh_release "bentopdf" "alam00000/bentopdf" "tarball" "latest" "
msg_info "Setup BentoPDF"
cd /opt/bentopdf
$STD npm ci --no-audit --no-fund
$STD npm install http-server -g
cp ./.env.example ./.env.production
export NODE_OPTIONS="--max-old-space-size=3072"
export SIMPLE_MODE=true
$STD npm run build -- --mode production
export VITE_USE_CDN=true
$STD npm run build:all
msg_ok "Setup BentoPDF"
msg_info "Creating Service"
@@ -31,8 +35,8 @@ After=network.target
[Service]
Type=simple
WorkingDirectory=/opt/bentopdf
ExecStart=/usr/bin/npx serve dist -p 8080
WorkingDirectory=/opt/bentopdf/dist
ExecStart=/usr/bin/npx http-server -g -b -d false -r --no-dotfiles
Restart=always
RestartSec=10

View File

@@ -33,7 +33,7 @@ done
# Install MongoDB Database Tools via direct .deb (no APT repo for Debian 13)
[[ "$(get_os_info id)" == "ubuntu" ]] && MONGO_DIST="ubuntu2204" || MONGO_DIST="debian12"
MONGO_VERSION=$(get_latest_gh_tag "mongodb/mongo-tools" "100." || echo "100.14.1")
fetch_and_deploy_from_url "https://fastdl.mongodb.org/tools/db/mongodb-database-tools-${MONGO_DIST}-x86_64-${MONGO_VERSION}.deb"
fetch_and_deploy_from_url "https://fastdl.mongodb.org/tools/db/mongodb-database-tools-${MONGO_DIST}-x86_64-${MONGO_VERSION}.deb" ""
mkdir -p /usr/local/mongodb-database-tools/bin
[[ -f /usr/bin/mongodump ]] && ln -sf /usr/bin/mongodump /usr/local/mongodb-database-tools/bin/mongodump
[[ -f /usr/bin/mongorestore ]] && ln -sf /usr/bin/mongorestore /usr/local/mongodb-database-tools/bin/mongorestore

View File

@@ -0,0 +1,37 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2026 mitchscobell
# Author: mitchscobell
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://ddclient.net/
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
color
verb_ip6
catch_errors
setting_up_container
network_check
update_os
msg_info "Installing ddclient"
DEBIAN_FRONTEND=noninteractive $STD apt -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" install -y ddclient
msg_ok "Installed ddclient"
msg_info "Creating ddclient service"
cat << EOF >/etc/ddclient.conf
protocol=namecheap
use=web, web=dynamicdns.park-your-domain.com/getip
protocol=namecheap
use=web, web=dynamicdns.park-your-domain.com/getip
server=dynamicdns.park-your-domain.com
login=yourdomain.com
password='your-ddns-password'
@,www
EOF
chmod 600 /etc/ddclient.conf
systemctl enable -q --now ddclient
msg_ok "Created ddclient service"
motd_ssh
customize
cleanup_lxc

View File

@@ -14,7 +14,9 @@ network_check
update_os
msg_info "Installing Dependencies"
$STD apt install -y zip
$STD apt install -y \
build-essential \
zip
msg_ok "Installed Dependencies"
PG_VERSION="17" setup_postgresql

180
install/netbird-install.sh Normal file
View File

@@ -0,0 +1,180 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: TechHutTV
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://netbird.io/
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
color
verb_ip6
catch_errors
setting_up_container
network_check
update_os
msg_info "Installing NetBird"
setup_deb822_repo \
"netbird" \
"https://pkgs.netbird.io/debian/public.key" \
"https://pkgs.netbird.io/debian" \
"stable"
$STD apt install -y netbird
msg_ok "Installed NetBird"
msg_info "Starting NetBird Service"
systemctl enable -q --now netbird
msg_ok "Started NetBird Service"
echo ""
echo ""
echo -e "${BL}NetBird Deployment Type${CL}"
echo "─────────────────────────────────────────"
echo "Are you using NetBird Managed or Self-Hosted?"
echo ""
echo " 1) NetBird Managed (default) - Use NetBird's managed service"
echo " 2) Self-Hosted - Use your own NetBird management server"
echo ""
read -r -p "${TAB3}Select deployment type [1]: " DEPLOYMENT_TYPE
DEPLOYMENT_TYPE="${DEPLOYMENT_TYPE:-1}"
NETBIRD_MGMT_URL=""
case "$DEPLOYMENT_TYPE" in
1)
msg_ok "Using NetBird Managed service"
;;
2)
echo ""
echo -e "${BL}Self-Hosted Configuration${CL}"
echo "─────────────────────────────────────────"
echo "Enter your NetBird management server URL."
echo "Example: https://management.example.com"
echo ""
read -r -p "Management URL: " NETBIRD_MGMT_URL
if [[ -z "$NETBIRD_MGMT_URL" ]]; then
msg_warn "No management URL provided. Run 'netbird up --management-url <url>' to connect."
else
NETBIRD_MGMT_URL="${NETBIRD_MGMT_URL%/}"
msg_ok "Management URL configured: ${NETBIRD_MGMT_URL}"
fi
;;
*)
msg_warn "Invalid selection. Using NetBird Managed service."
;;
esac
echo ""
echo ""
echo -e "${BL}NetBird Connection Setup${CL}"
echo "─────────────────────────────────────────"
echo "Choose how to connect to your NetBird network:"
echo ""
if [[ "$DEPLOYMENT_TYPE" == "1" ]]; then
echo " 1) Setup Key (default) - Use a pre-generated setup key"
echo " 2) SSO Login - Authenticate via browser with your identity provider"
echo " 3) Skip - Configure later with 'netbird up'"
else
echo " 1) Setup Key (default) - Use a pre-generated setup key"
echo " 2) Skip - Configure later with 'netbird up'"
fi
echo ""
read -r -p "Select authentication method [1]: " AUTH_METHOD
AUTH_METHOD="${AUTH_METHOD:-1}"
if [[ "$DEPLOYMENT_TYPE" == "1" ]]; then
case "$AUTH_METHOD" in
1)
echo ""
echo "Enter your NetBird setup key from the NetBird dashboard."
echo ""
read -r -p "Setup key: " NETBIRD_SETUP_KEY
echo ""
if [[ -z "$NETBIRD_SETUP_KEY" ]]; then
msg_warn "No setup key provided. Run 'netbird up -k <key>' to connect."
else
msg_info "Connecting to NetBird with setup key"
if $STD netbird up -k "$NETBIRD_SETUP_KEY"; then
msg_ok "Connected to NetBird"
else
msg_warn "Connection failed. Run 'netbird up -k <key>' to retry."
fi
fi
;;
2)
echo ""
echo -e "${BL}SSO Authentication${CL}"
echo "─────────────────────────────────────────"
echo "A login URL will appear below."
echo "Copy the URL and open it in your browser to authenticate."
echo ""
msg_info "Starting SSO login"
netbird login 2>&1 || true
echo ""
msg_info "Connecting to NetBird"
if $STD netbird up; then
msg_ok "Connected to NetBird"
else
msg_warn "Connection failed. Run 'netbird up' to retry."
fi
;;
3)
msg_ok "Skipped. Run 'netbird up' to connect."
;;
*)
msg_warn "Invalid selection. Run 'netbird up' to connect."
;;
esac
else
case "$AUTH_METHOD" in
1)
echo ""
echo "Enter your NetBird setup key from the NetBird dashboard."
echo ""
read -r -p "Setup key: " NETBIRD_SETUP_KEY
echo ""
if [[ -z "$NETBIRD_SETUP_KEY" ]]; then
if [[ -z "$NETBIRD_MGMT_URL" ]]; then
msg_warn "No setup key provided. Run 'netbird up -k <key> --management-url <url>' to connect."
else
msg_warn "No setup key provided. Run 'netbird up -k <key> --management-url $NETBIRD_MGMT_URL' to connect."
fi
else
if [[ -z "$NETBIRD_MGMT_URL" ]]; then
msg_error "Management URL is required for self-hosted deployments. Please configure it first."
else
msg_info "Connecting to NetBird with setup key"
if $STD netbird up -k "$NETBIRD_SETUP_KEY" --management-url "$NETBIRD_MGMT_URL"; then
msg_ok "Connected to NetBird"
else
msg_warn "Connection failed. Run 'netbird up -k <key> --management-url $NETBIRD_MGMT_URL' to retry."
fi
fi
fi
;;
2)
if [[ -z "$NETBIRD_MGMT_URL" ]]; then
msg_ok "Skipped. Run 'netbird up --management-url <url>' to connect."
else
msg_ok "Skipped. Run 'netbird up --management-url $NETBIRD_MGMT_URL' to connect."
fi
;;
*)
if [[ -z "$NETBIRD_MGMT_URL" ]]; then
msg_warn "Invalid selection. Run 'netbird up --management-url <url>' to connect."
else
msg_warn "Invalid selection. Run 'netbird up --management-url $NETBIRD_MGMT_URL' to connect."
fi
;;
esac
fi
motd_ssh
customize
cleanup_lxc

79
install/papra-install.sh Normal file
View File

@@ -0,0 +1,79 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/papra-hq/papra
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 \
tesseract-ocr \
tesseract-ocr-all
msg_ok "Installed Dependencies"
RELEASE=$(curl -fsSL https://api.github.com/repos/papra-hq/papra/releases | grep -oP '"tag_name":\s*"\K@papra/app@[^"]+' | head -n1)
fetch_and_deploy_gh_release "papra" "papra-hq/papra" "tarball" "${RELEASE}" "/opt/papra"
pnpm_version=$(grep -oP '"packageManager":\s*"pnpm@\K[^"]+' /opt/papra/package.json)
NODE_VERSION="24" NODE_MODULE="pnpm@$pnpm_version" setup_nodejs
msg_info "Installing Papra (Patience)"
cd /opt/papra
$STD pnpm install --frozen-lockfile
$STD pnpm --filter "@papra/app-client..." run build
$STD pnpm --filter "@papra/app-server..." run build
ln -sf /opt/papra/apps/papra-client/dist /opt/papra/apps/papra-server/public
msg_ok "Installed Papra"
msg_info "Configuring Papra"
mkdir -p /opt/papra_data/{db,documents,ingestion}
[[ ! -f /opt/papra_data/.secret ]] && openssl rand -hex 32 >/opt/papra_data/.secret
cat <<EOF >/opt/papra/apps/papra-server/.env
NODE_ENV=production
SERVER_SERVE_PUBLIC_DIR=true
PORT=1221
DATABASE_URL=file:/opt/papra_data/db/db.sqlite
DOCUMENT_STORAGE_FILESYSTEM_ROOT=/opt/papra_data/documents
PAPRA_CONFIG_DIR=/opt/papra_data
AUTH_SECRET=$(cat /opt/papra_data/.secret)
BETTER_AUTH_SECRET=$(cat /opt/papra_data/.secret)
BETTER_AUTH_TELEMETRY=0
CLIENT_BASE_URL=http://${LOCAL_IP}:1221
SERVER_BASE_URL=http://${LOCAL_IP}:1221
EMAILS_DRY_RUN=true
INGESTION_FOLDER_IS_ENABLED=true
INGESTION_FOLDER_ROOT_PATH=/opt/papra_data/ingestion
EOF
msg_ok "Configured Papra"
msg_info "Creating Service"
cat <<EOF >/etc/systemd/system/papra.service
[Unit]
Description=Papra Document Management
After=network.target
[Service]
Type=simple
WorkingDirectory=/opt/papra/apps/papra-server
EnvironmentFile=/opt/papra/apps/papra-server/.env
ExecStartPre=/usr/bin/pnpm run migrate:up
ExecStart=/usr/bin/node dist/index.js
[Install]
WantedBy=multi-user.target
EOF
systemctl enable -q --now papra
msg_ok "Created Service"
motd_ssh
customize
cleanup_lxc

View File

@@ -41,7 +41,7 @@ $STD apt install -y \
sed -i 's/^launch=$/# launch=/' /etc/powerdns/pdns.conf
rm -f /etc/powerdns/pdns.d/bind.conf
cat <<EOF >/etc/powerdns/pdns.d/gsqlite3.conf
launch+=gsqlite3
launch=gsqlite3
gsqlite3-database=/opt/poweradmin/powerdns.db
EOF
msg_ok "Setup PowerDNS"

View File

@@ -13,10 +13,13 @@ setting_up_container
network_check
update_os
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"
fetch_and_deploy_gh_release "rustdesk-utils" "rustdesk/rustdesk-server" "binary" "latest" "/opt/rustdesk" "rustdesk-server-utils*amd64.deb"
fetch_and_deploy_gh_release "rustdesk-hbbr" "lejianwen/rustdesk-server" "binary" "latest" "/opt/rustdesk" "rustdesk-server-hbbr*amd64.deb"
fetch_and_deploy_gh_release "rustdesk-hbbs" "lejianwen/rustdesk-server" "binary" "latest" "/opt/rustdesk" "rustdesk-server-hbbs*amd64.deb"
fetch_and_deploy_gh_release "rustdesk-utils" "lejianwen/rustdesk-server" "binary" "latest" "/opt/rustdesk" "rustdesk-server-utils*amd64.deb"
fetch_and_deploy_gh_release "rustdesk-api" "lejianwen/rustdesk-api" "binary" "latest" "/opt/rustdesk" "rustdesk-api-server*amd64.deb"
systemctl enable -q --now rustdesk-hbbr
systemctl enable -q --now rustdesk-hbbs
systemctl enable -q --now rustdesk-api
motd_ssh
customize

View File

@@ -30,11 +30,12 @@ SEM_KEY=$(openssl rand -base64 32)
SEM_PW=$(openssl rand -base64 12)
cat <<EOF >/opt/semaphore/config.json
{
"bolt": {
"host": "/opt/semaphore/semaphore_db.bolt"
"sqlite": {
"host": "/opt/semaphore/database.sqlite"
},
"dialect": "sqlite",
"tmp_path": "/opt/semaphore/tmp",
"cookie_hash": "${SEM_HASH}",
"cookie_hash": "${SEM_HASH}",
"cookie_encryption": "${SEM_ENCRYPTION}",
"access_key_encryption": "${SEM_KEY}"
}

View File

@@ -1,41 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: Slaviša Arežina (tremor021)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/Suwayomi/Suwayomi-Server
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 libc++-dev
msg_ok "Installed Dependencies"
JAVA_VERSION=21 setup_java
fetch_and_deploy_gh_release "suwayomi-server" "Suwayomi/Suwayomi-Server" "binary"
msg_info "Creating Service"
cat <<EOF >/etc/systemd/system/suwayomi-server.service
[Unit]
Description=Suwayomi-Server Service
After=network.target
[Service]
ExecStart=/usr/bin/suwayomi-server
Restart=always
[Install]
WantedBy=multi-user.target
EOF
systemctl enable -q --now suwayomi-server
msg_ok "Created Service"
motd_ssh
customize
cleanup_lxc

View File

@@ -27,6 +27,8 @@ PG_VERSION="17" setup_postgresql
PG_DB_NAME="tianji_db" PG_DB_USER="tianji" setup_postgresql_db
PYTHON_VERSION="3.13" setup_uv
fetch_and_deploy_gh_release "tianji" "msgbyte/tianji" "tarball"
TIANJI_SECRET=$(openssl rand -base64 256 | tr -dc 'A-Za-z' | head -c 64)
echo "Tianji Secret: $TIANJI_SECRET" >>~/tianji.creds
msg_info "Setting up Tianji"
cd /opt/tianji

View File

@@ -24,7 +24,7 @@ msg_ok "Installed Dependencies"
setup_rust
NODE_VERSION="20" NODE_MODULE="pnpm" setup_nodejs
fetch_and_deploy_gh_release "wealthfolio" "afadil/wealthfolio" "tarball"
fetch_and_deploy_gh_release "wealthfolio" "afadil/wealthfolio" "tarball" "v3.0.3"
msg_info "Building Frontend (patience)"
cd /opt/wealthfolio
@@ -51,8 +51,8 @@ WF_DB_PATH=/opt/wealthfolio_data/wealthfolio.db
WF_SECRET_KEY=${SECRET_KEY}
WF_AUTH_PASSWORD_HASH=${WF_PASSWORD_HASH}
WF_STATIC_DIR=/opt/wealthfolio/dist
WF_CORS_ALLOW_ORIGINS=*
WF_REQUEST_TIMEOUT_MS=30000
WF_CORS_ALLOW_ORIGINS=http://${LOCAL_IP}:8080
EOF
echo "WF_PASSWORD=${WF_PASSWORD}" >~/wealthfolio.creds
msg_ok "Configured Wealthfolio"

View File

@@ -1032,8 +1032,8 @@ load_vars_file() {
local VAR_WHITELIST=(
var_apt_cacher var_apt_cacher_ip var_brg var_cpu var_disk var_fuse var_gpu var_keyctl
var_gateway var_hostname var_ipv6_method var_mac var_mknod var_mount_fs var_mtu
var_net var_nesting var_ns var_protection var_pw var_ram var_tags var_timezone var_tun var_unprivileged
var_verbose var_vlan var_ssh var_ssh_authorized_key var_container_storage var_template_storage var_searchdomain
var_net var_nesting var_ns var_os var_protection var_pw var_ram var_tags var_timezone var_tun var_unprivileged
var_verbose var_version var_vlan var_ssh var_ssh_authorized_key var_container_storage var_template_storage var_searchdomain
)
# Whitelist check helper
@@ -1214,8 +1214,8 @@ default_var_settings() {
local VAR_WHITELIST=(
var_apt_cacher var_apt_cacher_ip var_brg var_cpu var_disk var_fuse var_gpu var_keyctl
var_gateway var_hostname var_ipv6_method var_mac var_mknod var_mount_fs var_mtu
var_net var_nesting var_ns var_protection var_pw var_ram var_tags var_timezone var_tun var_unprivileged
var_verbose var_vlan var_ssh var_ssh_authorized_key var_container_storage var_template_storage
var_net var_nesting var_ns var_os var_protection var_pw var_ram var_tags var_timezone var_tun var_unprivileged
var_verbose var_version var_vlan var_ssh var_ssh_authorized_key var_container_storage var_template_storage
)
# Snapshot: environment variables (highest precedence)
@@ -1376,8 +1376,8 @@ if ! declare -p VAR_WHITELIST >/dev/null 2>&1; then
declare -ag VAR_WHITELIST=(
var_apt_cacher var_apt_cacher_ip var_brg var_cpu var_disk var_fuse var_gpu
var_gateway var_hostname var_ipv6_method var_mac var_mtu
var_net var_ns var_pw var_ram var_tags var_tun var_unprivileged
var_verbose var_vlan var_ssh var_ssh_authorized_key var_container_storage var_template_storage
var_net var_ns var_os var_pw var_ram var_tags var_tun var_unprivileged
var_verbose var_version var_vlan var_ssh var_ssh_authorized_key var_container_storage var_template_storage
)
fi
@@ -1549,6 +1549,8 @@ _build_current_app_vars_tmp() {
echo "# Generated on $(date -u '+%Y-%m-%dT%H:%M:%SZ')"
echo
echo "var_os=$(_sanitize_value "${var_os:-}")"
echo "var_version=$(_sanitize_value "${var_version:-}")"
echo "var_unprivileged=$(_sanitize_value "$_unpriv")"
echo "var_cpu=$(_sanitize_value "$_cpu")"
echo "var_ram=$(_sanitize_value "$_ram")"
@@ -3423,6 +3425,9 @@ start() {
set_std_mode
ensure_profile_loaded
get_lxc_ip
if [[ "$(dpkg --print-architecture)" == "arm64" ]] && declare -f update_script_arm64 >/dev/null 2>&1; then
update_script_arm64
fi
update_script
update_motd_ip
cleanup_lxc
@@ -3451,6 +3456,9 @@ start() {
esac
ensure_profile_loaded
get_lxc_ip
if [[ "$(dpkg --print-architecture)" == "arm64" ]] && declare -f update_script_arm64 >/dev/null 2>&1; then
update_script_arm64
fi
update_script
update_motd_ip
cleanup_lxc
@@ -4094,7 +4102,16 @@ EOF'
# that sends "configuring" status AFTER the host already reported "failed"
export CONTAINER_INSTALLING=true
lxc-attach -n "$CTID" -- bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/install/${var_install}.sh)"
local _install_script
_install_script="$(curl -fsSL "https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/install/${var_install}.sh")"
if [[ "$ARCH" == "arm64" ]]; then
local _arm_script
_arm_script="$(curl -fsSL "https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/install/arm/${var_install}.sh" 2>/dev/null || true)"
if [[ -n "$_arm_script" ]]; then
_install_script="${_arm_script}"$'\n'"${_install_script}"
fi
fi
lxc-attach -n "$CTID" -- bash -c "$_install_script"
local lxc_exit=$?
unset CONTAINER_INSTALLING
@@ -4472,7 +4489,16 @@ EOF'
# Re-run install script in existing container (don't destroy/recreate)
set +Eeuo pipefail
trap - ERR
lxc-attach -n "$CTID" -- bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/install/${var_install}.sh)"
local _install_script
_install_script="$(curl -fsSL "https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/install/${var_install}.sh")"
if [[ "$ARCH" == "arm64" ]]; then
local _arm_script
_arm_script="$(curl -fsSL "https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/install/arm/${var_install}.sh" 2>/dev/null || true)"
if [[ -n "$_arm_script" ]]; then
_install_script="${_arm_script}"$'\n'"${_install_script}"
fi
fi
lxc-attach -n "$CTID" -- bash -c "$_install_script"
local apt_retry_exit=$?
set -Eeuo pipefail
trap 'error_handler' ERR
@@ -4991,6 +5017,64 @@ create_lxc_container() {
esac
}
ARCH="$(dpkg --print-architecture)"
# Maps OS type + version to the release variant name used by ARM64 template sources.
arm64_template_variant() {
case "$1" in
debian)
case "$2" in
11 | 11.*) echo "bullseye" ;; 12 | 12.*) echo "bookworm" ;;
13 | 13.*) echo "trixie" ;; *) echo "trixie" ;;
esac ;;
alpine) echo "3.22" ;;
ubuntu)
case "$2" in
20.04* | focal) echo "focal" ;; 24.04* | noble) echo "noble" ;;
24.10* | oracular) echo "oracular" ;; *) echo "jammy" ;;
esac ;;
*) return 1 ;;
esac
}
# Downloads an ARM64 LXC rootfs template to $1.
# Debian: fetches latest release from asylumexp/debian-ifupdown2-lxc on GitHub.
# Others: fetches from jenkins.linuxcontainers.org.
download_arm64_template() {
local dest="$1" url
mkdir -p "$(dirname "$dest")" || { msg_error "Cannot create template dir."; exit 207; }
if [[ "$PCT_OSTYPE" == "debian" ]]; then
url=$(curl -fsSL "https://api.github.com/repos/asylumexp/debian-ifupdown2-lxc/releases/latest" \
| grep -Eo "https://[^\"]*debian-${CUSTOM_TEMPLATE_VARIANT}-arm64-rootfs\.tar\.xz" | head -n1)
[[ -n "$url" ]] || { msg_error "Could not find Debian ${CUSTOM_TEMPLATE_VARIANT} ARM64 template URL."; exit 207; }
else
url="https://jenkins.linuxcontainers.org/job/image-${PCT_OSTYPE}/architecture=arm64,release=${CUSTOM_TEMPLATE_VARIANT},variant=default/lastStableBuild/artifact/rootfs.tar.xz"
fi
msg_info "Downloading ${PCT_OSTYPE^} ${CUSTOM_TEMPLATE_VARIANT} ARM64 template"
if ! curl -fsSL -o "$dest" "$url"; then
msg_error "Failed to download ARM64 template from: $url"
exit 208
fi
msg_ok "Downloaded ARM64 LXC template"
}
# Architecture-aware template download wrapper.
# Optional $1 overrides destination path (for local-storage fallback).
download_template() {
local dest="${1:-$TEMPLATE_PATH}"
if [[ "$ARCH" == "arm64" ]]; then
download_arm64_template "$dest"
else
pveam download "$TEMPLATE_STORAGE" "$TEMPLATE" >>"${BUILD_LOG:-/dev/null}" 2>&1 || {
msg_error "Failed to download template '$TEMPLATE' to storage '$TEMPLATE_STORAGE'"
exit 222
}
fi
}
# ------------------------------------------------------------------------------
# Required input variables
# ------------------------------------------------------------------------------
@@ -5127,153 +5211,116 @@ create_lxc_container() {
# ------------------------------------------------------------------------------
# Template discovery & validation
# ------------------------------------------------------------------------------
TEMPLATE_SEARCH="${PCT_OSTYPE}-${PCT_OSVERSION:-}"
case "$PCT_OSTYPE" in
debian | ubuntu) TEMPLATE_PATTERN="-standard_" ;;
alpine | fedora | rocky | centos) TEMPLATE_PATTERN="-default_" ;;
*) TEMPLATE_PATTERN="" ;;
esac
CUSTOM_TEMPLATE_VARIANT=""
msg_info "Searching for template '$TEMPLATE_SEARCH'"
if [[ "$ARCH" == "arm64" ]]; then
# ARM64: use custom template download from linuxcontainers.org / GitHub
msg_info "Preparing ARM64 template"
# Initialize variables
ONLINE_TEMPLATE=""
ONLINE_TEMPLATES=()
CUSTOM_TEMPLATE_VARIANT=$(arm64_template_variant "$PCT_OSTYPE" "${PCT_OSVERSION:-}") || {
msg_error "No ARM64 template mapping for ${PCT_OSTYPE} ${PCT_OSVERSION:-latest}"
exit 207
}
# Step 1: Check local templates first (instant)
mapfile -t LOCAL_TEMPLATES < <(
pveam list "$TEMPLATE_STORAGE" 2>/dev/null |
awk -v search="${TEMPLATE_SEARCH}" -v pattern="${TEMPLATE_PATTERN}" '$1 ~ search && $1 ~ pattern {print $1}' |
sed 's|.*/||' | sort -t - -k 2 -V
)
TEMPLATE="${PCT_OSTYPE}-${CUSTOM_TEMPLATE_VARIANT}-rootfs.tar.xz"
TEMPLATE_SOURCE="custom-arm64"
# Step 2: If local template found, use it immediately (skip pveam update)
if [[ ${#LOCAL_TEMPLATES[@]} -gt 0 ]]; then
TEMPLATE="${LOCAL_TEMPLATES[-1]}"
TEMPLATE_SOURCE="local"
msg_ok "Template search completed"
else
# Step 3: No local template - need to check online (this may be slow)
msg_info "No local template found, checking online catalog..."
# Update catalog with timeout to prevent long hangs
if command -v timeout &>/dev/null; then
if ! timeout 30 pveam update >/dev/null 2>&1; then
msg_warn "Template catalog update timed out (possible network/DNS issue). Run 'pveam update' manually to diagnose."
fi
else
pveam update >/dev/null 2>&1 || msg_warn "Could not update template catalog (pveam update failed)"
# Resolve template path: pvesm → storage.cfg fallback → default
TEMPLATE_PATH="$(pvesm path "${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE}" 2>/dev/null || true)"
if [[ -z "$TEMPLATE_PATH" ]]; then
local _tpl_base
_tpl_base=$(awk -v s="$TEMPLATE_STORAGE" '$1==s {f=1} f && /path/ {print $2; exit}' /etc/pve/storage.cfg)
TEMPLATE_PATH="${_tpl_base:-/var/lib/vz}/template/cache/$TEMPLATE"
fi
# Download if missing, too small, or corrupt (single pass)
if [[ ! -f "$TEMPLATE_PATH" ]]; then
download_arm64_template "$TEMPLATE_PATH"
elif [[ "$(stat -c%s "$TEMPLATE_PATH")" -lt 1000000 ]] || ! tar -tf "$TEMPLATE_PATH" &>/dev/null; then
msg_warn "Local template invalid re-downloading."
rm -f "$TEMPLATE_PATH"
download_arm64_template "$TEMPLATE_PATH"
else
msg_ok "Template ${BL}$TEMPLATE${CL} found locally."
fi
else
TEMPLATE_SEARCH="${PCT_OSTYPE}-${PCT_OSVERSION:-}"
case "$PCT_OSTYPE" in
debian | ubuntu) TEMPLATE_PATTERN="-standard_" ;;
alpine | fedora | rocky | centos) TEMPLATE_PATTERN="-default_" ;;
*) TEMPLATE_PATTERN="" ;;
esac
msg_info "Searching for template '$TEMPLATE_SEARCH'"
# Initialize variables
ONLINE_TEMPLATE=""
ONLINE_TEMPLATES=()
mapfile -t ONLINE_TEMPLATES < <(pveam available -section system 2>/dev/null | grep -E '\.(tar\.zst|tar\.xz|tar\.gz)$' | awk '{print $2}' | grep -E "^${TEMPLATE_SEARCH}.*${TEMPLATE_PATTERN}" | sort -t - -k 2 -V 2>/dev/null || true)
[[ ${#ONLINE_TEMPLATES[@]} -gt 0 ]] && ONLINE_TEMPLATE="${ONLINE_TEMPLATES[-1]}"
TEMPLATE="$ONLINE_TEMPLATE"
TEMPLATE_SOURCE="online"
msg_ok "Template search completed"
fi
# If still no template, try to find alternatives
if [[ -z "$TEMPLATE" ]]; then
msg_warn "No template found for ${PCT_OSTYPE} ${PCT_OSVERSION}, searching for alternatives..."
# Get all available versions for this OS type
AVAILABLE_VERSIONS=()
mapfile -t AVAILABLE_VERSIONS < <(
pveam available -section system 2>/dev/null |
grep -E '\.(tar\.zst|tar\.xz|tar\.gz)$' |
awk -F'\t' '{print $1}' |
grep "^${PCT_OSTYPE}-" |
sed -E "s/.*${PCT_OSTYPE}-([0-9]+(\.[0-9]+)?).*/\1/" |
sort -u -V 2>/dev/null
# Step 1: Check local templates first (instant)
mapfile -t LOCAL_TEMPLATES < <(
pveam list "$TEMPLATE_STORAGE" 2>/dev/null |
awk -v search="${TEMPLATE_SEARCH}" -v pattern="${TEMPLATE_PATTERN}" '$1 ~ search && $1 ~ pattern {print $1}' |
sed 's|.*/||' | sort -t - -k 2 -V
)
if [[ ${#AVAILABLE_VERSIONS[@]} -gt 0 ]]; then
echo ""
echo "${BL}Available ${PCT_OSTYPE} versions:${CL}"
for i in "${!AVAILABLE_VERSIONS[@]}"; do
echo " [$((i + 1))] ${AVAILABLE_VERSIONS[$i]}"
done
echo ""
read -p "Select version [1-${#AVAILABLE_VERSIONS[@]}] or press Enter to cancel: " choice </dev/tty
# Step 2: If local template found, use it immediately (skip pveam update)
if [[ ${#LOCAL_TEMPLATES[@]} -gt 0 ]]; then
TEMPLATE="${LOCAL_TEMPLATES[-1]}"
TEMPLATE_SOURCE="local"
msg_ok "Template search completed"
else
# Step 3: No local template - need to check online (this may be slow)
msg_info "No local template found, checking online catalog..."
if [[ "$choice" =~ ^[0-9]+$ ]] && [[ "$choice" -ge 1 ]] && [[ "$choice" -le ${#AVAILABLE_VERSIONS[@]} ]]; then
PCT_OSVERSION="${AVAILABLE_VERSIONS[$((choice - 1))]}"
TEMPLATE_SEARCH="${PCT_OSTYPE}-${PCT_OSVERSION}"
ONLINE_TEMPLATES=()
mapfile -t ONLINE_TEMPLATES < <(
pveam available -section system 2>/dev/null |
grep -E '\.(tar\.zst|tar\.xz|tar\.gz)$' |
awk '{print $2}' |
grep -E "^${TEMPLATE_SEARCH}-.*${TEMPLATE_PATTERN}" |
sort -t - -k 2 -V 2>/dev/null || true
)
if [[ ${#ONLINE_TEMPLATES[@]} -gt 0 ]]; then
TEMPLATE="${ONLINE_TEMPLATES[-1]}"
TEMPLATE_SOURCE="online"
else
msg_error "No templates available for ${PCT_OSTYPE} ${PCT_OSVERSION}"
exit 225
# Update catalog with timeout to prevent long hangs
if command -v timeout &>/dev/null; then
if ! timeout 30 pveam update >/dev/null 2>&1; then
msg_warn "Template catalog update timed out (possible network/DNS issue). Run 'pveam update' manually to diagnose."
fi
else
msg_custom "🚫" "${YW}" "Installation cancelled"
exit 0
pveam update >/dev/null 2>&1 || msg_warn "Could not update template catalog (pveam update failed)"
fi
else
msg_error "No ${PCT_OSTYPE} templates available at all"
exit 225
ONLINE_TEMPLATES=()
mapfile -t ONLINE_TEMPLATES < <(pveam available -section system 2>/dev/null | grep -E '\.(tar\.zst|tar\.xz|tar\.gz)$' | awk '{print $2}' | grep -E "^${TEMPLATE_SEARCH}.*${TEMPLATE_PATTERN}" | sort -t - -k 2 -V 2>/dev/null || true)
[[ ${#ONLINE_TEMPLATES[@]} -gt 0 ]] && ONLINE_TEMPLATE="${ONLINE_TEMPLATES[-1]}"
TEMPLATE="$ONLINE_TEMPLATE"
TEMPLATE_SOURCE="online"
msg_ok "Template search completed"
fi
fi
TEMPLATE_PATH="$(pvesm path $TEMPLATE_STORAGE:vztmpl/$TEMPLATE 2>/dev/null || true)"
if [[ -z "$TEMPLATE_PATH" ]]; then
TEMPLATE_BASE=$(awk -v s="$TEMPLATE_STORAGE" '$1==s {f=1} f && /path/ {print $2; exit}' /etc/pve/storage.cfg)
[[ -n "$TEMPLATE_BASE" ]] && TEMPLATE_PATH="$TEMPLATE_BASE/template/cache/$TEMPLATE"
fi
# If we still don't have a path but have a valid template name, construct it
if [[ -z "$TEMPLATE_PATH" && -n "$TEMPLATE" ]]; then
TEMPLATE_PATH="/var/lib/vz/template/cache/$TEMPLATE"
fi
[[ -n "$TEMPLATE_PATH" ]] || {
# If still no template, try to find alternatives
if [[ -z "$TEMPLATE" ]]; then
msg_error "Template ${PCT_OSTYPE} ${PCT_OSVERSION} not available"
msg_warn "No template found for ${PCT_OSTYPE} ${PCT_OSVERSION}, searching for alternatives..."
# Get available versions
# Get all available versions for this OS type
AVAILABLE_VERSIONS=()
mapfile -t AVAILABLE_VERSIONS < <(
pveam available -section system 2>/dev/null |
grep -E '\.(tar\.zst|tar\.xz|tar\.gz)$' |
awk -F'\t' '{print $1}' |
grep "^${PCT_OSTYPE}-" |
sed -E 's/.*'"${PCT_OSTYPE}"'-([0-9]+\.[0-9]+).*/\1/' |
grep -E '^[0-9]+\.[0-9]+$' |
sort -u -V 2>/dev/null || sort -u
sed -E "s/.*${PCT_OSTYPE}-([0-9]+(\.[0-9]+)?).*/\1/" |
sort -u -V 2>/dev/null
)
if [[ ${#AVAILABLE_VERSIONS[@]} -gt 0 ]]; then
echo -e "\n${BL}Available versions:${CL}"
echo ""
echo "${BL}Available ${PCT_OSTYPE} versions:${CL}"
for i in "${!AVAILABLE_VERSIONS[@]}"; do
echo " [$((i + 1))] ${AVAILABLE_VERSIONS[$i]}"
done
echo ""
read -p "Select version [1-${#AVAILABLE_VERSIONS[@]}] or Enter to exit: " choice </dev/tty
read -p "Select version [1-${#AVAILABLE_VERSIONS[@]}] or press Enter to cancel: " choice </dev/tty
if [[ "$choice" =~ ^[0-9]+$ ]] && [[ "$choice" -ge 1 ]] && [[ "$choice" -le ${#AVAILABLE_VERSIONS[@]} ]]; then
export var_version="${AVAILABLE_VERSIONS[$((choice - 1))]}"
export PCT_OSVERSION="$var_version"
msg_ok "Switched to ${PCT_OSTYPE} ${var_version}"
PCT_OSVERSION="${AVAILABLE_VERSIONS[$((choice - 1))]}"
TEMPLATE_SEARCH="${PCT_OSTYPE}-${PCT_OSVERSION}"
# Retry template search with new version
TEMPLATE_SEARCH="${PCT_OSTYPE}-${PCT_OSVERSION:-}"
mapfile -t LOCAL_TEMPLATES < <(
pveam list "$TEMPLATE_STORAGE" 2>/dev/null |
awk -v search="${TEMPLATE_SEARCH}-" -v pattern="${TEMPLATE_PATTERN}" '$1 ~ search && $1 ~ pattern {print $1}' |
sed 's|.*/||' | sort -t - -k 2 -V
)
ONLINE_TEMPLATES=()
mapfile -t ONLINE_TEMPLATES < <(
pveam available -section system 2>/dev/null |
grep -E '\.(tar\.zst|tar\.xz|tar\.gz)$' |
@@ -5281,109 +5328,181 @@ create_lxc_container() {
grep -E "^${TEMPLATE_SEARCH}-.*${TEMPLATE_PATTERN}" |
sort -t - -k 2 -V 2>/dev/null || true
)
ONLINE_TEMPLATE=""
[[ ${#ONLINE_TEMPLATES[@]} -gt 0 ]] && ONLINE_TEMPLATE="${ONLINE_TEMPLATES[-1]}"
if [[ ${#LOCAL_TEMPLATES[@]} -gt 0 ]]; then
TEMPLATE="${LOCAL_TEMPLATES[-1]}"
TEMPLATE_SOURCE="local"
else
TEMPLATE="$ONLINE_TEMPLATE"
if [[ ${#ONLINE_TEMPLATES[@]} -gt 0 ]]; then
TEMPLATE="${ONLINE_TEMPLATES[-1]}"
TEMPLATE_SOURCE="online"
else
msg_error "No templates available for ${PCT_OSTYPE} ${PCT_OSVERSION}"
exit 225
fi
TEMPLATE_PATH="$(pvesm path $TEMPLATE_STORAGE:vztmpl/$TEMPLATE 2>/dev/null || true)"
if [[ -z "$TEMPLATE_PATH" ]]; then
TEMPLATE_BASE=$(awk -v s="$TEMPLATE_STORAGE" '$1==s {f=1} f && /path/ {print $2; exit}' /etc/pve/storage.cfg)
[[ -n "$TEMPLATE_BASE" ]] && TEMPLATE_PATH="$TEMPLATE_BASE/template/cache/$TEMPLATE"
fi
# If we still don't have a path but have a valid template name, construct it
if [[ -z "$TEMPLATE_PATH" && -n "$TEMPLATE" ]]; then
TEMPLATE_PATH="/var/lib/vz/template/cache/$TEMPLATE"
fi
[[ -n "$TEMPLATE_PATH" ]] || {
msg_error "Template still not found after version change"
exit 220
}
else
msg_custom "🚫" "${YW}" "Installation cancelled"
exit 0
fi
else
msg_error "No ${PCT_OSTYPE} templates available"
exit 220
msg_error "No ${PCT_OSTYPE} templates available at all"
exit 225
fi
fi
}
# Validate that we found a template
if [[ -z "$TEMPLATE" ]]; then
msg_error "No template found for ${PCT_OSTYPE} ${PCT_OSVERSION}"
msg_custom "" "${YW}" "Please check:"
msg_custom " •" "${YW}" "Is pveam catalog available? (run: pveam available -section system)"
msg_custom " •" "${YW}" "Does the template exist for your OS version?"
exit 225
fi
msg_ok "Template ${BL}$TEMPLATE${CL} [$TEMPLATE_SOURCE]"
msg_debug "Resolved TEMPLATE_PATH=$TEMPLATE_PATH"
NEED_DOWNLOAD=0
if [[ ! -f "$TEMPLATE_PATH" ]]; then
msg_info "Template not present locally will download."
NEED_DOWNLOAD=1
elif [[ ! -r "$TEMPLATE_PATH" ]]; then
msg_error "Template file exists but is not readable check permissions."
exit 221
elif [[ "$(stat -c%s "$TEMPLATE_PATH")" -lt 1000000 ]]; then
if [[ -n "$ONLINE_TEMPLATE" ]]; then
msg_warn "Template file too small (<1MB) re-downloading."
NEED_DOWNLOAD=1
else
msg_warn "Template looks too small, but no online version exists. Keeping local file."
TEMPLATE_PATH="$(pvesm path $TEMPLATE_STORAGE:vztmpl/$TEMPLATE 2>/dev/null || true)"
if [[ -z "$TEMPLATE_PATH" ]]; then
TEMPLATE_BASE=$(awk -v s="$TEMPLATE_STORAGE" '$1==s {f=1} f && /path/ {print $2; exit}' /etc/pve/storage.cfg)
[[ -n "$TEMPLATE_BASE" ]] && TEMPLATE_PATH="$TEMPLATE_BASE/template/cache/$TEMPLATE"
fi
elif ! tar -tf "$TEMPLATE_PATH" &>/dev/null; then
if [[ -n "$ONLINE_TEMPLATE" ]]; then
msg_warn "Template appears corrupted re-downloading."
NEED_DOWNLOAD=1
else
msg_warn "Template appears corrupted, but no online version exists. Keeping local file."
fi
else
$STD msg_ok "Template $TEMPLATE is present and valid."
fi
if [[ "$TEMPLATE_SOURCE" == "local" && -n "$ONLINE_TEMPLATE" && "$TEMPLATE" != "$ONLINE_TEMPLATE" ]]; then
msg_warn "Local template is outdated: $TEMPLATE (latest available: $ONLINE_TEMPLATE)"
if whiptail --yesno "A newer template is available:\n$ONLINE_TEMPLATE\n\nDo you want to download and use it instead?" 12 70; then
TEMPLATE="$ONLINE_TEMPLATE"
NEED_DOWNLOAD=1
else
msg_custom "" "${BL}" "Continuing with local template $TEMPLATE"
# If we still don't have a path but have a valid template name, construct it
if [[ -z "$TEMPLATE_PATH" && -n "$TEMPLATE" ]]; then
TEMPLATE_PATH="/var/lib/vz/template/cache/$TEMPLATE"
fi
fi
if [[ "$NEED_DOWNLOAD" -eq 1 ]]; then
[[ -f "$TEMPLATE_PATH" ]] && rm -f "$TEMPLATE_PATH"
for attempt in {1..3}; do
msg_info "Attempt $attempt: Downloading template $TEMPLATE to $TEMPLATE_STORAGE"
if pveam download "$TEMPLATE_STORAGE" "$TEMPLATE" >>"${BUILD_LOG:-/dev/null}" 2>&1; then
msg_ok "Template download successful."
break
[[ -n "$TEMPLATE_PATH" ]] || {
if [[ -z "$TEMPLATE" ]]; then
msg_error "Template ${PCT_OSTYPE} ${PCT_OSVERSION} not available"
# Get available versions
mapfile -t AVAILABLE_VERSIONS < <(
pveam available -section system 2>/dev/null |
grep "^${PCT_OSTYPE}-" |
sed -E 's/.*'"${PCT_OSTYPE}"'-([0-9]+\.[0-9]+).*/\1/' |
grep -E '^[0-9]+\.[0-9]+$' |
sort -u -V 2>/dev/null || sort -u
)
if [[ ${#AVAILABLE_VERSIONS[@]} -gt 0 ]]; then
echo -e "\n${BL}Available versions:${CL}"
for i in "${!AVAILABLE_VERSIONS[@]}"; do
echo " [$((i + 1))] ${AVAILABLE_VERSIONS[$i]}"
done
echo ""
read -p "Select version [1-${#AVAILABLE_VERSIONS[@]}] or Enter to exit: " choice </dev/tty
if [[ "$choice" =~ ^[0-9]+$ ]] && [[ "$choice" -ge 1 ]] && [[ "$choice" -le ${#AVAILABLE_VERSIONS[@]} ]]; then
export var_version="${AVAILABLE_VERSIONS[$((choice - 1))]}"
export PCT_OSVERSION="$var_version"
msg_ok "Switched to ${PCT_OSTYPE} ${var_version}"
# Retry template search with new version
TEMPLATE_SEARCH="${PCT_OSTYPE}-${PCT_OSVERSION:-}"
mapfile -t LOCAL_TEMPLATES < <(
pveam list "$TEMPLATE_STORAGE" 2>/dev/null |
awk -v search="${TEMPLATE_SEARCH}-" -v pattern="${TEMPLATE_PATTERN}" '$1 ~ search && $1 ~ pattern {print $1}' |
sed 's|.*/||' | sort -t - -k 2 -V
)
mapfile -t ONLINE_TEMPLATES < <(
pveam available -section system 2>/dev/null |
grep -E '\.(tar\.zst|tar\.xz|tar\.gz)$' |
awk '{print $2}' |
grep -E "^${TEMPLATE_SEARCH}-.*${TEMPLATE_PATTERN}" |
sort -t - -k 2 -V 2>/dev/null || true
)
ONLINE_TEMPLATE=""
[[ ${#ONLINE_TEMPLATES[@]} -gt 0 ]] && ONLINE_TEMPLATE="${ONLINE_TEMPLATES[-1]}"
if [[ ${#LOCAL_TEMPLATES[@]} -gt 0 ]]; then
TEMPLATE="${LOCAL_TEMPLATES[-1]}"
TEMPLATE_SOURCE="local"
else
TEMPLATE="$ONLINE_TEMPLATE"
TEMPLATE_SOURCE="online"
fi
TEMPLATE_PATH="$(pvesm path $TEMPLATE_STORAGE:vztmpl/$TEMPLATE 2>/dev/null || true)"
if [[ -z "$TEMPLATE_PATH" ]]; then
TEMPLATE_BASE=$(awk -v s="$TEMPLATE_STORAGE" '$1==s {f=1} f && /path/ {print $2; exit}' /etc/pve/storage.cfg)
[[ -n "$TEMPLATE_BASE" ]] && TEMPLATE_PATH="$TEMPLATE_BASE/template/cache/$TEMPLATE"
fi
# If we still don't have a path but have a valid template name, construct it
if [[ -z "$TEMPLATE_PATH" && -n "$TEMPLATE" ]]; then
TEMPLATE_PATH="/var/lib/vz/template/cache/$TEMPLATE"
fi
[[ -n "$TEMPLATE_PATH" ]] || {
msg_error "Template still not found after version change"
exit 220
}
else
msg_custom "🚫" "${YW}" "Installation cancelled"
exit 0
fi
else
msg_error "No ${PCT_OSTYPE} templates available"
exit 220
fi
fi
if [[ $attempt -eq 3 ]]; then
msg_error "Failed after 3 attempts. Please check network access, permissions, or manually run:\n pveam download $TEMPLATE_STORAGE $TEMPLATE"
exit 222
fi
sleep $((attempt * 5))
done
fi
}
if ! pveam list "$TEMPLATE_STORAGE" 2>/dev/null | grep -q "$TEMPLATE"; then
msg_error "Template $TEMPLATE not available in storage $TEMPLATE_STORAGE after download."
exit 223
# Validate that we found a template
if [[ -z "$TEMPLATE" ]]; then
msg_error "No template found for ${PCT_OSTYPE} ${PCT_OSVERSION}"
msg_custom "" "${YW}" "Please check:"
msg_custom " •" "${YW}" "Is pveam catalog available? (run: pveam available -section system)"
msg_custom " •" "${YW}" "Does the template exist for your OS version?"
exit 225
fi
msg_ok "Template ${BL}$TEMPLATE${CL} [$TEMPLATE_SOURCE]"
msg_debug "Resolved TEMPLATE_PATH=$TEMPLATE_PATH"
NEED_DOWNLOAD=0
if [[ ! -f "$TEMPLATE_PATH" ]]; then
msg_info "Template not present locally will download."
NEED_DOWNLOAD=1
elif [[ ! -r "$TEMPLATE_PATH" ]]; then
msg_error "Template file exists but is not readable check permissions."
exit 221
elif [[ "$(stat -c%s "$TEMPLATE_PATH")" -lt 1000000 ]]; then
if [[ -n "$ONLINE_TEMPLATE" ]]; then
msg_warn "Template file too small (<1MB) re-downloading."
NEED_DOWNLOAD=1
else
msg_warn "Template looks too small, but no online version exists. Keeping local file."
fi
elif ! tar -tf "$TEMPLATE_PATH" &>/dev/null; then
if [[ -n "$ONLINE_TEMPLATE" ]]; then
msg_warn "Template appears corrupted re-downloading."
NEED_DOWNLOAD=1
else
msg_warn "Template appears corrupted, but no online version exists. Keeping local file."
fi
else
$STD msg_ok "Template $TEMPLATE is present and valid."
fi
if [[ "$TEMPLATE_SOURCE" == "local" && -n "$ONLINE_TEMPLATE" && "$TEMPLATE" != "$ONLINE_TEMPLATE" ]]; then
msg_warn "Local template is outdated: $TEMPLATE (latest available: $ONLINE_TEMPLATE)"
if whiptail --yesno "A newer template is available:\n$ONLINE_TEMPLATE\n\nDo you want to download and use it instead?" 12 70; then
TEMPLATE="$ONLINE_TEMPLATE"
NEED_DOWNLOAD=1
else
msg_custom "" "${BL}" "Continuing with local template $TEMPLATE"
fi
fi
if [[ "$NEED_DOWNLOAD" -eq 1 ]]; then
[[ -f "$TEMPLATE_PATH" ]] && rm -f "$TEMPLATE_PATH"
for attempt in {1..3}; do
msg_info "Attempt $attempt: Downloading template $TEMPLATE to $TEMPLATE_STORAGE"
if pveam download "$TEMPLATE_STORAGE" "$TEMPLATE" >>"${BUILD_LOG:-/dev/null}" 2>&1; then
msg_ok "Template download successful."
break
fi
if [[ $attempt -eq 3 ]]; then
msg_error "Failed after 3 attempts. Please check network access, permissions, or manually run:\n pveam download $TEMPLATE_STORAGE $TEMPLATE"
exit 222
fi
sleep $((attempt * 5))
done
fi
if ! pveam list "$TEMPLATE_STORAGE" 2>/dev/null | grep -q "$TEMPLATE"; then
msg_error "Template $TEMPLATE not available in storage $TEMPLATE_STORAGE after download."
exit 223
fi
fi
# ------------------------------------------------------------------------------
@@ -5462,19 +5581,13 @@ create_lxc_container() {
if [[ ! -s "$TEMPLATE_PATH" || "$(stat -c%s "$TEMPLATE_PATH" 2>/dev/null || echo 0)" -lt 1000000 ]]; then
msg_info "Template file missing or too small downloading"
rm -f "$TEMPLATE_PATH"
pveam download "$TEMPLATE_STORAGE" "$TEMPLATE" >>"${BUILD_LOG:-/dev/null}" 2>&1 || {
msg_error "Failed to download template '$TEMPLATE' to storage '$TEMPLATE_STORAGE'"
exit 222
}
download_template
msg_ok "Template downloaded"
elif ! tar -tf "$TEMPLATE_PATH" &>/dev/null; then
if [[ -n "$ONLINE_TEMPLATE" ]]; then
if [[ "$ARCH" == "arm64" || -n "$ONLINE_TEMPLATE" ]]; then
msg_info "Template appears corrupted re-downloading"
rm -f "$TEMPLATE_PATH"
pveam download "$TEMPLATE_STORAGE" "$TEMPLATE" >>"${BUILD_LOG:-/dev/null}" 2>&1 || {
msg_error "Failed to re-download template '$TEMPLATE'"
exit 222
}
download_template
msg_ok "Template re-downloaded"
else
msg_warn "Template appears corrupted, but no online version exists. Skipping re-download."
@@ -5495,7 +5608,7 @@ create_lxc_container() {
if grep -qiE 'unable to open|corrupt|invalid' "$LOGFILE"; then
msg_info "Template may be corrupted re-downloading"
rm -f "$TEMPLATE_PATH"
pveam download "$TEMPLATE_STORAGE" "$TEMPLATE" >>"${BUILD_LOG:-/dev/null}" 2>&1
download_template
msg_ok "Template re-downloaded"
fi
@@ -5508,7 +5621,11 @@ create_lxc_container() {
if [[ ! -f "$LOCAL_TEMPLATE_PATH" ]]; then
msg_ok "Trying local storage fallback"
msg_info "Downloading template to local"
pveam download local "$TEMPLATE" >>"${BUILD_LOG:-/dev/null}" 2>&1
if [[ "$ARCH" == "arm64" ]]; then
download_arm64_template "$LOCAL_TEMPLATE_PATH"
else
pveam download local "$TEMPLATE" >>"${BUILD_LOG:-/dev/null}" 2>&1
fi
msg_ok "Template downloaded to local"
else
msg_ok "Trying local storage fallback"
@@ -5644,15 +5761,15 @@ description() {
<span style='margin: 0 10px;'>
<i class="fa fa-github fa-fw" style="color: #f5f5f5;"></i>
<a href='https://github.com/community-scripts/ProxmoxVE' target='_blank' rel='noopener noreferrer' style='text-decoration: none; color: #00617f;'>GitHub</a>
<a href='https://github.com/community-scripts/ProxmoxVED' target='_blank' rel='noopener noreferrer' style='text-decoration: none; color: #00617f;'>GitHub</a>
</span>
<span style='margin: 0 10px;'>
<i class="fa fa-comments fa-fw" style="color: #f5f5f5;"></i>
<a href='https://github.com/community-scripts/ProxmoxVE/discussions' target='_blank' rel='noopener noreferrer' style='text-decoration: none; color: #00617f;'>Discussions</a>
<a href='https://github.com/community-scripts/ProxmoxVED/discussions' target='_blank' rel='noopener noreferrer' style='text-decoration: none; color: #00617f;'>Discussions</a>
</span>
<span style='margin: 0 10px;'>
<i class="fa fa-exclamation-circle fa-fw" style="color: #f5f5f5;"></i>
<a href='https://github.com/community-scripts/ProxmoxVE/issues' target='_blank' rel='noopener noreferrer' style='text-decoration: none; color: #00617f;'>Issues</a>
<a href='https://github.com/community-scripts/ProxmoxVED/issues' target='_blank' rel='noopener noreferrer' style='text-decoration: none; color: #00617f;'>Issues</a>
</span>
</div>
EOF

View File

@@ -344,9 +344,10 @@ pve_check() {
# - Provides link to ARM64-compatible scripts
# ------------------------------------------------------------------------------
arch_check() {
if [ "$(dpkg --print-architecture)" != "amd64" ]; then
msg_error "This script will not work with PiMox (ARM architecture detected)."
msg_warn "Visit https://github.com/asylumexp/Proxmox for ARM64 support."
local arch
arch="$(dpkg --print-architecture)"
if [[ "$arch" != "amd64" && "$arch" != "arm64" ]]; then
msg_error "This script requires amd64 or arm64 (detected: $arch)."
sleep 2
exit 106
fi

View File

@@ -235,6 +235,7 @@ EOF
fi
apt_update_safe
$STD apt-get -o Dpkg::Options::="--force-confold" -y dist-upgrade
$STD apt-get install -y sudo curl mc gnupg2 openssh-server wget gcc
rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED
msg_ok "Updated Container OS"
post_progress_to_api

View File

@@ -2735,10 +2735,13 @@ function fetch_and_deploy_codeberg_release() {
# Fall back to architecture heuristic
if [[ -z "$url_match" ]]; then
for u in $assets; do
if [[ "$u" =~ ($arch|amd64|x86_64|aarch64|arm64).*\.deb$ ]]; then
url_match="$u"
break
if [[ "${arch,,}" =~ ^(amd64|x86_64)$ ]]; then
[[ "$u" =~ (amd64|x86_64).*\.deb$ ]] || continue
elif [[ "${arch,,}" =~ ^(arm64|aarch64)$ ]]; then
[[ "$u" =~ (arm64|aarch64).*\.deb$ ]] || continue
fi
url_match="$u"
break
done
fi
@@ -3035,7 +3038,11 @@ _gh_scan_older_releases() {
done)
fi
if [[ "$has_match" != "true" ]]; then
has_match=$(echo "$releases_list" | jq -r ".[$i].assets[].browser_download_url" | grep -qE "($arch|amd64|x86_64|aarch64|arm64).*\.deb$" && echo true)
if [[ "${arch,,}" =~ ^(amd64|x86_64)$ ]]; then
has_match=$(echo "$releases_list" | jq -r ".[$i].assets[].browser_download_url" | grep -qE '(amd64|x86_64).*\.deb$' && echo true)
elif [[ "${arch,,}" =~ ^(arm64|aarch64)$ ]]; then
has_match=$(echo "$releases_list" | jq -r ".[$i].assets[].browser_download_url" | grep -qE '(arm64|aarch64).*\.deb$' && echo true)
fi
fi
if [[ "$has_match" != "true" ]]; then
has_match=$(echo "$releases_list" | jq -r ".[$i].assets[].browser_download_url" | grep -qE '\.deb$' && echo true)
@@ -3233,10 +3240,13 @@ function fetch_and_deploy_gh_release() {
# If no match via explicit pattern, fall back to architecture heuristic
if [[ -z "$url_match" ]]; then
for u in $assets; do
if [[ "$u" =~ ($arch|amd64|x86_64|aarch64|arm64).*\.deb$ ]]; then
url_match="$u"
break
if [[ "${arch,,}" =~ ^(amd64|x86_64)$ ]]; then
[[ "$u" =~ (amd64|x86_64).*\.deb$ ]] || continue
elif [[ "${arch,,}" =~ ^(arm64|aarch64)$ ]]; then
[[ "$u" =~ (arm64|aarch64).*\.deb$ ]] || continue
fi
url_match="$u"
break
done
fi
@@ -3267,10 +3277,13 @@ function fetch_and_deploy_gh_release() {
fi
if [[ -z "$url_match" ]]; then
for u in $assets; do
if [[ "$u" =~ ($arch|amd64|x86_64|aarch64|arm64).*\.deb$ ]]; then
url_match="$u"
break
if [[ "${arch,,}" =~ ^(amd64|x86_64)$ ]]; then
[[ "$u" =~ (amd64|x86_64).*\.deb$ ]] || continue
elif [[ "${arch,,}" =~ ^(arm64|aarch64)$ ]]; then
[[ "$u" =~ (arm64|aarch64).*\.deb$ ]] || continue
fi
url_match="$u"
break
done
fi
if [[ -z "$url_match" ]]; then
@@ -7999,7 +8012,7 @@ EOF
# ------------------------------------------------------------------------------
function fetch_and_deploy_from_url() {
local url="$1"
local directory="$2"
local directory="${2:-}"
if [[ -z "$url" ]]; then
msg_error "URL parameter is required"