github MacRimi/ProxMenux v1.2.4

4 hours ago

ProxMenux logo ProxMenux v1.2.4

Adds two in-dashboard improvements (Update Now button + mobile PWA install prompt), extends the Backups restore flow with atomic pmxcfs (config.db) snapshots and automatic ZFS data-pool import, sharpens Log2RAM behaviour on PBS-as-a-service hosts, hardens the firewall bridge sysctl tuning across VM lifecycle events, narrows the ZFS ARC optimization to its own scope, makes the persistent NIC naming idempotent, rebuilds DKMS drivers automatically when a new kernel is staged, keeps the Monitor terminal session intact when a ProxMenux update is available, and reinforces five notification templates + three Health panel checks.

✨ What's new

  • Update Now button in the Health Monitor → System Updates section. Runs proxmox_update.sh in an in-dashboard terminal (apt update + dist-upgrade + post-cleanup). On close it forces a fresh Health scan (/api/health/full?refresh=1) so the pending-update count and kernel row reflect the post-update state right away instead of the cached pre-update value. Only appears when there are pending updates.
  • In-app Install prompt for mobile — bottom-sheet with iOS Safari / Android instructions. "Not now" (30d) or "Don't show again" (permanent, localStorage).
  • Safe update flow — new scripts/global/update-pve-safe.sh invoked by the Update Now button and the CLI utility. Respects user-authored repos (never disables enterprise/ceph, never purges alternate NTP, never force-installs zfsutils/chrony); on a bare host lays down only the missing base repos via ensure_repositories. Detects a newly installed kernel that isn't the running one (via dpkg-query) and prompts for reboot even when needrestart isn't installed. cleanup_duplicate_repos reworked to compare URI + Suite + Component exactly against proxmox.sources / debian.sources and only touch a fixed allowlist of legacy pve-*.list files — so custom download.proxmox.com/* entries (PBS server on host, local mirror) survive intact.
  • is_apt_active_on_host() — gate in _check_service_failure that suppresses service_fail notifications while apt/dpkg is running (marker + fuser on dpkg-lock-frontend + 60s grace). PVE services restarted as part of the upgrade cycle stay quiet during the window.

🔔 Notification content — five rendering refinements

  • Backup destination shown — vzdump emails/Telegram carry the --storage target in title + body row, so users with several PBS/Local destinations can tell at a glance which one produced the event.
  • Migration bodies carry the real target node — pulled from the PVE task log for qmigrate / vzmigrate events.
  • Snapshot bodies carry the real snapshot name — pulled from the PVE task log for qmsnapshot / vzsnapshot events.
  • Generic system_problem notifications include the PVE payload message as the reason.
  • NVIDIA / Coral driver update emails render the New Version row correctly by aligning the template placeholder with the field the renderer reads.

🩹 Health panel — three checks reinforced

  • Dismiss now silences storage alerts — the acknowledge flow includes storage_unavailable_*, mount_stale, mount_readonly, lxc_disk_low_*, lxc_mount_low_*, pve_storage_full_* and zfs_pool_full_* under the storage category, and the storage cache is invalidated on dismiss so the panel refreshes immediately.
  • VMs & Containers check tolerates NULL details rows (#255) — _check_vms_cts_with_persistence coalesces persisted errors with a missing details column to an empty dict before reading nested keys, so a single sparse row no longer takes the whole VM/CT check offline.
  • system_startup fires once per boot_check_startup_aggregation now marks aggregation as done right after queuing the event, so the boot summary lands one time regardless of how many polling ticks fit inside the current session.

🛠 Mobile & webhook

  • Mobile dashboard polling stays live on HTTPS + reverse proxy setupspwa-register.tsx auto-unregisters any Service Worker on load, and the PWA installability path is now driven by the new in-app install prompt described above.
  • Webhook auth trusts every host-local IP — the internal webhook accepts requests from any interface IP the host owns (Tailscale, WireGuard, LAN, IPv6, including v4-mapped IPv6 ::ffff:x.x.x.x that Flask emits on dual-stack binds), so PVE Test buttons work over any of them.

🛡 Update flow — Safe path when launched from the Monitor terminal

  • The Monitor's WebSocket terminal now identifies itself via PROXMENUX_TERMINAL=monitor, inherited by every child shell it spawns.
  • When menu detects a new ProxMenux version and the session is running from that terminal, the yes/no update prompt is replaced by an informational msgbox naming the new version and pointing to the canonical bash -c "$(wget -qLO - …)" one-liner to run from SSH / the host console. The menu keeps working — the user can continue using ProxMenux from the current terminal; only the update path is routed to a session that survives the Monitor service restart.
  • Same guard on the release-channel switch in Settings → Release Channel (config_menu.sh). Selecting Stable ↔ Beta from the Monitor terminal shows the informational msgbox with the exact wget one-liner for the target channel and returns to the menu instead of running the installer in place.
  • SSH sessions, the Proxmox host console, and any environment where PROXMENUX_TERMINAL isn't monitor keep the previous yes/no prompt and can update or switch channels as always.

🔧 Update flow — DKMS drivers rebuilt when a new kernel lands

  • update-pve-safe.sh (Update Now button in the Health Monitor and the CLI utility that delegates to it) now rebuilds ProxMenux-installed DKMS drivers whenever apt full-upgrade stages a kernel newer than the one currently running. Detects the case via dpkg-query on proxmox-kernel-* / pve-kernel-* vs uname -r. Installs the matching headers (proxmox-headers-<newkver> or pve-headers-<newkver>) if missing, runs dkms autoinstall -k <newkver>, then verifies each expected module (gasket for Coral, nvidia for the NVIDIA driver) actually reached installed for the new kernel. If any module was left behind, falls back to each installer's --auto-reinstall path.
  • Whiptail msgbox announces the rebuild before it runs — single OK button, no yes/no. Names the incoming kernel and the components that will be rebuilt, so the user sees what's coming without a false "cancel" option that would leave the system with dead drivers at boot. Non-interactive runs (cron, headless) skip the msgbox and log the same information.
  • Only components already registered as installed in components_status.json are considered. Hosts without NVIDIA / Coral drivers see no msgbox and no rebuild step.
  • Shared helper pmx_rebuild_dkms_after_kernel lives in scripts/global/utils-install-functions.sh, so the CLI utility (utilities/proxmox_update.sh) inherits the behaviour by delegation and no other call site needs to duplicate the logic.

🔌 Post-install — Persistent NIC naming becomes idempotent

  • ProxMenux-owned .link files now carry a distinctive prefix (10-proxmenux-<iface>.link) and a first-line marker (# Managed by ProxMenux — do not edit) so the reconciliation and uninstall paths can identify their own files with certainty and leave every other .link in /etc/systemd/network/ (user-authored, other packages) strictly alone.
  • Reruns reconcile stale ProxMenux entries. On every execution the function walks the existing 10-proxmenux-*.link files, compares the recorded MACAddress= against the MACs currently present under /sys/class/net/, and removes only the ProxMenux-owned entries whose MAC is gone. Replacing or migrating a NIC no longer leaves an orphan mapping behind.
  • Legacy 1.0-format files (10-<iface>.link with the plain two-section template) are migrated automatically on the first run of 1.1, so an existing install ends up on the new naming without leaving duplicates or manual cleanup for the user.
  • The uninstall path now only removes files that carry both the 10-proxmenux- filename prefix and the marker on the first line. The previous blanket rm -f *.link is gone — anything the user wrote by hand or that came from another package is preserved.
  • Single shared implementation in scripts/global/utils-install-functions.sh (pmx_setup_persistent_network + pmx_uninstall_persistent_network). The three call sites (auto_post_install.sh, customizable_post_install.sh, network_menu.sh) plus the uninstall path all delegate to the same helper, so the logic can't drift across variants any more.
  • FUNC_VERSION bumped 1.0 → 1.1 so the update detector re-runs the function on hosts installed with 1.0 — that first re-run performs the legacy migration and the reconciliation in one shot.

🧮 Post-install — ZFS ARC optimization narrowed to its scope

  • optimize_zfs_arc now sets only zfs_arc_maxzfs_arc_min stays managed by OpenZFS defaults, and the L2ARC (l2arc_noprefetch, l2arc_write_max) and TXG (zfs_txg_timeout) tunables that the previous implementation wrote unconditionally are no longer touched. The function does exactly what its name says: caps the ARC maximum.
  • update-initramfs -u -k all runs after writing /etc/modprobe.d/99-zfsarc.conf (plus proxmox-boot-tool refresh on systemd-boot hosts), so on ZFS-on-root systems the new cap actually takes effect on the next boot instead of being shadowed by the initramfs's stale copy.
  • Guarded on live pools — the function short-circuits when no ZFS pool is present, so nothing gets written on a host that doesn't use ZFS.
  • Cap uses clean binary sizes — 512 MiB for hosts up to 16 GB RAM, 1 GiB up to 32 GB, RAM/8 above that (never below 512 MiB).
  • FUNC_VERSION bumped 1.0 → 1.1 so the update detector re-runs the function on existing installs; the fresh write of 99-zfsarc.conf cleans out any leftover L2ARC/TXG lines from earlier runs. Uninstall path also runs update-initramfs + proxmox-boot-tool refresh so restoring or removing the tuning is picked up at boot too.

🔥 Post-install — Firewall bridge sysctl tuning hardened

  • rp_filter=0 / log_martians=0 on fwbr*, fwln*, fwpr*, tap* now applies to interfaces Proxmox creates on every VM start / stop / reboot / migrate. New /etc/udev/rules.d/99-proxmenux-fwbr-tune.rules fires a helper on each matching net/add event, so fresh interfaces pick up the value immediately — no reboot, no rerun.
  • Tuning logic centralised in /usr/local/sbin/proxmenux-fwbr-tune — shared by the initial sweep (proxmenux-fwbr-tune.service, oneshot) and the udev rule. Explicit invocation at install time so the current session sees the change without waiting for the next VM cycle.
  • Customizable post-install flow now installs the same helper + service + udev rule + initial sweep as the automatic flow — both variants leave the system in the same end state.
  • Both apply_network_optimizations bumped FUNC_VERSION 1.0 → 1.1 so the update detector re-runs them. Uninstall extended to remove the helper and udev rule and reload udev.

🧰 Post-install — Log2RAM + PBS

  • PBS API log rotation applied when proxmox-backup-server runs as a service on the same host. Both install_log2ram_auto and configure_log2ram now drop /etc/logrotate.d/proxmox-backup-api + /etc/cron.hourly/proxmox-backup-logrotate so access.log and auth.log stay bounded at 20MB × 3 rotations — hourly cadence keeps the tmpfs backing Log2RAM comfortably under budget on hosts where pvestatd polls the local datastore every few seconds. No-op on hosts without PBS.
  • Upstream log2ram script patched to rsync -aXv --no-acls. Both installers rewrite the call in place right after install.sh runs, so log2ram write finishes cleanly on /var/log.hdd filesystems that don't accept POSIX ACLs (ZFS with acltype=off, ext4 without the acl option). Guarded by grep -q so a future upstream release that already dropped -A isn't patched again.
  • Emergency block in log2ram-check.sh rotates PBS logs before truncating. When /var/log crosses the 92% threshold, the script runs logrotate -f /etc/logrotate.d/proxmox-backup-api (only if the rule exists) before the existing pveproxy / pveam truncate — recent PBS access/auth history is preserved in the rotated .gz files instead of being lost. Both FUNC_VERSION bumped 1.2 → 1.3.

🗄 Backup restore — pmxcfs / ZFS data pools

  • /var/lib/pve-cluster/config.db is captured via sqlite3 .backup — the canonical way to snapshot the pmxcfs SQLite store consistently with pve-cluster running, matching Proxmox's own documented advice. The raw file is skipped from the general rsync so nothing overwrites the atomic dump. A raw-fallback copy is kept when sqlite3 isn't installed, and the recovery helper promotes it to config.db automatically. The restore path continues to use the canonical stop pve-cluster → cp → start pattern with the DB the user brings back now guaranteed consistent.
  • Data pools listed in the backup are now imported automatically during restore. New _rs_import_data_pools step runs after config apply, iterates storage_inventory.zfs_pools[] and does zpool import <name> for every non-root pool whose disks are all present on this host. On a foreign hostid (fresh PVE install regrabbed the label) it retries with -f and flags the pool as forced so the user has trace. Pools with missing disks are skipped with a clear warning.
  • Result persists to the post-restore progress card. The auto-import writes a data_pools_import section into /var/lib/proxmenux/restore-state.json and a raw log at /var/log/proxmenux/restore-datapools-<timestamp>.log. The Backups tab card renders a dedicated block (Imported / Forced / Skipped partial / Skipped missing / Failed) so the summary stays consultable after the restore terminal is closed.
  • Recognises pools created with by-partuuid or raw /dev/sdX — the auto-import step and validate_storage.sh treat devices_by_id entries starting with / as absolute paths, so pools built against partition UUIDs or raw block devices are detected as present when their disks are on the host.
  • /etc/systemd/network added to the default backup paths. That directory holds systemd .link files that pin NIC names to their MAC — setup_persistent_network in the post_install writes them, and users can drop their own. Preserving them across a fresh-install restore keeps the source host's NIC naming policy intact on the target.

🙏 Acknowledgments

  • @PepenAI — mobile dashboard on HTTPS + reverse proxy
  • Pepo — webhook auth from a Tailscale FQDN
  • @ash34 (#255) — VM/CT check with a NULL details row
  • @f3rs3n (#256, #257, #258) — firewall bridge sysctl tuning, ZFS ARC optimization scope, persistent NIC naming reconciliation
  • Juan C. — ZFS data pool auto-import after a fresh install
  • David Barbero (@sikete) — DKMS driver rebuild on kernel upgrade

Don't miss a new ProxMenux release

NewReleases is sending notifications on new releases.