mirror of
https://github.com/community-scripts/ProxmoxVE.git
synced 2026-02-21 04:25:56 +01:00
Compare commits
9 Commits
add-script
...
feature/ex
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e7aa04b838 | ||
|
|
f39024c930 | ||
|
|
33884f6228 | ||
|
|
c4449aa041 | ||
|
|
476b50b4e2 | ||
|
|
fac5c5ebf6 | ||
|
|
61e535d3ec | ||
|
|
6989d98214 | ||
|
|
ce5b7986ac |
19
CHANGELOG.md
19
CHANGELOG.md
@@ -404,20 +404,6 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
|
||||
|
||||
</details>
|
||||
|
||||
## 2026-02-18
|
||||
|
||||
### 🚀 Updated Scripts
|
||||
|
||||
- #### 💥 Breaking Changes
|
||||
|
||||
- [Fix] PatchMon: use `SERVER_PORT` in Nginx config if set in env [@vhsdream](https://github.com/vhsdream) ([#12053](https://github.com/community-scripts/ProxmoxVE/pull/12053))
|
||||
|
||||
### 💾 Core
|
||||
|
||||
- #### ✨ New Features
|
||||
|
||||
- core: Execution ID & Telemetry Improvements [@MickLesk](https://github.com/MickLesk) ([#12041](https://github.com/community-scripts/ProxmoxVE/pull/12041))
|
||||
|
||||
## 2026-02-17
|
||||
|
||||
### 🆕 New Scripts
|
||||
@@ -428,7 +414,6 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
|
||||
|
||||
- #### 🐞 Bug Fixes
|
||||
|
||||
- [Hotfix] Cleanuparr: backup config before update [@vhsdream](https://github.com/vhsdream) ([#12039](https://github.com/community-scripts/ProxmoxVE/pull/12039))
|
||||
- fix: pterodactyl-panel add symlink [@CrazyWolf13](https://github.com/CrazyWolf13) ([#11997](https://github.com/community-scripts/ProxmoxVE/pull/11997))
|
||||
|
||||
### 💾 Core
|
||||
@@ -452,10 +437,6 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
|
||||
|
||||
- Immich Public Proxy: centralize and fix systemd service creation [@MickLesk](https://github.com/MickLesk) ([#12025](https://github.com/community-scripts/ProxmoxVE/pull/12025))
|
||||
|
||||
### 📚 Documentation
|
||||
|
||||
- fix contribution/setup-fork [@andreasabeck](https://github.com/andreasabeck) ([#12047](https://github.com/community-scripts/ProxmoxVE/pull/12047))
|
||||
|
||||
## 2026-02-16
|
||||
|
||||
### 🆕 New Scripts
|
||||
|
||||
@@ -32,17 +32,8 @@ function update_script() {
|
||||
systemctl stop cleanuparr
|
||||
msg_ok "Stopped Service"
|
||||
|
||||
msg_info "Backing up config"
|
||||
cp -r /opt/cleanuparr/config /opt/cleanuparr_config_backup
|
||||
msg_ok "Backed up config"
|
||||
|
||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "Cleanuparr" "Cleanuparr/Cleanuparr" "prebuild" "latest" "/opt/cleanuparr" "*linux-amd64.zip"
|
||||
|
||||
msg_info "Restoring config"
|
||||
[[ -d /opt/cleanuparr/config ]] && rm -rf /opt/cleanuparr/config
|
||||
mv /opt/cleanuparr_config_backup /opt/cleanuparr/config
|
||||
msg_ok "Restored config"
|
||||
|
||||
msg_info "Starting Service"
|
||||
systemctl start cleanuparr
|
||||
msg_ok "Started Service"
|
||||
|
||||
@@ -46,7 +46,6 @@ function update_script() {
|
||||
VERSION=$(get_latest_github_release "PatchMon/PatchMon")
|
||||
PROTO="$(sed -n '/SERVER_PROTOCOL/s/[^=]*=//p' /opt/backend.env)"
|
||||
HOST="$(sed -n '/SERVER_HOST/s/[^=]*=//p' /opt/backend.env)"
|
||||
SERVER_PORT="$(sed -n '/SERVER_PORT/s/[^=]*=//p' /opt/backend.env)"
|
||||
[[ "${PROTO:-http}" == "http" ]] && PORT=":3001"
|
||||
sed -i 's/PORT=3399/PORT=3001/' /opt/backend.env
|
||||
sed -i -e "s/VERSION=.*/VERSION=$VERSION/" \
|
||||
@@ -67,9 +66,6 @@ function update_script() {
|
||||
-e '\|try_files |i\ root /opt/patchmon/frontend/dist;' \
|
||||
-e 's|alias.*|alias /opt/patchmon/frontend/dist/assets;|' \
|
||||
-e '\|expires 1y|i\ root /opt/patchmon/frontend/dist;' /etc/nginx/sites-available/patchmon.conf
|
||||
if [[ -n "$SERVER_PORT" ]] && [[ "$SERVER_PORT" != "443" ]]; then
|
||||
sed -i "s/listen [[:digit:]]/listen ${SERVER_PORT};/" /etc/nginx/sites-available/patchmon.conf
|
||||
fi
|
||||
ln -sf /etc/nginx/sites-available/patchmon.conf /etc/nginx/sites-enabled/
|
||||
rm -f /etc/nginx/sites-enabled/default
|
||||
$STD nginx -t
|
||||
|
||||
@@ -134,7 +134,7 @@ update_links() {
|
||||
# Find all files containing the old repo reference
|
||||
while IFS= read -r file; do
|
||||
# Count occurrences
|
||||
local count=$(grep -E -c "(github.com|githubusercontent.com)/$old_repo/$old_name" "$file" 2>/dev/null || echo 0)
|
||||
local count=$(grep -c "github.com/$old_repo/$old_name" "$file" 2>/dev/null || echo 0)
|
||||
|
||||
if [[ $count -gt 0 ]]; then
|
||||
# Backup original
|
||||
@@ -143,16 +143,16 @@ update_links() {
|
||||
# Replace links - use different sed syntax for BSD/macOS vs GNU sed
|
||||
if sed --version &>/dev/null 2>&1; then
|
||||
# GNU sed
|
||||
sed -E -i "s@(github.com|githubusercontent.com)/$old_repo/$old_name@\\1/$new_owner/$new_repo@g" "$file"
|
||||
sed -i "s|github.com/$old_repo/$old_name|github.com/$new_owner/$new_repo|g" "$file"
|
||||
else
|
||||
# BSD sed (macOS)
|
||||
sed -E -i '' "s@(github.com|githubusercontent.com)/$old_repo/$old_name@\\1/$new_owner/$new_repo@g" "$file"
|
||||
sed -i '' "s|github.com/$old_repo/$old_name|github.com/$new_owner/$new_repo|g" "$file"
|
||||
fi
|
||||
|
||||
((files_updated++))
|
||||
print_success "Updated $file ($count links)"
|
||||
fi
|
||||
done < <(find "$search_path" -type f \( -name "*.md" -o -name "*.sh" -o -name "*.func" -o -name "*.json" \) -not -path "*/.git/*" 2>/dev/null | xargs grep -E -l "(github.com|githubusercontent.com)/$old_repo/$old_name" 2>/dev/null)
|
||||
done < <(find "$search_path" -type f \( -name "*.md" -o -name "*.sh" -o -name "*.func" -o -name "*.json" \) -not -path "*/.git/*" 2>/dev/null | xargs grep -l "github.com/$old_repo/$old_name" 2>/dev/null)
|
||||
|
||||
return $files_updated
|
||||
}
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
{
|
||||
"name": "CronMaster",
|
||||
"slug": "cronmaster",
|
||||
"categories": [
|
||||
1
|
||||
],
|
||||
"date_created": "2026-02-17",
|
||||
"type": "pve",
|
||||
"updateable": true,
|
||||
"privileged": false,
|
||||
"interface_port": 3000,
|
||||
"documentation": "https://github.com/fccview/cronmaster",
|
||||
"website": "https://github.com/fccview/cronmaster",
|
||||
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/cr-nmaster.webp",
|
||||
"config_path": "/opt/cronmaster/.env",
|
||||
"description": "Self-hosted cron job scheduler with web UI, live logs, auth and prebuilt binaries provided upstream.",
|
||||
"install_methods": [
|
||||
{
|
||||
"type": "default",
|
||||
"script": "tools/addon/cronmaster.sh",
|
||||
"resources": {
|
||||
"cpu": null,
|
||||
"ram": null,
|
||||
"hdd": null,
|
||||
"os": null,
|
||||
"version": null
|
||||
}
|
||||
}
|
||||
],
|
||||
"default_credentials": {
|
||||
"username": null,
|
||||
"password": null
|
||||
},
|
||||
"notes": []
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"generated": "2026-02-18T12:13:31Z",
|
||||
"generated": "2026-02-17T12:14:18Z",
|
||||
"versions": [
|
||||
{
|
||||
"slug": "2fauth",
|
||||
@@ -158,9 +158,9 @@
|
||||
{
|
||||
"slug": "bookstack",
|
||||
"repo": "BookStackApp/BookStack",
|
||||
"version": "v25.12.5",
|
||||
"version": "v25.12.4",
|
||||
"pinned": false,
|
||||
"date": "2026-02-17T18:42:47Z"
|
||||
"date": "2026-02-17T11:44:48Z"
|
||||
},
|
||||
{
|
||||
"slug": "byparr",
|
||||
@@ -207,9 +207,9 @@
|
||||
{
|
||||
"slug": "comfyui",
|
||||
"repo": "comfyanonymous/ComfyUI",
|
||||
"version": "v0.14.2",
|
||||
"version": "v0.14.0",
|
||||
"pinned": false,
|
||||
"date": "2026-02-18T06:12:02Z"
|
||||
"date": "2026-02-17T06:29:10Z"
|
||||
},
|
||||
{
|
||||
"slug": "commafeed",
|
||||
@@ -221,9 +221,9 @@
|
||||
{
|
||||
"slug": "configarr",
|
||||
"repo": "raydak-labs/configarr",
|
||||
"version": "v1.21.0",
|
||||
"version": "v1.20.0",
|
||||
"pinned": false,
|
||||
"date": "2026-02-17T22:59:07Z"
|
||||
"date": "2026-01-10T21:25:47Z"
|
||||
},
|
||||
{
|
||||
"slug": "convertx",
|
||||
@@ -256,9 +256,9 @@
|
||||
{
|
||||
"slug": "databasus",
|
||||
"repo": "databasus/databasus",
|
||||
"version": "v3.14.1",
|
||||
"version": "v3.12.2",
|
||||
"pinned": false,
|
||||
"date": "2026-02-18T10:43:45Z"
|
||||
"date": "2026-02-14T22:28:59Z"
|
||||
},
|
||||
{
|
||||
"slug": "dawarich",
|
||||
@@ -270,9 +270,9 @@
|
||||
{
|
||||
"slug": "discopanel",
|
||||
"repo": "nickheyer/discopanel",
|
||||
"version": "v1.0.37",
|
||||
"version": "v1.0.36",
|
||||
"pinned": false,
|
||||
"date": "2026-02-18T08:53:43Z"
|
||||
"date": "2026-02-09T21:15:44Z"
|
||||
},
|
||||
{
|
||||
"slug": "dispatcharr",
|
||||
@@ -557,9 +557,9 @@
|
||||
{
|
||||
"slug": "huntarr",
|
||||
"repo": "plexguide/Huntarr.io",
|
||||
"version": "9.3.3",
|
||||
"version": "9.3.0",
|
||||
"pinned": false,
|
||||
"date": "2026-02-18T02:35:29Z"
|
||||
"date": "2026-02-17T06:34:38Z"
|
||||
},
|
||||
{
|
||||
"slug": "immich-public-proxy",
|
||||
@@ -585,16 +585,16 @@
|
||||
{
|
||||
"slug": "invoiceninja",
|
||||
"repo": "invoiceninja/invoiceninja",
|
||||
"version": "v5.12.64",
|
||||
"version": "v5.12.62",
|
||||
"pinned": false,
|
||||
"date": "2026-02-18T07:59:44Z"
|
||||
"date": "2026-02-17T03:23:48Z"
|
||||
},
|
||||
{
|
||||
"slug": "jackett",
|
||||
"repo": "Jackett/Jackett",
|
||||
"version": "v0.24.1147",
|
||||
"version": "v0.24.1140",
|
||||
"pinned": false,
|
||||
"date": "2026-02-18T05:54:19Z"
|
||||
"date": "2026-02-17T05:54:25Z"
|
||||
},
|
||||
{
|
||||
"slug": "jellystat",
|
||||
@@ -704,9 +704,9 @@
|
||||
{
|
||||
"slug": "leantime",
|
||||
"repo": "Leantime/leantime",
|
||||
"version": "v3.7.0",
|
||||
"version": "v3.6.2",
|
||||
"pinned": false,
|
||||
"date": "2026-02-18T00:02:31Z"
|
||||
"date": "2026-01-29T16:37:00Z"
|
||||
},
|
||||
{
|
||||
"slug": "librenms",
|
||||
@@ -746,9 +746,9 @@
|
||||
{
|
||||
"slug": "linkstack",
|
||||
"repo": "linkstackorg/linkstack",
|
||||
"version": "v4.8.6",
|
||||
"version": "v4.8.4",
|
||||
"pinned": false,
|
||||
"date": "2026-02-17T16:53:47Z"
|
||||
"date": "2024-12-10T15:14:34Z"
|
||||
},
|
||||
{
|
||||
"slug": "linkwarden",
|
||||
@@ -893,9 +893,9 @@
|
||||
{
|
||||
"slug": "netbox",
|
||||
"repo": "netbox-community/netbox",
|
||||
"version": "v4.5.3",
|
||||
"version": "v4.5.2",
|
||||
"pinned": false,
|
||||
"date": "2026-02-17T15:39:18Z"
|
||||
"date": "2026-02-03T13:54:26Z"
|
||||
},
|
||||
{
|
||||
"slug": "nextcloud-exporter",
|
||||
@@ -1096,9 +1096,9 @@
|
||||
{
|
||||
"slug": "planka",
|
||||
"repo": "plankanban/planka",
|
||||
"version": "v2.0.1",
|
||||
"version": "v2.0.0",
|
||||
"pinned": false,
|
||||
"date": "2026-02-17T15:26:55Z"
|
||||
"date": "2026-02-11T13:50:10Z"
|
||||
},
|
||||
{
|
||||
"slug": "plant-it",
|
||||
@@ -1243,9 +1243,9 @@
|
||||
{
|
||||
"slug": "rclone",
|
||||
"repo": "rclone/rclone",
|
||||
"version": "v1.73.1",
|
||||
"version": "v1.73.0",
|
||||
"pinned": false,
|
||||
"date": "2026-02-17T18:27:21Z"
|
||||
"date": "2026-01-30T22:12:03Z"
|
||||
},
|
||||
{
|
||||
"slug": "rdtclient",
|
||||
@@ -1341,9 +1341,9 @@
|
||||
{
|
||||
"slug": "semaphore",
|
||||
"repo": "semaphoreui/semaphore",
|
||||
"version": "v2.17.7",
|
||||
"version": "v2.17.2",
|
||||
"pinned": false,
|
||||
"date": "2026-02-18T08:10:16Z"
|
||||
"date": "2026-02-16T10:27:40Z"
|
||||
},
|
||||
{
|
||||
"slug": "shelfmark",
|
||||
@@ -1418,9 +1418,9 @@
|
||||
{
|
||||
"slug": "stirling-pdf",
|
||||
"repo": "Stirling-Tools/Stirling-PDF",
|
||||
"version": "v2.5.1",
|
||||
"version": "v2.5.0",
|
||||
"pinned": false,
|
||||
"date": "2026-02-18T11:05:34Z"
|
||||
"date": "2026-02-16T22:58:17Z"
|
||||
},
|
||||
{
|
||||
"slug": "streamlink-webui",
|
||||
@@ -1488,9 +1488,9 @@
|
||||
{
|
||||
"slug": "threadfin",
|
||||
"repo": "threadfin/threadfin",
|
||||
"version": "1.2.37",
|
||||
"version": "delete",
|
||||
"pinned": false,
|
||||
"date": "2025-09-11T16:13:41Z"
|
||||
"date": ""
|
||||
},
|
||||
{
|
||||
"slug": "tianji",
|
||||
@@ -1551,9 +1551,9 @@
|
||||
{
|
||||
"slug": "tunarr",
|
||||
"repo": "chrisbenincasa/tunarr",
|
||||
"version": "v1.1.14",
|
||||
"version": "v1.1.13",
|
||||
"pinned": false,
|
||||
"date": "2026-02-17T18:26:17Z"
|
||||
"date": "2026-02-16T16:16:17Z"
|
||||
},
|
||||
{
|
||||
"slug": "uhf",
|
||||
|
||||
@@ -148,7 +148,6 @@ motd_ssh() {
|
||||
# Start the sshd service
|
||||
$STD /etc/init.d/sshd start
|
||||
fi
|
||||
post_progress_to_api
|
||||
}
|
||||
|
||||
# Validate Timezone for some LXC's
|
||||
@@ -185,5 +184,5 @@ EOF
|
||||
|
||||
echo "bash -c \"\$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/ct/${app}.sh)\"" >/usr/bin/update
|
||||
chmod +x /usr/bin/update
|
||||
post_progress_to_api
|
||||
|
||||
}
|
||||
|
||||
@@ -688,29 +688,6 @@ EOF
|
||||
POST_TO_API_DONE=true
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# post_progress_to_api()
|
||||
#
|
||||
# - Lightweight progress ping from host or container
|
||||
# - Updates the existing telemetry record status to "configuring"
|
||||
# - Signals that the installation is actively progressing (not stuck)
|
||||
# - Fire-and-forget: never blocks or fails the script
|
||||
# - Only executes if DIAGNOSTICS=yes and RANDOM_UUID is set
|
||||
# - Can be called multiple times safely
|
||||
# ------------------------------------------------------------------------------
|
||||
post_progress_to_api() {
|
||||
command -v curl &>/dev/null || return 0
|
||||
[[ "${DIAGNOSTICS:-no}" == "no" ]] && return 0
|
||||
[[ -z "${RANDOM_UUID:-}" ]] && return 0
|
||||
|
||||
local app_name="${NSAPP:-${app:-unknown}}"
|
||||
local telemetry_type="${TELEMETRY_TYPE:-lxc}"
|
||||
|
||||
curl -fsS -m 5 -X POST "${TELEMETRY_URL:-https://telemetry.community-scripts.org/telemetry}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"random_id\":\"${RANDOM_UUID}\",\"execution_id\":\"${EXECUTION_ID:-${RANDOM_UUID}}\",\"type\":\"${telemetry_type}\",\"nsapp\":\"${app_name}\",\"status\":\"configuring\"}" &>/dev/null || true
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# post_update_to_api()
|
||||
#
|
||||
|
||||
@@ -3660,6 +3660,9 @@ $PCT_OPTIONS_STRING"
|
||||
exit 214
|
||||
fi
|
||||
msg_ok "Storage space validated"
|
||||
|
||||
# Report installation start to API (early - captures failed installs too)
|
||||
post_to_api
|
||||
fi
|
||||
|
||||
create_lxc_container || exit $?
|
||||
@@ -3905,7 +3908,6 @@ EOF
|
||||
for i in {1..10}; do
|
||||
if pct status "$CTID" | grep -q "status: running"; then
|
||||
msg_ok "Started LXC Container"
|
||||
post_progress_to_api # Signal container is running
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
@@ -3960,7 +3962,6 @@ EOF
|
||||
echo -e "${YW}Container may have limited internet access. Installation will continue...${CL}"
|
||||
else
|
||||
msg_ok "Network in LXC is reachable (ping)"
|
||||
post_progress_to_api # Signal network is ready
|
||||
fi
|
||||
fi
|
||||
# Function to get correct GID inside container
|
||||
@@ -4032,7 +4033,6 @@ EOF'
|
||||
fi
|
||||
|
||||
msg_ok "Customized LXC Container"
|
||||
post_progress_to_api # Signal ready for app installation
|
||||
|
||||
# Optional DNS override for retry scenarios (inside LXC, never on host)
|
||||
if [[ "${DNS_RETRY_OVERRIDE:-false}" == "true" ]]; then
|
||||
@@ -4106,9 +4106,9 @@ EOF'
|
||||
build_log_copied=true
|
||||
fi
|
||||
|
||||
# Copy and append INSTALL_LOG from container (with timeout to prevent hangs)
|
||||
# Copy and append INSTALL_LOG from container
|
||||
local temp_install_log="/tmp/.install-temp-${SESSION_ID}.log"
|
||||
if timeout 8 pct pull "$CTID" "/root/.install-${SESSION_ID}.log" "$temp_install_log" 2>/dev/null; then
|
||||
if pct pull "$CTID" "/root/.install-${SESSION_ID}.log" "$temp_install_log" 2>/dev/null; then
|
||||
{
|
||||
echo "================================================================================"
|
||||
echo "PHASE 2: APPLICATION INSTALLATION (Container)"
|
||||
@@ -4888,9 +4888,6 @@ create_lxc_container() {
|
||||
exit 206
|
||||
fi
|
||||
|
||||
# Report installation start to API early - captures failures in storage/template/create
|
||||
post_to_api
|
||||
|
||||
# Storage capability check
|
||||
check_storage_support "rootdir" || {
|
||||
msg_error "No valid storage found for 'rootdir' [Container]"
|
||||
@@ -5420,7 +5417,9 @@ create_lxc_container() {
|
||||
}
|
||||
|
||||
msg_ok "LXC Container ${BL}$CTID${CL} ${GN}was successfully created."
|
||||
post_progress_to_api # Signal container creation complete
|
||||
|
||||
# Report container creation to API
|
||||
post_to_api
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
@@ -5493,7 +5492,6 @@ EOF
|
||||
# - If INSTALL_LOG points to a container path (e.g. /root/.install-*),
|
||||
# tries to pull it from the container and create a combined log
|
||||
# - This allows get_error_text() to find actual error output for telemetry
|
||||
# - Uses timeout on pct pull to prevent hangs on dead/unresponsive containers
|
||||
# ------------------------------------------------------------------------------
|
||||
ensure_log_on_host() {
|
||||
# Already readable on host? Nothing to do.
|
||||
@@ -5523,9 +5521,9 @@ ensure_log_on_host() {
|
||||
echo ""
|
||||
} >>"$combined_log"
|
||||
fi
|
||||
# Pull INSTALL_LOG from container (with timeout to prevent hangs on dead containers)
|
||||
# Pull INSTALL_LOG from container
|
||||
local temp_log="/tmp/.install-temp-${SESSION_ID}.log"
|
||||
if timeout 8 pct pull "$CTID" "/root/.install-${SESSION_ID}.log" "$temp_log" 2>/dev/null; then
|
||||
if pct pull "$CTID" "/root/.install-${SESSION_ID}.log" "$temp_log" 2>/dev/null; then
|
||||
{
|
||||
echo "================================================================================"
|
||||
echo "PHASE 2: APPLICATION INSTALLATION (Container)"
|
||||
@@ -5548,8 +5546,8 @@ ensure_log_on_host() {
|
||||
# - Exit trap handler for reporting to API telemetry
|
||||
# - Captures exit code and reports to PocketBase using centralized error descriptions
|
||||
# - Uses explain_exit_code() from api.func for consistent error messages
|
||||
# - ALWAYS sends telemetry FIRST before log collection to prevent pct pull
|
||||
# hangs from blocking status updates (container may be dead/unresponsive)
|
||||
# - For signal exits (>128): sends telemetry FIRST before log collection
|
||||
# to prevent pct pull hangs from blocking status updates
|
||||
# - For non-zero exit codes: posts "failed" status
|
||||
# - For zero exit codes where post_update_to_api was never called:
|
||||
# catches orphaned "installing" records (e.g., script exited cleanly
|
||||
@@ -5558,12 +5556,14 @@ ensure_log_on_host() {
|
||||
api_exit_script() {
|
||||
local exit_code=$?
|
||||
if [ $exit_code -ne 0 ]; then
|
||||
# ALWAYS send telemetry FIRST - ensure status is reported even if
|
||||
# ensure_log_on_host hangs (e.g. pct pull on dead container)
|
||||
post_update_to_api "failed" "$exit_code" 2>/dev/null || true
|
||||
# Best-effort log collection with timeout (non-critical after telemetry is sent)
|
||||
if declare -f ensure_log_on_host >/dev/null 2>&1; then
|
||||
timeout 10 bash -c 'ensure_log_on_host' 2>/dev/null || true
|
||||
if [ $exit_code -gt 128 ]; then
|
||||
# Signal exit: send telemetry IMMEDIATELY (container may be dying)
|
||||
post_update_to_api "failed" "$exit_code" 2>/dev/null || true
|
||||
ensure_log_on_host 2>/dev/null || true
|
||||
else
|
||||
# Normal error: collect logs first for better error details
|
||||
ensure_log_on_host 2>/dev/null || true
|
||||
post_update_to_api "failed" "$exit_code"
|
||||
fi
|
||||
elif [[ "${POST_TO_API_DONE:-}" == "true" && "${POST_UPDATE_DONE:-}" != "true" ]]; then
|
||||
# Script exited with 0 but never sent a completion status
|
||||
@@ -5575,7 +5575,7 @@ api_exit_script() {
|
||||
if command -v pveversion >/dev/null 2>&1; then
|
||||
trap 'api_exit_script' EXIT
|
||||
fi
|
||||
trap 'local _ec=$?; if [[ $_ec -ne 0 ]]; then post_update_to_api "failed" "$_ec" 2>/dev/null || true; timeout 10 bash -c "ensure_log_on_host" 2>/dev/null || true; fi' ERR
|
||||
trap 'post_update_to_api "failed" "129" 2>/dev/null || true; timeout 10 bash -c "ensure_log_on_host" 2>/dev/null || true; exit 129' SIGHUP
|
||||
trap 'post_update_to_api "failed" "130" 2>/dev/null || true; timeout 10 bash -c "ensure_log_on_host" 2>/dev/null || true; exit 130' SIGINT
|
||||
trap 'post_update_to_api "failed" "143" 2>/dev/null || true; timeout 10 bash -c "ensure_log_on_host" 2>/dev/null || true; exit 143' SIGTERM
|
||||
trap 'local _ec=$?; if [[ $_ec -ne 0 ]]; then ensure_log_on_host 2>/dev/null || true; post_update_to_api "failed" "$_ec"; fi' ERR
|
||||
trap 'post_update_to_api "failed" "129" 2>/dev/null || true; ensure_log_on_host 2>/dev/null || true; exit 129' SIGHUP
|
||||
trap 'post_update_to_api "failed" "130" 2>/dev/null || true; ensure_log_on_host 2>/dev/null || true; exit 130' SIGINT
|
||||
trap 'post_update_to_api "failed" "143" 2>/dev/null || true; ensure_log_on_host 2>/dev/null || true; exit 143' SIGTERM
|
||||
|
||||
@@ -1496,11 +1496,6 @@ cleanup_lxc() {
|
||||
fi
|
||||
|
||||
msg_ok "Cleaned"
|
||||
|
||||
# Send progress ping if available (defined in install.func)
|
||||
if declare -f post_progress_to_api &>/dev/null; then
|
||||
post_progress_to_api
|
||||
fi
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
@@ -204,12 +204,6 @@ error_handler() {
|
||||
|
||||
printf "\e[?25h"
|
||||
|
||||
# ALWAYS report failure to API immediately - don't wait for container checks
|
||||
# This ensures we capture failures that occur before/after container exists
|
||||
if declare -f post_update_to_api &>/dev/null; then
|
||||
post_update_to_api "failed" "$exit_code" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# Use msg_error if available, fallback to echo
|
||||
if declare -f msg_error >/dev/null 2>&1; then
|
||||
msg_error "in line ${line_number}: exit code ${exit_code} (${explanation}): while executing command ${command}"
|
||||
@@ -260,6 +254,11 @@ error_handler() {
|
||||
|
||||
# Offer to remove container if it exists (build errors after container creation)
|
||||
if [[ -n "${CTID:-}" ]] && command -v pct &>/dev/null && pct status "$CTID" &>/dev/null; then
|
||||
# Report failure to API before container cleanup
|
||||
if declare -f post_update_to_api &>/dev/null; then
|
||||
post_update_to_api "failed" "$exit_code"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
if declare -f msg_custom >/dev/null 2>&1; then
|
||||
echo -en "${TAB}❓${TAB}${YW}Remove broken container ${CTID}? (Y/n) [auto-remove in 60s]: ${CL}"
|
||||
@@ -340,17 +339,24 @@ on_exit() {
|
||||
# post_to_api was called ("installing" sent) but post_update_to_api was never called
|
||||
if [[ "${POST_TO_API_DONE:-}" == "true" && "${POST_UPDATE_DONE:-}" != "true" ]]; then
|
||||
if declare -f post_update_to_api >/dev/null 2>&1; then
|
||||
# ALWAYS send telemetry FIRST - ensure status is reported even if
|
||||
# ensure_log_on_host hangs (e.g. pct pull on dead/unresponsive container)
|
||||
if [[ $exit_code -ne 0 ]]; then
|
||||
if [[ $exit_code -gt 128 ]]; then
|
||||
# Signal exit: send telemetry IMMEDIATELY (container may be dying, pct pull could hang)
|
||||
post_update_to_api "failed" "$exit_code" 2>/dev/null || true
|
||||
# Then try log collection (non-critical, best-effort)
|
||||
if declare -f ensure_log_on_host >/dev/null 2>&1; then
|
||||
ensure_log_on_host 2>/dev/null || true
|
||||
fi
|
||||
else
|
||||
# exit_code=0 is never an error — report as success
|
||||
post_update_to_api "done" "0" 2>/dev/null || true
|
||||
fi
|
||||
# Best-effort log collection with timeout (non-critical after telemetry is sent)
|
||||
if declare -f ensure_log_on_host >/dev/null 2>&1; then
|
||||
timeout 10 bash -c 'ensure_log_on_host' 2>/dev/null || true
|
||||
# Normal exit: collect logs first for better error details
|
||||
if declare -f ensure_log_on_host >/dev/null 2>&1; then
|
||||
ensure_log_on_host 2>/dev/null || true
|
||||
fi
|
||||
if [[ $exit_code -ne 0 ]]; then
|
||||
post_update_to_api "failed" "$exit_code"
|
||||
else
|
||||
# exit_code=0 is never an error — report as success
|
||||
post_update_to_api "done" "0"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
@@ -374,9 +380,9 @@ on_interrupt() {
|
||||
if declare -f post_update_to_api >/dev/null 2>&1; then
|
||||
post_update_to_api "failed" "130" 2>/dev/null || true
|
||||
fi
|
||||
# Best-effort log collection with timeout (non-critical after telemetry is sent)
|
||||
# Best-effort log collection (non-critical after telemetry is sent)
|
||||
if declare -f ensure_log_on_host >/dev/null 2>&1; then
|
||||
timeout 10 bash -c 'ensure_log_on_host' 2>/dev/null || true
|
||||
ensure_log_on_host 2>/dev/null || true
|
||||
fi
|
||||
if declare -f msg_error >/dev/null 2>&1; then
|
||||
msg_error "Interrupted by user (SIGINT)" 2>/dev/null || true
|
||||
@@ -403,9 +409,9 @@ on_terminate() {
|
||||
if declare -f post_update_to_api >/dev/null 2>&1; then
|
||||
post_update_to_api "failed" "143" 2>/dev/null || true
|
||||
fi
|
||||
# Best-effort log collection with timeout (non-critical after telemetry is sent)
|
||||
# Best-effort log collection (non-critical after telemetry is sent)
|
||||
if declare -f ensure_log_on_host >/dev/null 2>&1; then
|
||||
timeout 10 bash -c 'ensure_log_on_host' 2>/dev/null || true
|
||||
ensure_log_on_host 2>/dev/null || true
|
||||
fi
|
||||
if declare -f msg_error >/dev/null 2>&1; then
|
||||
msg_error "Terminated by signal (SIGTERM)" 2>/dev/null || true
|
||||
|
||||
@@ -285,7 +285,6 @@ motd_ssh() {
|
||||
sed -i "s/#PermitRootLogin prohibit-password/PermitRootLogin yes/g" /etc/ssh/sshd_config
|
||||
systemctl restart sshd
|
||||
fi
|
||||
post_progress_to_api
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
@@ -324,5 +323,4 @@ EOF
|
||||
chmod 700 /root/.ssh
|
||||
chmod 600 /root/.ssh/authorized_keys
|
||||
fi
|
||||
post_progress_to_api
|
||||
}
|
||||
|
||||
@@ -1,226 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright (c) 2021-2026 community-scripts ORG
|
||||
# Author: MickLesk (CanbiZ)
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://github.com/fccview/cronmaster
|
||||
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/error_handler.func)
|
||||
|
||||
# Enable error handling
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler' ERR
|
||||
|
||||
# ==============================================================================
|
||||
# CONFIGURATION
|
||||
# ==============================================================================
|
||||
APP="CronMaster"
|
||||
APP_TYPE="addon"
|
||||
INSTALL_PATH="/opt/cronmaster"
|
||||
CONFIG_PATH="/opt/cronmaster/.env"
|
||||
DEFAULT_PORT=3000
|
||||
|
||||
# Initialize all core functions (colors, formatting, icons, STD mode)
|
||||
load_functions
|
||||
|
||||
# ==============================================================================
|
||||
# HEADER
|
||||
# ==============================================================================
|
||||
function header_info {
|
||||
clear
|
||||
cat <<"EOF"
|
||||
______ __ ___ __
|
||||
/ ____/________ ____ / |/ /___ ______/ /____ _____
|
||||
/ / / ___/ __ \/ __ \/ /|_/ / __ `/ ___/ __/ _ \/ ___/
|
||||
/ /___/ / / /_/ / / / / / / / /_/ (__ ) /_/ __/ /
|
||||
\____/_/ \____/_/ /_/_/ /_/\__,_/____/\__/\___/_/
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# OS DETECTION
|
||||
# ==============================================================================
|
||||
if [[ -f "/etc/alpine-release" ]]; then
|
||||
msg_error "Alpine is not supported for ${APP}. Use Debian/Ubuntu."
|
||||
exit 1
|
||||
elif [[ -f "/etc/debian_version" ]]; then
|
||||
OS="Debian"
|
||||
SERVICE_PATH="/etc/systemd/system/cronmaster.service"
|
||||
else
|
||||
echo -e "${CROSS} Unsupported OS detected. Exiting."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ==============================================================================
|
||||
# UNINSTALL
|
||||
# ==============================================================================
|
||||
function uninstall() {
|
||||
msg_info "Uninstalling ${APP}"
|
||||
systemctl disable --now cronmaster.service &>/dev/null || true
|
||||
rm -f "$SERVICE_PATH"
|
||||
rm -rf "$INSTALL_PATH"
|
||||
rm -f "/usr/local/bin/update_cronmaster"
|
||||
rm -f "$HOME/.cronmaster"
|
||||
msg_ok "${APP} has been uninstalled"
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# UPDATE
|
||||
# ==============================================================================
|
||||
function update() {
|
||||
if check_for_gh_release "cronmaster" "fccview/cronmaster"; then
|
||||
msg_info "Stopping service"
|
||||
systemctl stop cronmaster.service &>/dev/null || true
|
||||
msg_ok "Stopped service"
|
||||
|
||||
msg_info "Backing up configuration"
|
||||
cp "$CONFIG_PATH" /tmp/cronmaster.env.bak 2>/dev/null || true
|
||||
msg_ok "Backed up configuration"
|
||||
|
||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "cronmaster" "fccview/cronmaster" "prebuild" "latest" "$INSTALL_PATH" "cronmaster_*_prebuild.tar.gz"
|
||||
|
||||
msg_info "Restoring configuration"
|
||||
cp /tmp/cronmaster.env.bak "$CONFIG_PATH" 2>/dev/null || true
|
||||
rm -f /tmp/cronmaster.env.bak
|
||||
msg_ok "Restored configuration"
|
||||
|
||||
msg_info "Starting service"
|
||||
systemctl start cronmaster
|
||||
msg_ok "Started service"
|
||||
msg_ok "Updated successfully"
|
||||
exit
|
||||
fi
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# INSTALL
|
||||
# ==============================================================================
|
||||
function install() {
|
||||
# Setup Node.js (only installs if not present or different version)
|
||||
if command -v node &>/dev/null; then
|
||||
msg_ok "Node.js already installed ($(node -v))"
|
||||
else
|
||||
NODE_VERSION="22" setup_nodejs
|
||||
fi
|
||||
|
||||
# Force fresh download by removing version cache
|
||||
rm -f "$HOME/.cronmaster"
|
||||
fetch_and_deploy_gh_release "cronmaster" "fccview/cronmaster" "prebuild" "latest" "$INSTALL_PATH" "cronmaster_*_prebuild.tar.gz"
|
||||
|
||||
local AUTH_PASS
|
||||
AUTH_PASS="$(openssl rand -base64 18 | cut -c1-13)"
|
||||
|
||||
msg_info "Creating configuration"
|
||||
cat <<EOF >"$CONFIG_PATH"
|
||||
NODE_ENV=production
|
||||
AUTH_PASSWORD=${AUTH_PASS}
|
||||
PORT=${DEFAULT_PORT}
|
||||
HOSTNAME=0.0.0.0
|
||||
NEXT_TELEMETRY_DISABLED=1
|
||||
EOF
|
||||
chmod 600 "$CONFIG_PATH"
|
||||
msg_ok "Created configuration"
|
||||
|
||||
msg_info "Creating service"
|
||||
cat <<EOF >"$SERVICE_PATH"
|
||||
[Unit]
|
||||
Description=CronMaster Service
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=root
|
||||
WorkingDirectory=${INSTALL_PATH}
|
||||
EnvironmentFile=${CONFIG_PATH}
|
||||
ExecStart=/usr/bin/node ${INSTALL_PATH}/server.js
|
||||
Restart=always
|
||||
RestartSec=10
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-target.target
|
||||
EOF
|
||||
systemctl enable --now cronmaster &>/dev/null
|
||||
msg_ok "Created and started service"
|
||||
|
||||
# Create update script
|
||||
msg_info "Creating update script"
|
||||
cat <<'UPDATEEOF' >/usr/local/bin/update_cronmaster
|
||||
#!/usr/bin/env bash
|
||||
# CronMaster Update Script
|
||||
type=update bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/cronmaster.sh)"
|
||||
UPDATEEOF
|
||||
chmod +x /usr/local/bin/update_cronmaster
|
||||
msg_ok "Created update script (/usr/local/bin/update_cronmaster)"
|
||||
|
||||
echo ""
|
||||
msg_ok "${APP} is reachable at: ${BL}http://${LOCAL_IP}:${DEFAULT_PORT}${CL}"
|
||||
msg_ok "Password: ${BL}${AUTH_PASS}${CL}"
|
||||
echo ""
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# MAIN
|
||||
# ==============================================================================
|
||||
|
||||
# Handle type=update (called from update script)
|
||||
if [[ "${type:-}" == "update" ]]; then
|
||||
header_info
|
||||
if [[ -d "$INSTALL_PATH" ]]; then
|
||||
update
|
||||
else
|
||||
msg_error "${APP} is not installed. Nothing to update."
|
||||
exit 1
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
header_info
|
||||
get_lxc_ip
|
||||
|
||||
# Check if already installed
|
||||
if [[ -d "$INSTALL_PATH" && -n "$(ls -A "$INSTALL_PATH" 2>/dev/null)" ]]; then
|
||||
msg_warn "${APP} is already installed."
|
||||
echo ""
|
||||
|
||||
echo -n "${TAB}Uninstall ${APP}? (y/N): "
|
||||
read -r uninstall_prompt
|
||||
if [[ "${uninstall_prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
uninstall
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo -n "${TAB}Update ${APP}? (y/N): "
|
||||
read -r update_prompt
|
||||
if [[ "${update_prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
update
|
||||
exit 0
|
||||
fi
|
||||
|
||||
msg_warn "No action selected. Exiting."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Fresh installation
|
||||
msg_warn "${APP} is not installed."
|
||||
echo ""
|
||||
echo -e "${TAB}${INFO} This will install:"
|
||||
echo -e "${TAB} - Node.js 22"
|
||||
echo -e "${TAB} - CronMaster (prebuild)"
|
||||
echo ""
|
||||
|
||||
echo -n "${TAB}Install ${APP}? (y/N): "
|
||||
read -r install_prompt
|
||||
if [[ "${install_prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
install
|
||||
else
|
||||
msg_warn "Installation cancelled. Exiting."
|
||||
exit 0
|
||||
fi
|
||||
Reference in New Issue
Block a user