109 Commits

Author SHA1 Message Date
ProxMenuxBot 48fd8579c5 Update helpers_cache.json 2026-05-28 07:16:42 +00:00
ProxMenuxBot 62bf372e1d Update helpers_cache.json 2026-05-27 18:44:04 +00:00
ProxMenuxBot 3a4654141f Update helpers_cache.json 2026-05-27 13:04:44 +00:00
ProxMenuxBot 967dcfcb37 Update helpers_cache.json 2026-05-27 07:23:05 +00:00
ProxMenuxBot d7faf186f8 Update helpers_cache.json 2026-05-26 18:46:39 +00:00
ProxMenuxBot f819aa68d5 Update helpers_cache.json 2026-05-26 12:55:36 +00:00
ProxMenuxBot 975ad20d5a Update helpers_cache.json 2026-05-25 00:33:36 +00:00
ProxMenuxBot a94106ae61 Update helpers_cache.json 2026-05-24 18:19:55 +00:00
ProxMenuxBot 777e830aec Update helpers_cache.json 2026-05-24 00:32:25 +00:00
ProxMenuxBot bbf2dc903a Update helpers_cache.json 2026-05-23 00:32:41 +00:00
ProxMenuxBot 8fb05858c8 Update helpers_cache.json 2026-05-22 12:45:25 +00:00
ProxMenuxBot d0d0f30d64 Update helpers_cache.json 2026-05-21 18:35:52 +00:00
ProxMenuxBot 04185f9a31 Update helpers_cache.json 2026-05-21 13:02:35 +00:00
ProxMenuxBot 5227a1370c Update helpers_cache.json 2026-05-20 12:47:52 +00:00
ProxMenuxBot c33f306944 Update helpers_cache.json 2026-05-19 13:01:03 +00:00
ProxMenuxBot 3306780507 Update helpers_cache.json 2026-05-19 07:09:35 +00:00
ProxMenuxBot 84d7b60cd2 Update helpers_cache.json 2026-05-18 18:34:18 +00:00
ProxMenuxBot 0d435a5d4a Update helpers_cache.json 2026-05-18 13:08:58 +00:00
ProxMenuxBot 4994543d56 Update helpers_cache.json 2026-05-18 07:19:20 +00:00
ProxMenuxBot 026ceab2ef Update helpers_cache.json 2026-05-18 00:31:31 +00:00
ProxMenuxBot c92bf504fb Update helpers_cache.json 2026-05-17 12:17:49 +00:00
ProxMenuxBot a7eac42c9d Update helpers_cache.json 2026-05-17 00:30:19 +00:00
ProxMenuxBot f20550d5f6 Update helpers_cache.json 2026-05-14 18:35:05 +00:00
ProxMenuxBot 742b08c86d Update helpers_cache.json 2026-05-13 12:40:43 +00:00
ProxMenuxBot a85ddcd6c1 Update helpers_cache.json 2026-05-13 00:31:38 +00:00
ProxMenuxBot 758ac4ab62 Update helpers_cache.json 2026-05-12 00:29:10 +00:00
ProxMenuxBot 56e5d7ff54 Update helpers_cache.json 2026-05-11 18:35:26 +00:00
ProxMenuxBot 596a8ba21d Update helpers_cache.json 2026-05-11 12:55:43 +00:00
ProxMenuxBot 19b67b3c8a Update helpers_cache.json 2026-05-11 07:07:56 +00:00
ProxMenuxBot eaa97ce301 Update helpers_cache.json 2026-05-11 00:29:24 +00:00
ProxMenuxBot a05d16a789 Update helpers_cache.json 2026-05-10 12:16:31 +00:00
ProxMenuxBot f11aa77e3a Update helpers_cache.json 2026-05-07 18:32:01 +00:00
MacRimi 1bbcf60e58 Update attribution clause in LICENSE 2026-05-07 17:16:56 +02:00
ProxMenuxBot c90ee58bc0 Update helpers_cache.json 2026-05-07 12:34:40 +00:00
ProxMenuxBot 2983e20695 Update helpers_cache.json 2026-05-06 17:56:15 +00:00
MacRimi 4e7570cb26 Refactor install_methods variable and split_notes function 2026-05-06 19:55:33 +02:00
ProxMenuxBot 7987b61345 Update helpers_cache.json 2026-05-05 12:22:52 +00:00
ProxMenuxBot 6fbd47ed8a Update helpers_cache.json 2026-05-05 06:43:37 +00:00
ProxMenuxBot bada4ef524 Update helpers_cache.json 2026-05-05 00:27:53 +00:00
ProxMenuxBot 8918d37bb6 Update helpers_cache.json 2026-05-04 18:29:56 +00:00
ProxMenuxBot b0d94a3594 Update helpers_cache.json 2026-05-04 06:59:01 +00:00
ProxMenuxBot 1291204d2b Update helpers_cache.json 2026-05-04 00:27:30 +00:00
ProxMenuxBot 804f201589 Update helpers_cache.json 2026-05-03 18:16:18 +00:00
ProxMenuxBot 65779b1eb6 Update helpers_cache.json 2026-05-03 00:27:17 +00:00
ProxMenuxBot 7eac978950 Update helpers_cache.json 2026-05-02 18:16:00 +00:00
ProxMenuxBot b1d0cfa2e7 Update helpers_cache.json 2026-05-02 12:16:12 +00:00
ProxMenuxBot 282b1c2b0a Update helpers_cache.json 2026-05-02 00:27:19 +00:00
ProxMenuxBot b4b0d4cd7e Update helpers_cache.json 2026-04-30 18:27:38 +00:00
ProxMenuxBot 6a66ee75ac Update helpers_cache.json 2026-04-30 12:29:27 +00:00
ProxMenuxBot 45dcdcccbb Update helpers_cache.json 2026-04-30 06:50:16 +00:00
ProxMenuxBot 5d47f1dfca Update helpers_cache.json 2026-04-29 12:29:45 +00:00
ProxMenuxBot 1e07e5f17b Update helpers_cache.json 2026-04-28 12:33:16 +00:00
ProxMenuxBot 8adb1b9730 Update helpers_cache.json 2026-04-28 06:52:18 +00:00
ProxMenuxBot 9d3720b6a1 Update helpers_cache.json 2026-04-26 18:12:46 +00:00
ProxMenuxBot 6496601e4e Update helpers_cache.json 2026-04-26 12:12:36 +00:00
ProxMenuxBot b96df3b501 Update helpers_cache.json 2026-04-26 00:23:40 +00:00
ProxMenuxBot 489460f509 Update helpers_cache.json 2026-04-24 18:13:16 +00:00
ProxMenuxBot 192870d658 Update helpers_cache.json 2026-04-24 12:18:50 +00:00
ProxMenuxBot bed4b5ee49 Update helpers_cache.json 2026-04-22 12:19:08 +00:00
ProxMenuxBot f0eb402100 Update helpers_cache.json 2026-04-22 06:35:40 +00:00
MacRimi e73486904b Revise changelog for ProxMenux v1.2.1 release
Updated the changelog for ProxMenux v1.2.1 to clarify community-reported fixes and improvements.
2026-04-21 22:27:33 +02:00
github-actions[bot] 1119a45e93 Update AppImage release build (2026-04-21 19:28:24) 2026-04-21 19:28:24 +00:00
MacRimi 85860cdddd Merge pull request #187 from MacRimi/develop
Create CHANGELOG.md
2026-04-21 21:23:08 +02:00
MacRimi 01ed2da10e Merge pull request #186 from MacRimi/develop
Develop
2026-04-21 21:22:13 +02:00
MacRimi d725910e7a Delete CHANGELOG.md 2026-04-21 21:20:37 +02:00
MacRimi b599a990f6 Rename riov-indicator.png to sriov-indicator.png 2026-04-21 21:17:33 +02:00
MacRimi c403300cd2 Merge pull request #185 from MacRimi/develop
new version v1.2.1
2026-04-21 21:14:12 +02:00
ProxMenuxBot acf2302755 Update helpers_cache.json 2026-04-21 18:20:49 +00:00
ProxMenuxBot 8fedd3defe Update helpers_cache.json 2026-04-21 12:19:33 +00:00
ProxMenuxBot adda8181a6 Update helpers_cache.json 2026-04-21 06:35:35 +00:00
ProxMenuxBot 789494cc89 Update helpers_cache.json 2026-04-21 00:23:27 +00:00
ProxMenuxBot 561086e940 Update helpers_cache.json 2026-04-19 18:10:57 +00:00
ProxMenuxBot 8442cbca77 Update helpers_cache.json 2026-04-19 00:21:12 +00:00
github-actions[bot] 102a58a068 Update AppImage release build (2026-04-19 00:07:37) 2026-04-19 00:07:37 +00:00
MacRimi 4e849d5309 Merge pull request #178 from MacRimi/develop
update notification_events.py
2026-04-19 02:03:53 +02:00
MacRimi 44e92c8bf0 Delete AppImage/ProxMenux-Monitor.AppImage.sha256 2026-04-19 02:03:35 +02:00
MacRimi 873f5ae51e Delete AppImage/ProxMenux-1.2.0.AppImage 2026-04-19 02:03:24 +02:00
MacRimi 7ee6b6a96b Merge pull request #177 from MacRimi/develop
Update nvidia_installer.sh
2026-04-18 19:21:21 +02:00
MacRimi 91381f0850 Merge pull request #176 from MacRimi/develop
Develop
2026-04-18 19:01:18 +02:00
MacRimi 8c3d022506 Merge pull request #175 from MacRimi/develop
Develop
2026-04-18 18:51:06 +02:00
MacRimi 18b3b572f0 Delete beta_version.txt 2026-04-18 18:16:31 +02:00
MacRimi 023e3ff59b Merge pull request #174 from MacRimi/develop
Create beta_version.txt
2026-04-18 18:02:59 +02:00
MacRimi f516a1cf4c Merge pull request #173 from MacRimi/develop
Develop
2026-04-18 17:58:51 +02:00
MacRimi b049712cd6 Update CHANGELOG for ProxMenux v1.2.0 release
Document the release of ProxMenux v1.2.0 with AI enhancements and performance improvements.
2026-04-18 14:21:20 +02:00
MacRimi 2cdfc60fe1 Update CHANGELOG for ProxMenux v1.2.0 release
This release introduces AI-enhanced notifications, a redesigned multi-channel notification system, and performance improvements. It consolidates recent work on Storage, Hardware, and GPU/TPU scripts.
2026-04-18 14:20:31 +02:00
MacRimi 2739cb0894 Revise CHANGELOG for version v1.1.9
Updated changelog for version v1.1.9 with new entries.
2026-04-18 14:15:15 +02:00
MacRimi 3e5ef4fa08 Fix menu option display height in hw_grafics_menu.sh 2026-04-18 09:15:37 +02:00
MacRimi a7a010d660 Fix spinner stop call and add newline at end of file 2026-04-18 09:14:30 +02:00
MacRimi efa111e2dd Refactor message building in menu_Helper_Scripts.sh 2026-04-18 09:06:01 +02:00
MacRimi 813798ec2b Add message for completed NVIDIA uninstallation
Add confirmation message after NVIDIA uninstallation steps.
2026-04-18 09:05:18 +02:00
MacRimi 9220dfb7a3 Update version.txt 2026-04-18 01:24:52 +02:00
MacRimi 45e7713638 Update menu 2026-04-18 01:21:11 +02:00
MacRimi 46edd4e3e4 Remove safe self-update and beta check functions 2026-04-18 00:59:54 +02:00
MacRimi 800a18ac60 Eliminate syntax check for installed launcher
Removed defensive checks for launcher script syntax during installation.
2026-04-18 00:59:23 +02:00
MacRimi 07384e4d7c Implement safe self-update mechanism
Add safe self-update functionality to prevent launcher corruption.
2026-04-18 00:36:56 +02:00
MacRimi 1f7bf74970 Add syntax check for installed launcher script
Added defensive checks to ensure the installed launcher script passes syntax validation before proceeding with installation.
2026-04-18 00:36:30 +02:00
MacRimi 9e4e0bc24a Update version.txt 2026-04-18 00:11:49 +02:00
MacRimi 18687666a6 Update README with security note on VirusTotal
Added a security note regarding VirusTotal false positives.
2026-04-18 00:08:58 +02:00
MacRimi ccb924f8f6 Bump version from 1.1.9 to 1.2.0 2026-04-18 00:03:40 +02:00
MacRimi 58ac4ee743 Update CHANGELOG to remove UI flow consistency details
Removed UI flow consistency section from CHANGELOG.
2026-04-18 00:02:25 +02:00
MacRimi d515448113 Release v1.2.0 with AI enhancements and optimizations
This release introduces AI-enhanced notifications, a redesigned multi-channel notification system, expanded hardware detection, and significant performance optimizations.
2026-04-18 00:00:52 +02:00
github-actions[bot] ec3de30b14 Update AppImage release build (2026-04-17 22:00:49) 2026-04-17 22:00:49 +00:00
MacRimi 4837b66089 Update README.md 2026-04-17 23:57:15 +02:00
MacRimi c312cf3d38 Delete beta_version.txt 2026-04-17 23:56:38 +02:00
MacRimi 46f5af1966 Delete install_proxmenux_beta.sh 2026-04-17 23:56:25 +02:00
MacRimi 85f98dff9a Delete AppImage/ProxMenux-Monitor.AppImage.sha256 2026-04-17 23:54:41 +02:00
MacRimi bd56964860 Delete AppImage/ProxMenux-1.2.0.AppImage 2026-04-17 23:54:30 +02:00
MacRimi 481a653b75 Delete AppImage/ProxMenux-1.0.2.AppImage 2026-04-17 23:54:20 +02:00
MacRimi f94b59954f Merge pull request #169 from MacRimi/develop
ProxMenux v1.2.0
2026-04-17 23:51:51 +02:00
9 changed files with 4733 additions and 2114 deletions
+43 -16
View File
@@ -67,9 +67,9 @@ def fetch_all_records(url: str, *, expand: str | None = None, per_page: int = 50
return items return items
def normalize_os_variants(install_methods_json: list[dict[str, Any]]) -> list[str]: def normalize_os_variants(install_methods: list[dict[str, Any]]) -> list[str]:
os_values: list[str] = [] os_values: list[str] = []
for item in install_methods_json: for item in install_methods:
if not isinstance(item, dict): if not isinstance(item, dict):
continue continue
resources = item.get("resources", {}) resources = item.get("resources", {})
@@ -83,6 +83,31 @@ def normalize_os_variants(install_methods_json: list[dict[str, Any]]) -> list[st
return os_values return os_values
def split_notes(notes_raw: list[dict[str, Any]]) -> tuple[list[str], list[str]]:
"""Split PocketBase notes into (info_notes, warnings).
Each entry has shape ``{"text": str, "type": "warning"|...}``. Anything
flagged ``type == "warning"`` lands in the warnings list so the bash
menu can render those in red with a dedicated WARNINGS header. Other
notes go to the regular notes list.
"""
info: list[str] = []
warns: list[str] = []
for note in notes_raw or []:
if not isinstance(note, dict):
continue
text = note.get("text")
if not isinstance(text, str) or not text.strip():
continue
text = text.strip()
ntype = (note.get("type") or "").strip().lower()
if ntype == "warning":
warns.append(text)
else:
info.append(text)
return info, warns
def build_script_path(type_name: str, slug: str) -> str: def build_script_path(type_name: str, slug: str) -> str:
type_name = (type_name or "").strip().lower() type_name = (type_name or "").strip().lower()
slug = (slug or "").strip() slug = (slug or "").strip()
@@ -138,19 +163,19 @@ def main() -> int:
full_script_url = f"{SCRIPT_BASE}/{script_path}" full_script_url = f"{SCRIPT_BASE}/{script_path}"
script_url_mirror = to_mirror_url(full_script_url) script_url_mirror = to_mirror_url(full_script_url)
install_methods_json = raw.get("install_methods_json", []) # Sprint 11.7: PocketBase exposes these as `install_methods` and
if not isinstance(install_methods_json, list): # `notes`, not `install_methods_json` / `notes_json`. The legacy field
install_methods_json = [] # names silently returned [] for every entry, which is why the cache
# had empty notes and missing OS variants for every script.
install_methods = raw.get("install_methods", [])
if not isinstance(install_methods, list):
install_methods = []
notes_json = raw.get("notes_json", []) notes_raw = raw.get("notes", [])
if not isinstance(notes_json, list): if not isinstance(notes_raw, list):
notes_json = [] notes_raw = []
notes = [ notes, warnings = split_notes(notes_raw)
note.get("text", "")
for note in notes_json
if isinstance(note, dict) and isinstance(note.get("text"), str) and note.get("text", "").strip()
]
category_ids = raw.get("categories", []) category_ids = raw.get("categories", [])
if not isinstance(category_ids, list): if not isinstance(category_ids, list):
@@ -193,6 +218,7 @@ def main() -> int:
"categories": category_ids, "categories": category_ids,
"category_names": category_names, "category_names": category_names,
"notes": notes, "notes": notes,
"warnings": warnings,
"port": raw.get("port", 0), "port": raw.get("port", 0),
"website": raw.get("website", ""), "website": raw.get("website", ""),
"documentation": raw.get("documentation", ""), "documentation": raw.get("documentation", ""),
@@ -210,7 +236,7 @@ def main() -> int:
# Emit one entry per install method so the menu shell can offer an # Emit one entry per install method so the menu shell can offer an
# explicit OS choice. When there is only one method (or none), a # explicit OS choice. When there is only one method (or none), a
# single entry is emitted with os="" (script decides at runtime). # single entry is emitted with os="" (script decides at runtime).
os_variants = normalize_os_variants(install_methods_json) os_variants = normalize_os_variants(install_methods)
if len(os_variants) > 1: if len(os_variants) > 1:
for os_name in os_variants: for os_name in os_variants:
@@ -228,11 +254,12 @@ def main() -> int:
with OUTPUT_FILE.open("w", encoding="utf-8") as f: with OUTPUT_FILE.open("w", encoding="utf-8") as f:
json.dump(cache, f, ensure_ascii=False, indent=2) json.dump(cache, f, ensure_ascii=False, indent=2)
total_notes = sum(len(e.get("notes", [])) for e in cache)
total_warns = sum(len(e.get("warnings", [])) for e in cache)
print(f"\n✅ helpers_cache.json → {OUTPUT_FILE}") print(f"\n✅ helpers_cache.json → {OUTPUT_FILE}")
print(f" Guardados: {len(cache)}") print(f" Guardados: {len(cache)} entries, {total_notes} notes, {total_warns} warnings")
return 0 return 0
if __name__ == "__main__": if __name__ == "__main__":
sys.exit(main()) sys.exit(main())
BIN
View File
Binary file not shown.
@@ -0,0 +1 @@
db5bc199adba9c231f344428ac902a0cbf7473778e8a79a4535263599d975449 ProxMenux-1.2.0.AppImage
+1 -1
View File
@@ -3,7 +3,7 @@
### New version ProxMenux v1.2.1 — *SR-IOV Awareness & GPU Passthrough Hardening* ### New version ProxMenux v1.2.1 — *SR-IOV Awareness & GPU Passthrough Hardening*
Targeted release on top of **v1.2.0** addressing three community-reported areas that needed fixing before the next stable cycle: full SR-IOV awareness across the GPU/PCI subsystem, robust handling of GPU + audio companions during passthrough attach and detach (Intel iGPU with chipset audio, discrete cards with HDMI audio, mixed-GPU VMs), and compatibility fixes for the AI notification providers (OpenAI-compatible custom endpoints such as LiteLLM/MLX/LM Studio, OpenAI reasoning models, and Gemini 2.5+/3.x thinking models). Also bundles quality-of-life fixes in the NVIDIA installer, the disk health monitor, and the LXC lifecycle helpers used by the passthrough wizards. Targeted release on top of **v1.2.0** addressing three community-reported areas: complete SR-IOV awareness across the GPU/PCI subsystem, robust handling of GPU + audio companions during passthrough attach and detach (Intel iGPU with chipset audio, discrete cards with HDMI audio, mixed-GPU VMs), and compatibility fixes for AI notification providers (OpenAI-compatible custom endpoints such as LiteLLM/MLX/LM Studio, OpenAI reasoning models, and Gemini 2.5+/3.x thinking models). Also includes quality-of-life improvements in the NVIDIA installer, the disk health monitor, and the LXC lifecycle helpers used by the passthrough wizards.
--- ---
+2 -1
View File
@@ -16,7 +16,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
Under this license: Under this license:
1. Attribution: You must give appropriate credit to the original author (MacRimi). 1. Attribution: You must give appropriate credit to the original author (MacRimi)
and to all contributors involved in the development of the project.
2. Copyleft: If you remix, transform, or build upon ProxMenux, you must 2. Copyleft: If you remix, transform, or build upon ProxMenux, you must
distribute your contributions under the same GPL-3.0 license. distribute your contributions under the same GPL-3.0 license.
3. Source Code: Anyone distributing a modified version must make the 3. Source Code: Anyone distributing a modified version must make the

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 54 KiB

-670
View File
@@ -1,670 +0,0 @@
#!/bin/bash
# ==========================================================
# ProxMenux Monitor - Beta Program Installer
# ==========================================================
# Author : MacRimi
# Subproject : ProxMenux Monitor Beta
# Copyright : (c) 2024-2025 MacRimi
# License : GPL-3.0 (https://github.com/MacRimi/ProxMenux/blob/main/LICENSE)
# Version : Beta 1.1
# Branch : develop
# Last Updated : 2026-03-26
# ==========================================================
# Description:
# This script installs the BETA version of ProxMenux Monitor
# from the develop branch on GitHub.
#
# Beta testers are expected to:
# - Report bugs and unexpected behavior via GitHub Issues
# - Provide feedback to help improve the final release
#
# Installs:
# • dialog, curl, jq, git (system dependencies)
# • ProxMenux core files (/usr/local/share/proxmenux)
# • ProxMenux Monitor AppImage (Web dashboard on port 8008)
# • Systemd service (auto-start on boot)
#
# Notes:
# - Clones from the 'develop' branch
# - Beta version file: beta_version.txt in the repository
# - Transition to stable: re-run the official installer
# ==========================================================
# ── Configuration ──────────────────────────────────────────
INSTALL_DIR="/usr/local/bin"
BASE_DIR="/usr/local/share/proxmenux"
CONFIG_FILE="$BASE_DIR/config.json"
CACHE_FILE="$BASE_DIR/cache.json"
UTILS_FILE="$BASE_DIR/utils.sh"
LOCAL_VERSION_FILE="$BASE_DIR/version.txt"
BETA_VERSION_FILE="$BASE_DIR/beta_version.txt"
MENU_SCRIPT="menu"
MONITOR_INSTALL_DIR="$BASE_DIR"
MONITOR_SERVICE_FILE="/etc/systemd/system/proxmenux-monitor.service"
MONITOR_PORT=8008
REPO_URL="https://github.com/MacRimi/ProxMenux.git"
REPO_BRANCH="develop"
TEMP_DIR="/tmp/proxmenux-beta-install-$$"
# ── Colors ─────────────────────────────────────────────────
RESET="\033[0m"
BOLD="\033[1m"
WHITE="\033[38;5;15m"
NEON_PURPLE_BLUE="\033[38;5;99m"
DARK_GRAY="\033[38;5;244m"
ORANGE="\033[38;5;208m"
GN="\033[1;92m"
YW="\033[33m"
YWB="\033[1;33m"
RD="\033[01;31m"
BL="\033[36m"
CL="\033[m"
BGN="\e[1;32m"
TAB=" "
BFR="\\r\\033[K"
HOLD="-"
BOR=" | "
CM="${GN}${CL}"
SPINNER_PID=""
# ── Spinner ────────────────────────────────────────────────
spinner() {
local frames=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local spin_i=0
printf "\e[?25l"
while true; do
printf "\r ${YW}%s${CL}" "${frames[spin_i]}"
spin_i=$(( (spin_i + 1) % ${#frames[@]} ))
sleep 0.1
done
}
type_text() {
local text="$1"
local delay=0.04
for ((i=0; i<${#text}; i++)); do
echo -n "${text:$i:1}"
sleep $delay
done
echo
}
msg_info() {
local msg="$1"
echo -ne "${TAB}${YW}${HOLD}${msg}"
spinner &
SPINNER_PID=$!
}
msg_ok() {
if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID > /dev/null 2>&1; then
kill $SPINNER_PID > /dev/null 2>&1
SPINNER_PID=""
fi
printf "\e[?25h"
echo -e "${BFR}${TAB}${CM}${GN}${1}${CL}"
}
msg_error() {
if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID > /dev/null 2>&1; then
kill $SPINNER_PID > /dev/null 2>&1
SPINNER_PID=""
fi
printf "\e[?25h"
echo -e "${BFR}${TAB}${RD}[ERROR] ${1}${CL}"
}
msg_warn() {
if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID > /dev/null 2>&1; then
kill $SPINNER_PID > /dev/null 2>&1
SPINNER_PID=""
fi
printf "\e[?25h"
echo -e "${BFR}${TAB}${YWB}${1}${CL}"
}
msg_title() {
echo -e "\n"
echo -e "${TAB}${BOLD}${HOLD}${BOR}${1}${BOR}${HOLD}${CL}"
echo -e "\n"
}
show_progress() {
echo -e "\n${BOLD}${BL}${TAB}Installing ProxMenux Beta: Step ${1} of ${2}${CL}"
echo
echo -e "${TAB}${BOLD}${YW}${HOLD}${3}${CL}"
}
# ── Cleanup ────────────────────────────────────────────────
cleanup() {
if [ -d "$TEMP_DIR" ]; then
rm -rf "$TEMP_DIR"
fi
}
trap cleanup EXIT
# ── Logo ───────────────────────────────────────────────────
show_proxmenux_logo() {
clear
if [[ -z "$SSH_TTY" && -z "$(who am i | awk '{print $NF}' | grep -E '([0-9]{1,3}\.){3}[0-9]{1,3}')" ]]; then
LOGO=$(cat << "EOF"
\e[0m\e[38;2;61;61;61m▆\e[38;2;60;60;60m▄\e[38;2;54;54;54m▂\e[0m \e[38;2;0;0;0m \e[0m \e[38;2;54;54;54m▂\e[38;2;60;60;60m▄\e[38;2;61;61;61m▆\e[0m
\e[38;2;59;59;59;48;2;62;62;62m▏ \e[38;2;61;61;61;48;2;37;37;37m▇\e[0m\e[38;2;60;60;60m▅\e[38;2;56;56;56m▃\e[38;2;37;37;37m▁ \e[38;2;36;36;36m▁\e[38;2;56;56;56m▃\e[38;2;60;60;60m▅\e[38;2;61;61;61;48;2;37;37;37m▇\e[48;2;62;62;62m \e[0m\e[7m\e[38;2;60;60;60m▁\e[0m
\e[38;2;59;59;59;48;2;62;62;62m▏ \e[0m\e[7m\e[38;2;61;61;61m▂\e[0m\e[38;2;62;62;62;48;2;61;61;61m┈\e[48;2;62;62;62m \e[48;2;61;61;61m┈\e[0m\e[38;2;60;60;60m▆\e[38;2;57;57;57m▄\e[38;2;48;48;48m▂\e[0m \e[38;2;47;47;47m▂\e[38;2;57;57;57m▄\e[38;2;60;60;60m▆\e[38;2;62;62;62;48;2;61;61;61m┈\e[48;2;62;62;62m \e[48;2;61;61;61m┈\e[0m\e[7m\e[38;2;60;60;60m▂\e[38;2;57;57;57m▄\e[38;2;47;47;47m▆\e[0m \e[0m
\e[38;2;59;59;59;48;2;62;62;62m▏ \e[0m\e[38;2;32;32;32m▏\e[7m\e[38;2;39;39;39m▇\e[38;2;57;57;57m▅\e[38;2;60;60;60m▃\e[0m\e[38;2;40;40;40;48;2;61;61;61m▁\e[48;2;62;62;62m \e[38;2;54;54;54;48;2;61;61;61m┊\e[48;2;62;62;62m \e[38;2;39;39;39;48;2;61;61;61m▁\e[0m\e[7m\e[38;2;60;60;60m▃\e[38;2;57;57;57m▅\e[38;2;38;38;38m▇\e[0m \e[38;2;193;60;2m▃\e[38;2;217;67;2m▅\e[38;2;225;70;2m▇\e[0m
\e[38;2;59;59;59;48;2;62;62;62m▏ \e[0m\e[38;2;32;32;32m▏\e[0m \e[38;2;203;63;2m▄\e[38;2;147;45;1m▂\e[0m \e[7m\e[38;2;55;55;55m▆\e[38;2;60;60;60m▄\e[38;2;61;61;61m▂\e[38;2;60;60;60m▄\e[38;2;55;55;55m▆\e[0m \e[38;2;144;44;1m▂\e[38;2;202;62;2m▄\e[38;2;219;68;2m▆\e[38;2;231;72;3;48;2;226;70;2m┈\e[48;2;231;72;3m \e[48;2;225;70;2m▉\e[0m
\e[38;2;59;59;59;48;2;62;62;62m▏ \e[0m\e[38;2;32;32;32m▏\e[7m\e[38;2;121;37;1m▉\e[0m\e[38;2;0;0;0;48;2;231;72;3m \e[0m\e[38;2;221;68;2m▇\e[38;2;208;64;2m▅\e[38;2;212;66;2m▂\e[38;2;123;37;0m▁\e[38;2;211;65;2m▂\e[38;2;207;64;2m▅\e[38;2;220;68;2m▇\e[48;2;231;72;3m \e[38;2;231;72;3;48;2;225;70;2m┈\e[0m\e[7m\e[38;2;221;68;2m▂\e[0m\e[38;2;44;13;0;48;2;231;72;3m \e[38;2;231;72;3;48;2;225;70;2m▉\e[0m
\e[38;2;59;59;59;48;2;62;62;62m▏ \e[0m\e[38;2;32;32;32m▏\e[0m \e[7m\e[38;2;190;59;2m▅\e[38;2;216;67;2m▃\e[38;2;225;70;2m▁\e[0m\e[38;2;95;29;0;48;2;231;72;3m \e[38;2;231;72;3;48;2;230;71;2m┈\e[48;2;231;72;3m \e[0m\e[7m\e[38;2;225;70;2m▁\e[38;2;216;67;2m▃\e[38;2;191;59;2m▅\e[0m \e[38;2;0;0;0;48;2;231;72;3m \e[38;2;231;72;3;48;2;225;70;2m▉\e[0m
\e[38;2;59;59;59;48;2;62;62;62m▏ \e[0m\e[38;2;32;32;32m▏ \e[0m \e[7m\e[38;2;172;53;1m▆\e[38;2;213;66;2m▄\e[38;2;219;68;2m▂\e[38;2;213;66;2m▄\e[38;2;174;54;2m▆\e[0m \e[38;2;0;0;0m \e[0m \e[38;2;0;0;0;48;2;231;72;3m \e[38;2;231;72;3;48;2;225;70;2m▉\e[0m
\e[38;2;59;59;59;48;2;62;62;62m▏ \e[0m\e[38;2;32;32;32m▏ \e[0m \e[38;2;0;0;0;48;2;231;72;3m \e[38;2;231;72;3;48;2;225;70;2m▉\e[0m
\e[7m\e[38;2;52;52;52m▆\e[38;2;59;59;59m▄\e[38;2;61;61;61m▂\e[0m\e[38;2;31;31;31m▏ \e[0m \e[7m\e[38;2;228;71;2m▂\e[38;2;221;69;2m▄\e[38;2;196;60;2m▆\e[0m
EOF
)
TEXT=(
""
""
"${BOLD}ProxMenux${RESET}"
""
"${BOLD}${NEON_PURPLE_BLUE}An Interactive Menu for${RESET}"
"${BOLD}${NEON_PURPLE_BLUE}Proxmox VE management${RESET}"
""
"${BOLD}${YW} ★ BETA PROGRAM ★${RESET}"
""
""
)
mapfile -t logo_lines <<< "$LOGO"
for i in {0..9}; do
echo -e "${TAB}${logo_lines[i]} ${WHITE}${RESET} ${TEXT[i]}"
done
echo -e
else
TEXT=(
"" "" "" ""
"${BOLD}ProxMenux${RESET}"
""
"${BOLD}${NEON_PURPLE_BLUE}An Interactive Menu for${RESET}"
"${BOLD}${NEON_PURPLE_BLUE}Proxmox VE management${RESET}"
""
"${BOLD}${YW} ★ BETA PROGRAM ★${RESET}"
"" "" ""
)
LOGO=(
"${DARK_GRAY}░░░░ ░░░░${RESET}"
"${DARK_GRAY}░░░░░░░ ░░░░░░ ${RESET}"
"${DARK_GRAY}░░░░░░░░░░░ ░░░░░░░ ${RESET}"
"${DARK_GRAY}░░░░ ░░░░░░ ░░░░░░ ${ORANGE}░░${RESET}"
"${DARK_GRAY}░░░░ ░░░░░░░ ${ORANGE}░░▒▒▒${RESET}"
"${DARK_GRAY}░░░░ ░░░ ${ORANGE}░▒▒▒▒▒▒▒${RESET}"
"${DARK_GRAY}░░░░ ${ORANGE}▒▒▒░ ░▒▒▒▒▒▒▒▒▒▒${RESET}"
"${DARK_GRAY}░░░░ ${ORANGE}░▒▒▒▒▒ ▒▒▒▒▒░░ ▒▒▒▒${RESET}"
"${DARK_GRAY}░░░░ ${ORANGE}░░▒▒▒▒▒▒▒░░ ▒▒▒▒${RESET}"
"${DARK_GRAY}░░░░ ${ORANGE}░░░ ▒▒▒▒${RESET}"
"${DARK_GRAY}░░░░ ${ORANGE}▒▒▒▒${RESET}"
"${DARK_GRAY}░░░░ ${ORANGE}▒▒▒░${RESET}"
"${DARK_GRAY} ░░ ${ORANGE}░░ ${RESET}"
)
for i in {0..12}; do
echo -e "${TAB}${LOGO[i]}${RESET} ${TEXT[i]}"
done
echo -e
fi
}
# ── Beta welcome message ───────────────────────────────────
show_beta_welcome() {
local width=62
local line
line=$(printf '─%.0s' $(seq 1 $width))
echo -e "${TAB}${BOLD}${YW}${line}${CL}"
echo -e "${TAB}${BOLD}${YW}${CL}${BOLD} Welcome to the ProxMenux Monitor Beta Program ${YW}${CL}"
echo -e "${TAB}${BOLD}${YW}${line}${CL}"
echo
echo -e "${TAB}${WHITE}You are about to install a ${BOLD}pre-release (beta)${RESET}${WHITE} version of${CL}"
echo -e "${TAB}${WHITE}ProxMenux Monitor, built from the ${BOLD}develop${RESET}${WHITE} branch.${CL}"
echo
echo -e "${TAB}${BOLD}${GN}What this means for you:${CL}"
echo -e "${TAB} ${GN}${CL} You'll get the latest features before the official release."
echo -e "${TAB} ${GN}${CL} Some things may not work perfectly — that's expected."
echo -e "${TAB} ${GN}${CL} Your feedback is what makes the final version better."
echo
echo -e "${TAB}${BOLD}${YW}How to report issues:${CL}"
echo -e "${TAB} ${YW}${CL} Open a GitHub Issue at:"
echo -e "${TAB} ${BL}https://github.com/MacRimi/ProxMenux/issues${CL}"
echo -e "${TAB} ${YW}${CL} Describe what happened, what you expected, and any"
echo -e "${TAB} error messages you saw. Logs help a lot:"
echo -e "${TAB} ${DARK_GRAY}journalctl -u proxmenux-monitor -n 50${CL}"
echo
echo -e "${TAB}${BOLD}${NEON_PURPLE_BLUE}Thank you for being part of the beta program!${CL}"
echo -e "${TAB}${DARK_GRAY}Your help is essential to deliver a stable and polished release.${CL}"
echo
echo -e "${TAB}${BOLD}${YW}${line}${CL}"
echo -e "${TAB}${BOLD}${YW}${CL} ${YW}${CL}"
echo -e "${TAB}${BOLD}${YW}${CL} Press ${BOLD}${GN}[Enter]${CL} to continue with the beta installation, ${YW}${CL}"
echo -e "${TAB}${BOLD}${YW}${CL} or ${BOLD}${RD}[Ctrl+C]${CL} to cancel and exit. ${YW}${CL}"
echo -e "${TAB}${BOLD}${YW}${CL} ${YW}${CL}"
echo -e "${TAB}${BOLD}${YW}${line}${CL}"
echo
read -r -p ""
echo
}
# ── Helpers ────────────────────────────────────────────────
get_server_ip() {
local ip
ip=$(ip route get 1.1.1.1 2>/dev/null | grep -oP 'src \K\S+')
[ -z "$ip" ] && ip=$(hostname -I | awk '{print $1}')
[ -z "$ip" ] && ip="localhost"
echo "$ip"
}
update_config() {
local component="$1"
local status="$2"
local timestamp
timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
mkdir -p "$(dirname "$CONFIG_FILE")"
[ ! -f "$CONFIG_FILE" ] || ! jq empty "$CONFIG_FILE" >/dev/null 2>&1 && echo '{}' > "$CONFIG_FILE"
local tmp_file
tmp_file=$(mktemp)
if jq --arg comp "$component" --arg stat "$status" --arg time "$timestamp" \
'.[$comp] = {status: $stat, timestamp: $time}' "$CONFIG_FILE" > "$tmp_file" 2>/dev/null; then
mv "$tmp_file" "$CONFIG_FILE"
else
echo '{}' > "$CONFIG_FILE"
fi
[ -f "$tmp_file" ] && rm -f "$tmp_file"
}
reset_update_flag() {
# Reset the update_available flag in config.json after successful update
[ ! -f "$CONFIG_FILE" ] && return 0
local tmp_file
tmp_file=$(mktemp)
if jq '.update_available.beta = false | .update_available.beta_version = ""' "$CONFIG_FILE" > "$tmp_file" 2>/dev/null; then
mv "$tmp_file" "$CONFIG_FILE"
fi
[ -f "$tmp_file" ] && rm -f "$tmp_file"
}
cleanup_corrupted_files() {
if [ -f "$CONFIG_FILE" ] && ! jq empty "$CONFIG_FILE" >/dev/null 2>&1; then
rm -f "$CONFIG_FILE"
fi
if [ -f "$CACHE_FILE" ] && ! jq empty "$CACHE_FILE" >/dev/null 2>&1; then
rm -f "$CACHE_FILE"
fi
}
detect_latest_appimage() {
local appimage_dir="$TEMP_DIR/AppImage"
[ ! -d "$appimage_dir" ] && return 1
local latest
latest=$(find "$appimage_dir" -name "ProxMenux-*.AppImage" -type f | sort -V | tail -1)
[ -z "$latest" ] && return 1
echo "$latest"
}
get_appimage_version() {
local filename
filename=$(basename "$1")
echo "$filename" | grep -oP 'ProxMenux-\K[0-9]+\.[0-9]+\.[0-9]+'
}
# ── Monitor install ────────────────────────────────────────
install_proxmenux_monitor() {
local appimage_source
appimage_source=$(detect_latest_appimage)
if [ -z "$appimage_source" ] || [ ! -f "$appimage_source" ]; then
msg_error "ProxMenux Monitor AppImage not found in $TEMP_DIR/AppImage/"
msg_warn "Make sure the AppImage directory exists in the develop branch."
update_config "proxmenux_monitor" "appimage_not_found"
return 1
fi
local appimage_version
appimage_version=$(get_appimage_version "$appimage_source")
systemctl is-active --quiet proxmenux-monitor.service 2>/dev/null && \
systemctl stop proxmenux-monitor.service
local service_exists=false
[ -f "$MONITOR_SERVICE_FILE" ] && service_exists=true
local sha256_file="$TEMP_DIR/AppImage/ProxMenux-Monitor.AppImage.sha256"
if [ -f "$sha256_file" ]; then
msg_info "Verifying AppImage integrity..."
local expected_hash actual_hash
expected_hash=$(grep -Eo '^[a-f0-9]+' "$sha256_file" | tr -d '\n')
actual_hash=$(sha256sum "$appimage_source" | awk '{print $1}')
if [ "$expected_hash" != "$actual_hash" ]; then
msg_error "SHA256 verification failed! The AppImage may be corrupted."
return 1
fi
msg_ok "SHA256 verification passed."
else
msg_warn "SHA256 checksum file not found. Skipping verification."
fi
msg_info "Installing ProxMenux Monitor (beta)..."
mkdir -p "$MONITOR_INSTALL_DIR"
local target_path="$MONITOR_INSTALL_DIR/ProxMenux-Monitor.AppImage"
cp "$appimage_source" "$target_path"
chmod +x "$target_path"
# Copy shutdown-notify.sh script for systemd ExecStop
local shutdown_script_src="$TEMP_DIR/scripts/shutdown-notify.sh"
local shutdown_script_dst="$MONITOR_INSTALL_DIR/scripts/shutdown-notify.sh"
if [ -f "$shutdown_script_src" ]; then
cp "$shutdown_script_src" "$shutdown_script_dst"
chmod +x "$shutdown_script_dst"
msg_ok "Shutdown notification script installed."
else
msg_warn "Shutdown script not found at $shutdown_script_src"
fi
msg_ok "ProxMenux Monitor beta v${appimage_version} installed."
if [ "$service_exists" = false ]; then
return 0
else
# Check if service needs to be updated (missing ExecStop or outdated config)
if ! grep -q "ExecStop=" "$MONITOR_SERVICE_FILE" 2>/dev/null; then
msg_info "Updating service configuration (adding shutdown notification)..."
update_monitor_service
fi
systemctl start proxmenux-monitor.service
sleep 2
if systemctl is-active --quiet proxmenux-monitor.service; then
update_config "proxmenux_monitor" "beta_updated"
return 2
else
msg_warn "Service failed to restart. Check: journalctl -u proxmenux-monitor"
update_config "proxmenux_monitor" "failed"
return 1
fi
fi
}
# Update existing service file with new configuration
update_monitor_service() {
local exec_path="$MONITOR_INSTALL_DIR/ProxMenux-Monitor.AppImage"
cat > "$MONITOR_SERVICE_FILE" << EOF
[Unit]
Description=ProxMenux Monitor - Web Dashboard (Beta)
After=network.target
Before=shutdown.target reboot.target halt.target
Conflicts=shutdown.target reboot.target halt.target
[Service]
Type=simple
User=root
WorkingDirectory=$MONITOR_INSTALL_DIR
ExecStart=$exec_path
ExecStop=/bin/bash $MONITOR_INSTALL_DIR/scripts/shutdown-notify.sh
Restart=on-failure
RestartSec=10
Environment="PORT=$MONITOR_PORT"
TimeoutStopSec=45
KillMode=mixed
KillSignal=SIGTERM
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
msg_ok "Service configuration updated."
}
create_monitor_service() {
msg_info "Creating ProxMenux Monitor service..."
local exec_path="$MONITOR_INSTALL_DIR/ProxMenux-Monitor.AppImage"
if [ -f "$TEMP_DIR/systemd/proxmenux-monitor.service" ]; then
sed "s|ExecStart=.*|ExecStart=$exec_path|g" \
"$TEMP_DIR/systemd/proxmenux-monitor.service" > "$MONITOR_SERVICE_FILE"
msg_ok "Service file loaded from repository."
else
cat > "$MONITOR_SERVICE_FILE" << EOF
[Unit]
Description=ProxMenux Monitor - Web Dashboard (Beta)
After=network.target
Before=shutdown.target reboot.target halt.target
Conflicts=shutdown.target reboot.target halt.target
[Service]
Type=simple
User=root
WorkingDirectory=$MONITOR_INSTALL_DIR
ExecStart=$exec_path
ExecStop=/bin/bash $MONITOR_INSTALL_DIR/scripts/shutdown-notify.sh
Restart=on-failure
RestartSec=10
Environment="PORT=$MONITOR_PORT"
TimeoutStopSec=45
KillMode=mixed
KillSignal=SIGTERM
[Install]
WantedBy=multi-user.target
EOF
msg_ok "Default service file created."
fi
systemctl daemon-reload
systemctl enable proxmenux-monitor.service > /dev/null 2>&1
systemctl start proxmenux-monitor.service > /dev/null 2>&1
sleep 3
if systemctl is-active --quiet proxmenux-monitor.service; then
msg_ok "ProxMenux Monitor service started successfully."
update_config "proxmenux_monitor" "beta_installed"
return 0
else
msg_warn "ProxMenux Monitor service failed to start."
echo -e "${TAB}${DARK_GRAY}Check logs : journalctl -u proxmenux-monitor -n 20${CL}"
echo -e "${TAB}${DARK_GRAY}Check status: systemctl status proxmenux-monitor${CL}"
update_config "proxmenux_monitor" "failed"
return 1
fi
}
# ── Main install ───────────────────────────────────────────
install_beta() {
local total_steps=4
local current_step=1
# ── Step 1: Dependencies ──────────────────────────────
show_progress $current_step $total_steps "Installing system dependencies"
if ! command -v jq > /dev/null 2>&1; then
apt-get update > /dev/null 2>&1
if apt-get install -y jq > /dev/null 2>&1 && command -v jq > /dev/null 2>&1; then
update_config "jq" "installed"
else
local jq_url="https://github.com/jqlang/jq/releases/download/jq-1.7.1/jq-linux-amd64"
if wget -q -O /usr/local/bin/jq "$jq_url" 2>/dev/null && chmod +x /usr/local/bin/jq \
&& command -v jq > /dev/null 2>&1; then
update_config "jq" "installed_from_github"
else
msg_error "Failed to install jq. Please install it manually and re-run."
update_config "jq" "failed"
return 1
fi
fi
else
update_config "jq" "already_installed"
fi
local BASIC_DEPS=("dialog" "curl" "git")
if [ -z "${APT_UPDATED:-}" ]; then
apt-get update -y > /dev/null 2>&1 || true
APT_UPDATED=1
fi
for pkg in "${BASIC_DEPS[@]}"; do
if ! dpkg -l | grep -qw "$pkg"; then
if apt-get install -y "$pkg" > /dev/null 2>&1; then
update_config "$pkg" "installed"
else
msg_error "Failed to install $pkg. Please install it manually."
update_config "$pkg" "failed"
return 1
fi
else
update_config "$pkg" "already_installed"
fi
done
msg_ok "Dependencies installed: jq, dialog, curl, git."
# ── Step 2: Clone develop branch ─────────────────────
((current_step++))
show_progress $current_step $total_steps "Cloning ProxMenux develop branch"
msg_info "Cloning branch '${REPO_BRANCH}' from repository..."
if ! git clone --depth 1 --branch "$REPO_BRANCH" "$REPO_URL" "$TEMP_DIR" 2>/dev/null; then
msg_error "Failed to clone branch '$REPO_BRANCH' from $REPO_URL"
exit 1
fi
msg_ok "Repository cloned successfully (branch: ${REPO_BRANCH})."
# Read beta version if available
local beta_version="unknown"
if [ -f "$TEMP_DIR/beta_version.txt" ]; then
beta_version=$(cat "$TEMP_DIR/beta_version.txt" | tr -d '[:space:]')
fi
cd "$TEMP_DIR"
# ── Step 3: Files ─────────────────────────────────────
((current_step++))
show_progress $current_step $total_steps "Creating directories and copying files"
mkdir -p "$BASE_DIR" "$INSTALL_DIR"
[ ! -f "$CONFIG_FILE" ] && echo '{}' > "$CONFIG_FILE"
# Preserve user/runtime directories that must never be overwritten
mkdir -p "$BASE_DIR/oci"
cp "./scripts/utils.sh" "$UTILS_FILE"
cp "./menu" "$INSTALL_DIR/$MENU_SCRIPT"
cp "./version.txt" "$LOCAL_VERSION_FILE" 2>/dev/null || true
# Store beta version marker
if [ -f "$TEMP_DIR/beta_version.txt" ]; then
cp "$TEMP_DIR/beta_version.txt" "$BETA_VERSION_FILE"
else
echo "$beta_version" > "$BETA_VERSION_FILE"
fi
cp "./install_proxmenux.sh" "$BASE_DIR/install_proxmenux.sh" 2>/dev/null || true
cp "./install_proxmenux_beta.sh" "$BASE_DIR/install_proxmenux_beta.sh" 2>/dev/null || true
# Wipe the scripts tree before copying so any file removed upstream
# (renamed, consolidated, deprecated) disappears from the user install.
# Only $BASE_DIR/scripts/ is cleared; config.json, cache.json,
# components_status.json, version.txt, beta_version.txt, monitor.db,
# smart/, oci/ and the AppImage live outside this path and are preserved.
rm -rf "$BASE_DIR/scripts"
mkdir -p "$BASE_DIR/scripts"
cp -r "./scripts/"* "$BASE_DIR/scripts/"
# Only .sh files need the executable bit. Applying +x recursively would
# also flag README.md, .json, .py etc. as executable for no reason.
find "$BASE_DIR/scripts" -type f -name '*.sh' -exec chmod +x {} +
if [ -d "./oci" ]; then
mkdir -p "$BASE_DIR/oci"
cp -r "./oci/"* "$BASE_DIR/oci/" 2>/dev/null || true
fi
chmod +x "$INSTALL_DIR/$MENU_SCRIPT"
[ -f "$BASE_DIR/install_proxmenux.sh" ] && chmod +x "$BASE_DIR/install_proxmenux.sh"
[ -f "$BASE_DIR/install_proxmenux_beta.sh" ] && chmod +x "$BASE_DIR/install_proxmenux_beta.sh"
# Store beta flag in config
update_config "beta_program" "active"
update_config "beta_version" "$beta_version"
update_config "install_branch" "$REPO_BRANCH"
msg_ok "Files installed. Beta version: ${beta_version}."
# ── Step 4: Monitor ───────────────────────────────────
((current_step++))
show_progress $current_step $total_steps "Installing ProxMenux Monitor (beta)"
install_proxmenux_monitor
local monitor_status=$?
if [ $monitor_status -eq 0 ]; then
create_monitor_service
elif [ $monitor_status -eq 2 ]; then
msg_ok "ProxMenux Monitor beta updated successfully."
fi
# Reset the update indicator flag after successful installation
reset_update_flag
msg_ok "Beta installation completed."
}
# ── Stable transition notice ───────────────────────────────
check_stable_available() {
# Called if a stable version is detected (future use by update logic)
# When main's version.txt > beta_version.txt, the menu/updater can call this
echo -e "\n${TAB}${BOLD}${GN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${CL}"
echo -e "${TAB}${BOLD}${GN} A stable release is now available!${CL}"
echo -e "${TAB}${WHITE} To leave the beta program and switch to the stable version,${CL}"
echo -e "${TAB}${WHITE} run the official installer:${CL}"
echo -e ""
echo -e "${TAB} ${YWB}bash -c \"\$(wget -qLO - https://raw.githubusercontent.com/MacRimi/ProxMenux/main/install_proxmenux.sh)\"${CL}"
echo -e ""
echo -e "${TAB}${DARK_GRAY} This will cleanly replace your beta install with the stable release.${CL}"
echo -e "${TAB}${BOLD}${GN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${CL}\n"
}
# ── Entry point ────────────────────────────────────────────
if [ "$(id -u)" -ne 0 ]; then
echo -e "${RD}[ERROR] This script must be run as root.${CL}"
exit 1
fi
cleanup_corrupted_files
show_proxmenux_logo
show_beta_welcome
msg_title "Installing ProxMenux Beta — branch: develop"
install_beta
# Load utils if available
[ -f "$UTILS_FILE" ] && source "$UTILS_FILE"
msg_title "ProxMenux Beta installed successfully"
if systemctl is-active --quiet proxmenux-monitor.service; then
local_ip=$(get_server_ip)
echo -e "${GN}🌐 ProxMenux Monitor (beta) is running${CL}: ${BL}http://${local_ip}:${MONITOR_PORT}${CL}"
echo
fi
echo -ne "${GN}"
type_text "To run ProxMenux, execute this command in your terminal:"
echo -e "${YWB} menu${CL}"
echo
echo -e "${TAB}${DARK_GRAY}Report issues at: https://github.com/MacRimi/ProxMenux/issues${CL}"
echo
exit 0
+4683 -1423
View File
File diff suppressed because it is too large Load Diff