11 Commits

Author SHA1 Message Date
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
8 changed files with 252 additions and 674 deletions
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
7d3df15c65411b4429e72305e9c7460d09b67c6d5bd2a50c05dd88a928fc4f94 ProxMenux-1.2.0.AppImage
3b28537fe679b87f166bd5b01de05c71d1b4303f765c87f3a23b216d433120c2 ProxMenux-1.2.0.AppImage
+250
View File
@@ -1,3 +1,253 @@
# <img src="https://raw.githubusercontent.com/MacRimi/ProxMenux/main/images/logo.png" alt="ProxMenux logo" width="40"/> ProxMenux v1.2.0 — *AI-Enhanced Monitoring*
![ProxMenux AI](https://raw.githubusercontent.com/MacRimi/ProxMenux/main/images/ProxMenux_ai.png)
This release is the culmination of the v1.1.9.1 → v1.1.9.6 beta cycle and introduces the biggest evolution of **ProxMenux Monitor** to date: AI-enhanced notifications, a redesigned multi-channel notification system, a fully reworked hardware and storage experience, and broad performance improvements across the monitoring stack. It also consolidates all recent work on the Storage, Hardware and GPU/TPU scripts.
---
## 🤖 ProxMenux Monitor — AI-Enhanced Notifications
Notifications can now be enhanced using AI to generate clear, contextual messages instead of raw technical output.
Example — instead of `backup completed exitcode=0 size=2.3GB`, AI produces: *"The web server backup completed successfully. Size: 2.3GB"*.
### What AI does
- Transforms technical notifications into readable messages
- Translates to your preferred language
- Lets you choose detail level: minimal, standard, or detailed
- Works with Telegram, Discord, Email, Pushover, and Webhooks
### What AI does NOT do
- It is **not** a chatbot or assistant
- It does **not** analyze your system or make decisions
- It does **not** have access to data beyond the notification being processed
- It does **not** execute commands or modify the server
- It does **not** store history or learn from your data
### Multi-Provider Support
Choose between 6 AI providers, each with its own API key stored independently:
- **Groq** — fast inference, generous free tier
- **Google Gemini** — excellent quality/price ratio, free tier available
- **OpenAI** — industry standard
- **Anthropic Claude** — excellent for writing and translation
- **OpenRouter** — 300+ models with a single API key
- **Ollama** — 100% local execution, no internet required
### Verified AI Models
A curated list of models (`verified_ai_models.json`) tested specifically for notification enhancement.
- **Hybrid verification**: the system fetches provider-side models and filters to only show those tested to work correctly
- **Per-Provider Model Memory**: selected model is saved per provider, so switching providers preserves each choice
- **Daily verification**: background task checks model availability and auto-migrates to a verified alternative if the current model disappears
- **Incompatible models excluded**: Whisper, TTS, image/video, embeddings, guard models, etc. are filtered out per provider
| Provider | Recommended | Also Verified |
|----------|-------------|---------------|
| Gemini | gemini-2.5-flash-lite | gemini-flash-lite-latest |
| OpenAI | gpt-4o-mini | gpt-4.1-mini |
| Groq | llama-3.3-70b-versatile | llama-3.1-70b-versatile, llama-3.1-8b-instant, llama3-70b-8192, llama3-8b-8192, mixtral-8x7b-32768, gemma2-9b-it |
| Anthropic | claude-3-5-haiku-latest | claude-3-5-sonnet-latest, claude-3-opus-latest |
| OpenRouter | meta-llama/llama-3.3-70b-instruct | meta-llama/llama-3.1-70b-instruct, anthropic/claude-3.5-haiku, google/gemini-flash-2.5-flash-lite, openai/gpt-4o-mini, mistralai/mixtral-8x7b-instruct |
| Ollama | (all local models) | No filtering — shows all installed models |
### Custom AI Prompts
Advanced users can define their own prompt for full control over formatting and translation.
- **Prompt Mode selector** — Default Prompt or Custom Prompt
- **Export / Import** — save and share custom prompts across installations
- **Example Template** — starting point to build your own prompt
- **Community Prompts** — direct link to GitHub Discussions to share templates
- Language selector is hidden in Custom Prompt mode (you define the output language in the prompt itself)
### Enriched Context
- System **uptime** is included only for error/warning events (not informational ones) — helps distinguish startup vs runtime errors
- **Event frequency** tracking — indicates recurring vs one-time issues
- **SMART disk health** data is passed for disk-related errors
- **Known Proxmox errors** database improves diagnosis accuracy
- Clearer prompt instructions to prevent AI hallucinations
---
## 📨 Notification System Redesign
- **Multi-Channel Architecture** — Telegram, Discord, Pushover, Email, and Webhook channels running simultaneously
- **Per-Event Configuration** — enable/disable specific event types per channel
- **Channel Overrides** — customize notification behaviour per channel
- **Secure Webhook Endpoint** — external systems can send authenticated notifications
- **Encrypted Storage** — API keys and sensitive data stored encrypted
- **Queue-Based Processing** — background worker with automatic retry for failed notifications
- **SQLite-Based Config Storage** — replaces file-based config for reliability
### Telegram Topics Support
Send notifications to a specific topic inside groups with Topics enabled.
- New **Topic ID** field on the Telegram channel
- Automatic detection of topic-enabled groups
- Fully backwards compatible
### ProxMenux Update Notifications
The Monitor now detects when a new ProxMenux version is released.
- **Dual-channel** — monitors both stable (`version.txt`) and beta (`beta_version.txt`)
- **GitHub integration** — compares local vs remote versions
- **Dashboard Update Indicator** — the ProxMenux logo changes to an update variant when a new version is detected (non-intrusive, no popups)
- **Persistent state** — status stored in `config.json`, reset by update scripts
- Single toggle in Settings controls both channels (enabled by default)
---
## 🖥️ Hardware Panel — Expanded Detection
The Hardware page has been significantly expanded, with better detection and richer per-device detail.
- **SCSI / SAS / RAID Controllers** — model, driver and PCI slot shown in the storage controllers section
- **PCIe Link Speed Detection** — NVMe drives show current link speed (PCIe generation and lane width), making it easy to spot drives underperforming due to limited slot bandwidth
- **Enhanced Disk Detail Modal** — NVMe, SATA, SAS, and USB drives now expose their specific fields (PCIe link info, SAS version/speed, interface type) instead of a generic view
- **Smarter Disk Type Recognition** — uniform labelling for NVMe SSDs, SATA SSDs, HDDs and removable disks
- **Hardware Info Caching** (`lspci`, `lspci -vmm`) — 5 min cache avoids repeated scans for data that doesn't change
---
## 💽 Storage Overview — Health, Observations, Exclusions
The Storage Overview has been reworked around real-time state and user-controlled tracking.
### Disk Health Status Alignment
- Badges now reflect the **current** SMART state reported by Proxmox, not a historical worst value
- **Observations preserved** — historical findings remain accessible via the "X obs." badge
- **Automatic recovery** — when SMART reports healthy again, the disk immediately shows **Healthy**
- Removed the old `worst_health` tracking that required manual clearing
### Disk Registry Improvements
- **Smart serial lookup** — when a serial is unknown the system checks for an existing entry with a serial before inserting a new one
- **No more duplicates** — prevents separate entries for the same disk appearing with/without a serial
- **USB disk support** — handles USB drives that may appear under different device names between reboots
### Storage and Network Interface Exclusions
- **Storage Exclusions** section — exclude drives from health monitoring and notifications
- **Network Interface Exclusions** — new section for excluding interfaces (bridges `vmbr`, bonds, physical NICs, VLANs) from health and notifications; ideal for intentionally disabled interfaces that would otherwise generate false alerts
- **Separate toggles** per item for Health monitoring and Notifications
### Disk Detection Robustness
- **Power-On-Hours validation** — detects and corrects absurdly large values (billions of hours) on drives with non-standard SMART encoding
- **Intelligent bit masking** — extracts the correct value from drives that pack extra info into high bytes
- **Graceful fallback** — shows "N/A" instead of impossible numbers when data cannot be parsed
---
## 🧠 Health Monitor & Error Lifecycle
### Stale Error Cleanup
Errors for resources that no longer exist are now resolved automatically.
- **Deleted VMs / CTs** — related errors auto-resolve when the resource is removed
- **Removed Disks** — errors for disconnected USB or hot-swap drives are cleaned up
- **Cluster Changes** — cluster errors clear when a node leaves the cluster
- **Log Patterns** — log-based errors auto-resolve after 48 hours without recurrence
- **Security Updates** — update notifications auto-resolve after 7 days
### Database Migration System
- **Automatic column detection** — missing columns are added on startup
- **Schema compatibility** — works with both old and new column naming conventions
- **Backwards compatible** — databases from older ProxMenux versions are supported
- **Graceful migration** — no data loss during schema updates
---
## 🧩 VM / CT Detail Modal
The VM/CT detail modal has been completely redesigned for usability.
- **Tabbed Navigation** — *Overview* (general information, status, resource usage) and *Backups* (dedicated history)
- **Visual Enhancements** — icons throughout, improved hierarchy and spacing, better VM vs CT distinction
- **Mobile Responsiveness** — adapts correctly to mobile screens in both webapp and direct browser access, no more overflow on small devices
- **Touch-Friendly Controls** — larger buttons and spacing
### Secure Gateway Modal
- **Scrollable storage list** when many destinations are available
- Mobile-adapted layout and improved visual hierarchy
### Terminal Connection
- **Reconnection loop fix** that was affecting mobile devices
- Improved WebSocket handling for mobile browsers
- More graceful connection timeout recovery
### Fail2ban & Lynis Management
- **Delete buttons** added in Settings for both tools
- Clean removal of packages and configuration files
- Confirmation dialog to prevent accidental deletion
---
## ⚡ Performance Optimizations
Major reduction in CPU usage and elimination of spikes on the Monitor.
### Staggered Polling Intervals
Collectors now run on offset schedules to prevent simultaneous execution:
| Collector | Schedule |
|-----------|----------|
| CPU sampling | Every 30s at offset 0 |
| Temperature sampling | Every 15s at offset 7s |
| Latency pings | Every 60s at offset 25s |
| Temperature record | Every 60s at offset 40s |
| Health collector | Starts at 55s offset |
| Notification polling | Health=10s, Updates=30s, ProxMenux=45s, AI=50s |
### Cached System Information
Expensive commands now cached to reduce repeated execution:
| Command | Cache TTL | Impact |
|---------|-----------|--------|
| `pveversion` | 6 hours | Eliminates 23%+ CPU spikes from Perl execution |
| `apt list --upgradable` | 6 hours | Reduces package manager queries |
| `pvesh get /cluster/resources` | 30 seconds | 6 API calls per request reduced to 1 |
| `sensors` | 10 seconds | Temperature readings cached between polls |
| `smartctl` (SMART health) | 30 minutes | Disk health checks reduced from every 5 min |
| `lspci` / `lspci -vmm` | 5 minutes | Hardware info cached (doesn't change) |
| `journalctl --since 24h` | 1 hour | Login attempts count cached (92% reduction) |
### Increased journalctl Timeouts
Prevents timeout cascades under system load:
| Query Type | Before | After |
|------------|--------|-------|
| Short-term (3-10 min) | 3s | 10s |
| Medium-term (1 hour) | 5s | 15s |
| Long-term (24 hours) | 5s | 20s |
### Reduced Polling Frequency
- `TaskWatcher` interval raised from **2s → 5s** (60% fewer checks)
### GitHub Actions
- All workflow actions upgraded to **v6** for Node.js 24 compatibility
- Deprecation warnings eliminated in CI/CD
---
## 🧰 Scripts — Storage, Hardware and GPU/TPU Work
This release also consolidates significant work on the core ProxMenux scripts.
### Storage scripts
- **SMART scheduled tests** and improved interactive SMART test workflow with clearer progress feedback
- **Disk formatting** (`format-disk.sh`) rework with safer device selection and dialog flow
- **Disk passthrough** for VMs and CTs — updated device enumeration, serial-based identification, and cleaner teardown
- **NVMe controller addition for VMs** — improved controller type selection and slot detection
- **Import disk image** — smoother path validation and progress reporting
- **Disk & storage manual guide** refresh
### Hardware / GPU / TPU scripts
- **Coral TPU installer** updated for current kernels and udev rules (Proxmox VE 8 & VE 9)
- **NVIDIA installer** — cleaner driver installation, kernel header handling, and VM/LXC attachment flow
- **GPU mode switch** (direct and interactive variants) — safer switching between iGPU modes
- **Add GPU to VM / LXC** — unified selection dialogs and permission handling
- **Intel / AMD GPU tools** kept in sync with the new shared patterns
- **Hardware & graphics menu** restructured for consistency with the rest of ProxMenux
---
## 2026-03-14
### New version v1.1.9 — *Helper Scripts Catalog Rebuilt*
-1
View File
@@ -160,7 +160,6 @@ Contributions, bug reports and feature suggestions are welcome!
- 💡 [Suggest a feature](https://github.com/MacRimi/ProxMenux/discussions)
- 🔀 [Submit a pull request](https://github.com/MacRimi/ProxMenux/pulls)
If you find ProxMenux useful, consider giving it a ⭐ on GitHub — it helps others discover the project!
---
-1
View File
@@ -1 +0,0 @@
1.1.9.5
-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
+1 -1
View File
@@ -1 +1 @@
1.1.9
1.2.0