update beta ProxMenux 1.2.1.1-beta

This commit is contained in:
MacRimi
2026-05-09 18:59:59 +02:00
parent 5ed1fc44fd
commit 2f919de9e3
125 changed files with 16506 additions and 2877 deletions
+1 -1
View File
@@ -4,7 +4,7 @@
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : MIT
# License : GPL-3.0
# Version : 1.0
# Last Updated: 08/04/2026
# ==========================================================
@@ -4,7 +4,7 @@
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : MIT
# License : GPL-3.0
# Version : 1.0
# Last Updated: 08/04/2026
# ==========================================================
+1 -1
View File
@@ -5,7 +5,7 @@
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : MIT
# License : GPL-3.0
# Version : 1.3-dialog
# Last Updated: 13/12/2024
# ==========================================================
+1 -1
View File
@@ -5,7 +5,7 @@
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : MIT
# License : GPL-3.0
# Version : 1.0
# Last Updated: 11/04/2026
# ==========================================================
+198 -7
View File
@@ -5,8 +5,18 @@ if [[ -n "${__PROXMENUX_GPU_HOOK_GUARD_HELPERS__}" ]]; then
fi
__PROXMENUX_GPU_HOOK_GUARD_HELPERS__=1
PROXMENUX_GPU_HOOK_STORAGE_REF="local:snippets/proxmenux-gpu-guard.sh"
PROXMENUX_GPU_HOOK_ABS_PATH="/var/lib/vz/snippets/proxmenux-gpu-guard.sh"
# Issue #195: snippets used to live at the hard-coded `local:snippets/`
# path, which broke LXC/VM migration between cluster nodes — `local` is
# node-specific, so the hookscript reference was dangling on the target
# node. The path now resolves dynamically through
# `_resolve_snippets_storage` and is cached per-process. Callers should
# invoke `_compute_snippets_paths` (interactive flag optional) before
# referencing the two PROXMENUX_GPU_HOOK_* variables.
PROXMENUX_GPU_HOOK_FILENAME="proxmenux-gpu-guard.sh"
PROXMENUX_GPU_HOOK_STORAGE_REF=""
PROXMENUX_GPU_HOOK_ABS_PATH=""
PROXMENUX_CONFIG_JSON="${PROXMENUX_CONFIG_JSON:-/usr/local/share/proxmenux/config.json}"
_gpu_guard_msg_warn() {
if declare -F msg_warn >/dev/null 2>&1; then
@@ -24,6 +34,164 @@ _gpu_guard_msg_ok() {
fi
}
# ────────────────────────────────────────────────────────────────────
# Snippets storage resolution (issue #195)
# ────────────────────────────────────────────────────────────────────
_save_snippets_storage_preference() {
local storage="$1"
command -v jq >/dev/null 2>&1 || return 0
mkdir -p "$(dirname "$PROXMENUX_CONFIG_JSON")" 2>/dev/null || true
[[ -f "$PROXMENUX_CONFIG_JSON" ]] || echo "{}" > "$PROXMENUX_CONFIG_JSON"
jq --arg s "$storage" '.snippets_storage = $s' "$PROXMENUX_CONFIG_JSON" \
> "${PROXMENUX_CONFIG_JSON}.tmp" 2>/dev/null \
&& mv "${PROXMENUX_CONFIG_JSON}.tmp" "$PROXMENUX_CONFIG_JSON"
}
# Decide which PVE storage backs ProxMenux snippets (hookscripts).
#
# Outcomes (in order):
# 1. Cached resolution in this shell → reuse, no work.
# 2. No active storage with content=snippets → fall back to "local".
# 3. Single candidate (standalone host with only `local`) → use it silently.
# 4. Multiple candidates + saved preference → use saved.
# 5. Multiple candidates, no preference, $1 == "interactive" + whiptail
# available → prompt the user, save the choice, use it.
# 6. Otherwise (non-interactive auto-call from sync_*, cron, etc.) →
# use the first listed candidate. Avoids blocking on a dialog from
# a non-tty context.
_list_snippets_candidates() {
pvesm status -content snippets 2>/dev/null \
| awk 'NR>1 && $3=="active" {print $1}'
}
# PVE 9 ships `local` without `snippets` in its content list, so a fresh
# install has zero candidates and ProxMenux can't write a hookscript
# anywhere. This silently appends `snippets` to local's content set so
# the GPU passthrough flow works out of the box. We only touch `local`
# (the always-present default storage) and only when there's nothing
# else to choose — never modifies a custom storage definition.
_ensure_local_supports_snippets() {
local current
current=$(pvesh get /storage/local --output-format json 2>/dev/null | jq -r '.content // empty' 2>/dev/null)
[[ -z "$current" ]] && return 1
echo "$current" | tr ',' '\n' | grep -qx 'snippets' && return 0
local new_content="${current},snippets"
if pvesm set local --content "$new_content" >/dev/null 2>&1; then
_gpu_guard_msg_ok "Enabled 'snippets' on the 'local' storage so ProxMenux can install hookscripts."
return 0
fi
return 1
}
_resolve_snippets_storage() {
local interactive="${1:-}"
if [[ -n "${__PROXMENUX_RESOLVED_SNIPPETS_STORAGE:-}" ]]; then
echo "$__PROXMENUX_RESOLVED_SNIPPETS_STORAGE"
return 0
fi
local candidates
candidates=$(_list_snippets_candidates)
if [[ -z "$candidates" ]]; then
# Fresh PVE 9 host — `local` doesn't include `snippets` by default.
# Auto-enable it; if that succeeds, re-list and continue.
if _ensure_local_supports_snippets; then
candidates=$(_list_snippets_candidates)
fi
fi
if [[ -z "$candidates" ]]; then
# Still nothing usable — fall back to `local` and let the caller
# surface the error if writing actually fails.
__PROXMENUX_RESOLVED_SNIPPETS_STORAGE="local"
echo "local"
return 0
fi
local count
count=$(echo "$candidates" | wc -l)
if [[ "$count" -eq 1 ]]; then
__PROXMENUX_RESOLVED_SNIPPETS_STORAGE="$candidates"
echo "$candidates"
return 0
fi
if [[ -f "$PROXMENUX_CONFIG_JSON" ]] && command -v jq >/dev/null 2>&1; then
local pref
pref=$(jq -r '.snippets_storage // empty' "$PROXMENUX_CONFIG_JSON" 2>/dev/null)
if [[ -n "$pref" ]] && echo "$candidates" | grep -qFx "$pref"; then
__PROXMENUX_RESOLVED_SNIPPETS_STORAGE="$pref"
echo "$pref"
return 0
fi
fi
if [[ "$interactive" == "interactive" ]] && command -v whiptail >/dev/null 2>&1; then
local options=()
local first_pick=1
while IFS= read -r s; do
[[ -z "$s" ]] && continue
if [[ $first_pick -eq 1 ]]; then
options+=("$s" "" "ON")
first_pick=0
else
options+=("$s" "" "OFF")
fi
done <<< "$candidates"
local choice
choice=$(whiptail --backtitle "ProxMenux" \
--title "Snippets storage (used by hookscripts)" \
--radiolist \
"Pick the storage where ProxMenux installs snippets/hookscripts.\n\nFor cluster setups, choose a shared NFS/CIFS storage so VMs and LXCs migrate cleanly between nodes — \`local\` is node-specific and breaks migration." \
20 78 8 \
"${options[@]}" 3>&1 1>&2 2>&3) || choice=""
if [[ -n "$choice" ]] && echo "$candidates" | grep -qFx "$choice"; then
_save_snippets_storage_preference "$choice"
__PROXMENUX_RESOLVED_SNIPPETS_STORAGE="$choice"
echo "$choice"
return 0
fi
fi
local first
first=$(echo "$candidates" | head -n 1)
__PROXMENUX_RESOLVED_SNIPPETS_STORAGE="$first"
echo "$first"
}
# Populate the two PROXMENUX_GPU_HOOK_* variables from whichever storage
# `_resolve_snippets_storage` returns. Idempotent — safe to call multiple
# times, the resolver is cached per-process.
_compute_snippets_paths() {
local interactive="${1:-}"
local storage
storage=$(_resolve_snippets_storage "$interactive")
PROXMENUX_GPU_HOOK_STORAGE_REF="${storage}:snippets/${PROXMENUX_GPU_HOOK_FILENAME}"
# `pvesm path` understands the storage:content/file syntax for any
# registered storage and returns the absolute filesystem path — works
# for `local`, NFS, CIFS, dir, etc. Falls back to the conventional
# mount point if pvesm doesn't resolve (very old PVE / mid-mount
# transitions).
local abs
abs=$(pvesm path "$PROXMENUX_GPU_HOOK_STORAGE_REF" 2>/dev/null)
if [[ -n "$abs" ]]; then
PROXMENUX_GPU_HOOK_ABS_PATH="$abs"
elif [[ "$storage" == "local" ]]; then
PROXMENUX_GPU_HOOK_ABS_PATH="/var/lib/vz/snippets/${PROXMENUX_GPU_HOOK_FILENAME}"
else
PROXMENUX_GPU_HOOK_ABS_PATH="/mnt/pve/${storage}/snippets/${PROXMENUX_GPU_HOOK_FILENAME}"
fi
}
_gpu_guard_has_vm_gpu() {
local vmid="$1"
qm config "$vmid" 2>/dev/null | grep -qE '^hostpci[0-9]+:'
@@ -37,7 +205,13 @@ _gpu_guard_has_lxc_gpu() {
}
ensure_proxmenux_gpu_guard_hookscript() {
mkdir -p /var/lib/vz/snippets 2>/dev/null || true
# Issue #195: resolve which snippets storage to write to (interactive
# — this function is called from the GPU passthrough flow which is
# always run from a tty). The resolver caches its answer for the rest
# of the bash session, so subsequent attach_* calls reuse it.
_compute_snippets_paths "interactive"
mkdir -p "$(dirname "$PROXMENUX_GPU_HOOK_ABS_PATH")" 2>/dev/null || true
cat >"$PROXMENUX_GPU_HOOK_ABS_PATH" <<'HOOKEOF'
#!/usr/bin/env bash
@@ -229,6 +403,12 @@ attach_proxmenux_gpu_guard_to_vm() {
local vmid="$1"
_gpu_guard_has_vm_gpu "$vmid" || return 0
# Resolver cache populated by ensure_* (or the first call here).
# Pass "interactive" so a sync done in isolation can still prompt;
# sync_proxmenux_gpu_guard_hooks pre-seeds the cache to suppress the
# dialog when running non-interactively.
_compute_snippets_paths "interactive"
local current
current=$(qm config "$vmid" 2>/dev/null | awk '/^hookscript:/ {print $2}')
if [[ "$current" == "$PROXMENUX_GPU_HOOK_STORAGE_REF" ]]; then
@@ -236,9 +416,9 @@ attach_proxmenux_gpu_guard_to_vm() {
fi
if qm set "$vmid" --hookscript "$PROXMENUX_GPU_HOOK_STORAGE_REF" >/dev/null 2>&1; then
_gpu_guard_msg_ok "PCIe passthrough guard attached to VM ${vmid}"
_gpu_guard_msg_ok "PCIe passthrough guard attached to VM ${vmid} (${PROXMENUX_GPU_HOOK_STORAGE_REF})"
else
_gpu_guard_msg_warn "Could not attach PCIe passthrough guard to VM ${vmid}. Ensure 'local' storage supports snippets."
_gpu_guard_msg_warn "Could not attach PCIe passthrough guard to VM ${vmid}. Verify ${__PROXMENUX_RESOLVED_SNIPPETS_STORAGE} storage supports snippets."
fi
}
@@ -246,6 +426,8 @@ attach_proxmenux_gpu_guard_to_lxc() {
local ctid="$1"
_gpu_guard_has_lxc_gpu "$ctid" || return 0
_compute_snippets_paths "interactive"
local current
current=$(pct config "$ctid" 2>/dev/null | awk '/^hookscript:/ {print $2}')
if [[ "$current" == "$PROXMENUX_GPU_HOOK_STORAGE_REF" ]]; then
@@ -253,13 +435,22 @@ attach_proxmenux_gpu_guard_to_lxc() {
fi
if pct set "$ctid" -hookscript "$PROXMENUX_GPU_HOOK_STORAGE_REF" >/dev/null 2>&1; then
_gpu_guard_msg_ok "PCIe passthrough guard attached to LXC ${ctid}"
_gpu_guard_msg_ok "PCIe passthrough guard attached to LXC ${ctid} (${PROXMENUX_GPU_HOOK_STORAGE_REF})"
else
_gpu_guard_msg_warn "Could not attach PCIe passthrough guard to LXC ${ctid}. Ensure 'local' storage supports snippets."
_gpu_guard_msg_warn "Could not attach PCIe passthrough guard to LXC ${ctid}. Verify ${__PROXMENUX_RESOLVED_SNIPPETS_STORAGE} storage supports snippets."
fi
}
# Iterate every VM/LXC and reattach the guard if it has GPU passthrough
# but no current hookscript reference. Used for cluster-wide sync /
# upgrades. Runs non-interactively: pre-seeds the resolver cache so the
# inner attach_* calls don't pop a dialog from a possibly headless
# context.
sync_proxmenux_gpu_guard_hooks() {
if [[ -z "${__PROXMENUX_RESOLVED_SNIPPETS_STORAGE:-}" ]]; then
__PROXMENUX_RESOLVED_SNIPPETS_STORAGE=$(_resolve_snippets_storage "")
fi
ensure_proxmenux_gpu_guard_hookscript
local vmid ctid
+1 -1
View File
@@ -2,7 +2,7 @@
# ProxMenux - Shared Common Functions
# ============================================
# Author : MacRimi
# License : MIT
# License : GPL-3.0
# Version : 1.0
# Last Updated: 29/01/2026
# ============================================
+27 -5
View File
@@ -1,11 +1,33 @@
#!/bin/bash
# ProxMenux - Universal GPU/iGPU Passthrough to LXC
# ==================================================
# ==========================================================
# ProxMenux - GPU / iGPU Passthrough to LXC
# ==========================================================
# Author : MacRimi
# License : MIT
# Copyright : (c) 2024 MacRimi
# License : GPL-3.0
# Version : 1.0
# Last Updated: 01/04/2026
# ==================================================
# ==========================================================
# Description:
# Shares a physical GPU (Intel iGPU, AMD or NVIDIA) with an
# LXC container on Proxmox VE. Unlike VM passthrough, the
# host keeps using the GPU — containers access it through
# device nodes, not via VFIO binding.
#
# Features:
# - Multi-vendor detection (Intel / AMD / NVIDIA)
# - Multi-GPU selection via checklist
# - Switch Mode: detects GPU bound to vfio-pci (VM) and
# offers to free it before LXC passthrough
# - SR-IOV check (blocks unsupported configurations)
# - Automatic dev-node enumeration (DRI, KFD, NVIDIA)
# - GID alignment (video / render) between host and CT
# - Distro-aware driver install inside the container
# (Alpine / Arch / Debian-Ubuntu / NVIDIA .run fallback)
# - NVIDIA userspace version matched to host driver
# - Container memory bump during NVIDIA install (restored)
# - Optional GPU guard hookscript integration
# ==========================================================
LOCAL_SCRIPTS="/usr/local/share/proxmenux/scripts"
BASE_DIR="/usr/local/share/proxmenux"
@@ -814,7 +836,7 @@ _get_iommu_group_ids() {
local dev dev_class
dev=$(basename "$dev_path")
dev_class=$(cat "/sys/bus/pci/devices/${dev}/class" 2>/dev/null)
[[ "$dev_class" == "0x0604" || "$dev_class" == "0x0600" ]] && continue
[[ "$dev_class" == 0x0604* || "$dev_class" == 0x0600* ]] && continue
local vid did
vid=$(cat "/sys/bus/pci/devices/${dev}/vendor" 2>/dev/null | sed 's/0x//')
did=$(cat "/sys/bus/pci/devices/${dev}/device" 2>/dev/null | sed 's/0x//')
+1 -1
View File
@@ -1112,7 +1112,7 @@ analyze_iommu_group() {
# Skip PCI bridges and host bridges (class 0x0604 / 0x0600)
local dev_class
dev_class=$(cat "/sys/bus/pci/devices/${dev}/class" 2>/dev/null)
if [[ "$dev_class" == "0x0604" || "$dev_class" == "0x0600" ]]; then
if [[ "$dev_class" == 0x0604* || "$dev_class" == 0x0600* ]]; then
continue
fi
+1 -1
View File
@@ -2,7 +2,7 @@
# ProxMenux - AMD GPU Tools Installer
# ============================================
# Author : MacRimi
# License : MIT
# License : GPL-3.0
# Version : 1.0
# Last Updated: 29/01/2026
# ============================================
+27 -26
View File
@@ -1,34 +1,35 @@
#!/bin/bash
# ==========================================================
# ProxMenux - Coral TPU Installer (unified: PCIe/M.2 + USB)
# =========================================================
# ==========================================================
# Author : MacRimi
# License : MIT
# Version : 2.0 (unified PCIe+USB; auto-detect; feranick fork; libedgetpu runtime)
# Copyright : (c) 2024 MacRimi
# License : GPL-3.0
# Version : 2.0
# Last Updated: 17/04/2026
# =========================================================
# ==========================================================
# Description:
# Single entry point for every Coral variant. At startup the
# script detects what Coral hardware is present on the host
# and installs only what is actually needed.
#
# One entry point for every Coral variant. At startup the script detects
# what Coral hardware is present on the host and installs only what is
# actually needed:
#
# • Coral M.2 / Mini-PCIe (vendor 1ac1 on PCIe)
# → build and install `gasket` + `apex` kernel modules via DKMS
# (feranick/gasket-driver fork; google as fallback with patches)
# → create apex group + udev rules
# → reboot required to load the fresh kernel module
#
# • Coral USB Accelerator (USB IDs 1a6e:089a / 18d1:9302)
# → add the Google Coral APT repository (signed-by keyring)
# → install libedgetpu1-std (Edge TPU runtime)
# → udev rules come with the package
# → no reboot required
#
# • Both present → both paths are run in sequence
# • Neither present → informative dialog and clean exit
#
# The script is idempotent: reruns on already-configured hosts skip work
# that is already done and recover from broken gasket-dkms package state
# (typical after a kernel upgrade on PVE 9).
# Features:
# - Auto-detection of M.2 / Mini-PCIe (vendor 1ac1) and
# USB (1a6e:089a / 18d1:9302) Accelerators in one pass
# - PCIe path: builds gasket + apex kernel modules via DKMS
# using feranick/gasket-driver fork (actively maintained),
# google/gasket-driver as fallback with kernel patches
# - Kernel-aware patches applied only when needed
# (no_llseek → noop_llseek on 6.5+, MODULE_IMPORT_NS
# string form on 6.13+)
# - apex system group + udev rules for /dev/apex_* nodes
# - USB path: Google Coral APT repo (signed-by keyring) +
# libedgetpu1-std runtime (udev rules ship with package)
# - Both variants present → both paths run in sequence
# - Idempotent: reruns skip work already done, recovers
# from broken gasket-dkms state after PVE 9 kernel upgrades
# - Reboot prompted only when the PCIe path ran
# ==========================================================
# Guarantee a valid working directory before anything else. When the user
# re-runs the installer from a previous /tmp/gasket-driver/... path that our
+66 -31
View File
@@ -1,39 +1,41 @@
#!/bin/bash
# ==========================================================
# ProxMenux - A menu-driven script for Proxmox VE management
# ProxMenux - Coral TPU Passthrough to LXC
# ==========================================================
# Author : MacRimi
# Revision : @Blaspt (USB passthrough via udev rule with persistent /dev/coral)
# Revision : @Blaspt (USB passthrough via udev rule)
# Copyright : (c) 2024 MacRimi
# License : (GPL-3.0) (https://github.com/MacRimi/ProxMenux/blob/main/LICENSE)
# Version : 1.4 (unprivileged container support, PVE dev API for apex/iGPU)
# License : GPL-3.0
# Version : 1.4
# Last Updated: 01/04/2026
# ==========================================================
# Description:
# This script automates the configuration and installation of
# Coral TPU and iGPU support in Proxmox VE containers. It:
# - Configures a selected LXC container for hardware acceleration
# - Installs and sets up Coral TPU drivers on the Proxmox host
# - Installs necessary drivers inside the container
# - Manages required system and container restarts
# Configures and installs Coral TPU passthrough (USB and
# M.2 / PCIe) in a Proxmox LXC container. Writes the needed
# dev / cgroup / mount entries into the LXC config, then
# boots the container and installs the Edge TPU runtime
# inside it so apps like Frigate can actually use the TPU.
# iGPU (DRI) device nodes are added alongside when present,
# which is the typical Frigate + Quick Sync combo.
#
# Supports Coral USB and Coral M.2 (PCIe) devices.
# Includes USB passthrough enhancement using persistent udev alias (/dev/coral).
#
# Changelog v1.3:
# - Fixed Coral USB passthrough: mount /dev/bus/usb instead of /dev/coral symlink
# The udev symlink /dev/coral is not passthrough-safe in LXC; mounting the full
# USB bus tree ensures the real device node is accessible inside the container
# regardless of which port the Coral USB is connected to.
#
# Changelog v1.2:
# - Fixed symlink detection for /dev/coral (create=dir for symlinks)
# - Fixed /dev/apex_0 not being mounted in PVE 9 (device existence not required)
# - Fixed grep patterns to avoid matching commented lines
# - Improved device type inference for non-existent devices
# - Added duplicate entry cleanup
# - Better error handling and logging
# Features:
# - Supports Coral USB Accelerator and Coral M.2 / PCIe
# - Auto-detects M.2 via lspci (Global Unichip), USB via
# a persistent udev rule that creates /dev/coral
# - USB passthrough mounts /dev/bus/usb (not /dev/coral)
# so the container sees the real node even if the user
# replugs the device to a different port
# - PCIe/M.2 uses the PVE dev API (dev<N>: ... ,gid=apex)
# which handles cgroup2 permissions automatically
# in both privileged and unprivileged containers
# - Fallback cgroup2 + mount if /dev/apex_0 not yet present
# (module not loaded on host — reboot still pending)
# - Inside container: adds Google Coral APT repo and
# installs libedgetpu1-std (default) or -max (optional)
# - Also installs iGPU user-space drivers when DRI nodes
# are passed, so Quick Sync works out of the box
# - Idempotent: duplicate entries in the LXC config are
# cleaned up on every run
# ==========================================================
LOCAL_SCRIPTS="/usr/local/share/proxmenux/scripts"
@@ -99,10 +101,16 @@ SUBSYSTEM=="usb", ATTRS{idVendor}=="18d1", ATTRS{idProduct}=="9302", MODE="0666"
# Coral Dev Board / Mini PCIe
SUBSYSTEM=="usb", ATTRS{idVendor}=="1a6e", ATTRS{idProduct}=="089a", MODE="0666", TAG+="uaccess", SYMLINK+="coral"'
if [[ ! -f "$RULE_FILE" ]] || ! grep -q "18d1.*9302\|1a6e.*089a" "$RULE_FILE"; then
if [[ ! -f "$RULE_FILE" ]]; then
echo "$RULE_CONTENT" > "$RULE_FILE"
udevadm control --reload-rules && udevadm trigger
msg_ok "$(translate 'Udev rules for Coral USB devices added and rules reloaded.')"
elif ! grep -q "18d1.*9302\|1a6e.*089a" "$RULE_FILE"; then
# Append (>>) instead of overwriting (>) so any user-authored
# rules in this file survive. Audit Tier 7 — udev rule sobreescribe.
printf '\n%s\n' "$RULE_CONTENT" >> "$RULE_FILE"
udevadm control --reload-rules && udevadm trigger
msg_ok "$(translate 'Udev rules for Coral USB devices appended and rules reloaded.')"
else
msg_ok "$(translate 'Udev rules for Coral USB devices already exist.')"
fi
@@ -276,6 +284,15 @@ configure_lxc_hardware() {
if lspci | grep -iq "Global Unichip"; then
msg_info "$(translate 'Coral M.2 Apex detected, configuring...')"
# Pre-flight: warn if the host driver isn't loaded. Without `apex`
# the container will see the device file but the TPU won't actually
# be usable, and Frigate / coral-libs error out at runtime — much
# later than expected. Audit Tier 6 — `install_coral_lxc.sh` no
# verifica apex driver cargado.
if ! lsmod 2>/dev/null | grep -q '^apex'; then
msg_warn "$(translate 'apex kernel module not loaded on host. Run "Install Coral on Host" first or the container will not see /dev/apex_0.')"
fi
local APEX_GID apex_dev_idx
APEX_GID=$(getent group apex 2>/dev/null | cut -d: -f3 || echo "0")
apex_dev_idx=$(get_next_dev_index "$CONFIG_FILE")
@@ -293,9 +310,18 @@ configure_lxc_hardware() {
# dynamically from /proc/devices to avoid hardcoding it.
local APEX_MAJOR
APEX_MAJOR=$(awk '/\bapex\b/{print $1}' /proc/devices 2>/dev/null | head -1)
[[ -z "$APEX_MAJOR" ]] && APEX_MAJOR="245"
if ! grep -q "lxc.cgroup2.devices.allow: c ${APEX_MAJOR}:0 rwm" "$CONFIG_FILE"; then
echo "lxc.cgroup2.devices.allow: c ${APEX_MAJOR}:0 rwm # Coral M2 Apex" >> "$CONFIG_FILE"
if [[ -z "$APEX_MAJOR" ]]; then
# Hardcoded `245` was wrong on kernels that load drivers in
# different order — dynamic majors vary. Surface the failure
# so the user knows the cgroup rule won't match and they need
# to load the apex module first. Audit Tier 6.
msg_warn "$(translate 'Could not detect apex major number from /proc/devices. Load the apex module first: modprobe apex')"
APEX_MAJOR=""
fi
if [[ -n "$APEX_MAJOR" ]]; then
if ! grep -q "lxc.cgroup2.devices.allow: c ${APEX_MAJOR}:0 rwm" "$CONFIG_FILE"; then
echo "lxc.cgroup2.devices.allow: c ${APEX_MAJOR}:0 rwm # Coral M2 Apex" >> "$CONFIG_FILE"
fi
fi
add_mount_if_needed "/dev/apex_0" "dev/apex_0" "$CONFIG_FILE"
msg_ok "$(translate 'Coral M.2 Apex configuration added - device will be available after reboot')"
@@ -332,6 +358,15 @@ install_coral_in_container() {
stop_spinner
# Pre-flight: refuse to run on non-Debian-family containers. The
# apt-get block below would crash with cryptic errors and leave the
# container half-configured. Audit Tier 6 — `install_coral_lxc.sh`
# asume Debian/Ubuntu sin distro detection.
if ! pct exec "$CONTAINER_ID" -- bash -c 'command -v apt-get' &>/dev/null; then
msg_error "$(translate 'Container does not have apt-get available. Coral driver installation only supports Debian/Ubuntu containers.')"
return 1
fi
# Determine driver package for Coral M.2
CORAL_M2=$(lspci | grep -i "Global Unichip")
if [[ -n "$CORAL_M2" ]]; then
+1 -1
View File
@@ -2,7 +2,7 @@
# ProxMenux - Intel GPU Tools Installer
# ============================================
# Author : MacRimi
# License : MIT
# License : GPL-3.0
# Version : 1.0
# Last Updated: 29/01/2026
# ============================================
+276 -54
View File
@@ -1,12 +1,29 @@
#!/bin/bash
# ProxMenux - NVIDIA Driver Installer (PVE 9.x)
# ============================================
# ==========================================================
# ProxMenux - NVIDIA GPU Driver Installer
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : (GPL-3.0) (https://github.com/MacRimi/ProxMenux/blob/main/LICENSE)
# Version : 1.2 (PVE9, fixed download issues)
# License : GPL-3.0
# Version : 1.2
# Last Updated: 26/03/2026
# ============================================
# ==========================================================
# Description:
# Installs and manages the NVIDIA proprietary driver on a
# Proxmox VE host. Detects hardware, picks a kernel-compatible
# driver version and handles the full lifecycle
# (install / update / remove).
#
# Features:
# - GPU detection + VFIO passthrough safety check
# - Kernel-aware driver version filter (5.15 → 6.17+)
# - Nouveau blacklist + module unload
# - DKMS-backed install (survives kernel upgrades)
# - udev rules + nvidia-persistenced service
# - Optional keylase/nvidia-patch (NVENC session limit)
# - LXC container driver propagation (Alpine/Arch/Debian)
# - Complete uninstall path
# ==========================================================
SCRIPT_TITLE="NVIDIA GPU Driver Installer for Proxmox VE"
@@ -246,13 +263,6 @@ update_lxc_nvidia() {
local install_rc=0
case "$distro" in
alpine)
msg_info2 "$(translate 'Upgrading NVIDIA utils (Alpine)...')"
pct exec "$ctid" -- sh -c \
"apk update && apk add --no-cache --upgrade nvidia-utils" \
2>&1 | tee -a "$LOG_FILE"
install_rc=${PIPESTATUS[0]}
;;
arch|manjaro|endeavouros)
msg_info2 "$(translate 'Upgrading NVIDIA utils (Arch)...')"
pct exec "$ctid" -- bash -c \
@@ -270,7 +280,8 @@ update_lxc_nvidia() {
install_rc=1
else
local free_mb
free_mb=$(pct exec "$ctid" -- df -m / 2>/dev/null | awk 'NR==2{print $4}' || echo 0)
free_mb=$(pct exec "$ctid" -- df -P -m / 2>/dev/null | awk 'END{print $4}')
free_mb=${free_mb:-0}
if [[ "$free_mb" -lt 1500 ]]; then
_restore_container_memory "$ctid"
whiptail --backtitle "ProxMenux" \
@@ -314,21 +325,51 @@ update_lxc_nvidia() {
msg_info2 "$(translate 'Running NVIDIA installer in container. This may take several minutes...')"
echo "" >>"$LOG_FILE"
pct exec "$ctid" -- bash -c "
mkdir -p /tmp/nvidia_lxc_install
tar -xzf /tmp/nvidia_lxc.tar.gz -C /tmp/nvidia_lxc_install 2>&1
/tmp/nvidia_lxc_install/nvidia-installer \
--no-kernel-modules \
--no-questions \
--ui=none \
--no-nouveau-check \
--no-dkms \
--no-install-compat32-libs
EXIT=\$?
rm -rf /tmp/nvidia_lxc_install /tmp/nvidia_lxc.tar.gz
exit \$EXIT
" 2>&1 | tee -a "$LOG_FILE"
install_rc=${PIPESTATUS[0]}
if [[ "$distro" == "alpine" ]]; then
# Alpine uses musl libc and does not ship a glibc dynamic
# loader, so the nvidia-installer binary (glibc) cannot
# execute. We pull `gcompat` to provide the glibc loader
# and a libc shim, then copy the userspace libs and the
# standard NVIDIA binaries by hand. SONAME symlinks are
# built from `readelf` (binutils) instead of trusting a
# hard-coded list — the .run ships ~50 .so files and the
# set varies between branches.
pct exec "$ctid" -- sh -c '
set -e
mkdir -p /tmp/nvidia_lxc_install
tar -xzf /tmp/nvidia_lxc.tar.gz -C /tmp/nvidia_lxc_install
apk add --no-cache gcompat binutils >/dev/null
cd /tmp/nvidia_lxc_install
mkdir -p /usr/lib /usr/bin
cp -P *.so* /usr/lib/ 2>/dev/null || true
for lib in /usr/lib/lib*.so.*; do
[ -f "$lib" ] || continue
soname=$(readelf -d "$lib" 2>/dev/null | grep SONAME | head -n1 | sed -e "s/.*\[//" -e "s/\].*//")
[ -n "$soname" ] && [ "$(basename "$lib")" != "$soname" ] && ln -sf "$(basename "$lib")" "/usr/lib/$soname"
done
for bin in nvidia-smi nvidia-debugdump nvidia-cuda-mps-control nvidia-cuda-mps-server nvidia-persistenced nvidia-modprobe; do
[ -f "$bin" ] && cp -P "$bin" /usr/bin/ && chmod 755 "/usr/bin/$bin"
done
rm -rf /tmp/nvidia_lxc_install /tmp/nvidia_lxc.tar.gz
' 2>&1 | tee -a "$LOG_FILE"
install_rc=${PIPESTATUS[0]}
else
pct exec "$ctid" -- bash -c "
mkdir -p /tmp/nvidia_lxc_install
tar -xzf /tmp/nvidia_lxc.tar.gz -C /tmp/nvidia_lxc_install 2>&1
/tmp/nvidia_lxc_install/nvidia-installer \
--no-kernel-modules \
--no-questions \
--ui=none \
--no-nouveau-check \
--no-dkms \
--no-install-compat32-libs
EXIT=\$?
rm -rf /tmp/nvidia_lxc_install /tmp/nvidia_lxc.tar.gz
exit \$EXIT
" 2>&1 | tee -a "$LOG_FILE"
install_rc=${PIPESTATUS[0]}
fi
rm -rf "$extract_dir"
_restore_container_memory "$ctid"
@@ -596,13 +637,20 @@ get_kernel_compatibility_info() {
KERNEL_MAJOR=$(echo "$kernel_version" | cut -d. -f1)
KERNEL_MINOR=$(echo "$kernel_version" | cut -d. -f2)
# Define minimum compatible versions based on kernel
# Based on https://docs.nvidia.com/datacenter/tesla/drivers/index.html
if [[ "$KERNEL_MAJOR" -ge 6 ]] && [[ "$KERNEL_MINOR" -ge 17 ]]; then
# Kernel 6.17+ (Proxmox 9.x) - Requires 580.82.07 or higher
MIN_DRIVER_VERSION="580.82.07"
# Define minimum compatible versions based on kernel.
# Floor bumped from 580.82.07 → 580.105.08 for kernel 6.17+ after a
# user report (issue tracked as Sprint 11.4) that 580.82-580.95 builds
# fail on kernel 6.17.13 (DKMS module compile errors with the newer
# toolchain shipped with PVE 9.1). 580.105.08 is verified working on
# the test host. Future kernel 7.x falls into the same bucket — the
# `KERNEL_MAJOR -ge 7` branch was previously missing and routed 7.x
# kernels to MIN=535 incorrectly.
if { [[ "$KERNEL_MAJOR" -ge 7 ]]; } || \
{ [[ "$KERNEL_MAJOR" -eq 6 ]] && [[ "$KERNEL_MINOR" -ge 17 ]]; }; then
# Kernel 6.17+ / 7.x (Proxmox 9.x +) - Requires 580.105.08 or higher
MIN_DRIVER_VERSION="580.105.08"
RECOMMENDED_BRANCH="580"
COMPATIBILITY_NOTE="Kernel $kernel_version requires NVIDIA driver 580.82.07 or newer"
COMPATIBILITY_NOTE="Kernel $kernel_version requires NVIDIA driver 580.105.08 or newer (older 580.x builds fail to compile)"
elif [[ "$KERNEL_MAJOR" -ge 6 ]] && [[ "$KERNEL_MINOR" -ge 8 ]]; then
# Kernel 6.8-6.16 (Proxmox 8.2+) - Works with 550.x or higher
MIN_DRIVER_VERSION="550"
@@ -635,31 +683,131 @@ is_version_compatible() {
ver_minor=$(echo "$version" | cut -d. -f2)
ver_patch=$(echo "$version" | cut -d. -f3)
if [[ "$MIN_DRIVER_VERSION" == "580.82.07" ]]; then
# Compare full version: must be >= 580.82.07
if [[ ${ver_major} -gt 580 ]]; then
return 0
elif [[ ${ver_major} -eq 580 ]]; then
if [[ $((10#${ver_minor})) -gt 82 ]]; then
# Full-version comparison when MIN is dotted (e.g. "580.105.08").
# Strips the dotted threshold from MIN_DRIVER_VERSION and reuses the
# existing `version_le` helper. The previous code had a hardcoded
# branch only for "580.82.07" — bumping the floor required editing two
# places. Sprint 11.4.
case "$MIN_DRIVER_VERSION" in
*.*.*)
# Dotted threshold: compare full triple.
local _min_major _min_minor _min_patch
IFS='.' read -r _min_major _min_minor _min_patch <<<"$MIN_DRIVER_VERSION"
_min_major=${_min_major:-0}
_min_minor=${_min_minor:-0}
_min_patch=${_min_patch:-0}
ver_minor=${ver_minor:-0}
ver_patch=${ver_patch:-0}
if (( 10#$ver_major > 10#$_min_major )); then
return 0
elif [[ $((10#${ver_minor})) -eq 82 ]]; then
if [[ $((10#${ver_patch:-0})) -ge 7 ]]; then
elif (( 10#$ver_major == 10#$_min_major )); then
if (( 10#$ver_minor > 10#$_min_minor )); then
return 0
elif (( 10#$ver_minor == 10#$_min_minor )); then
if (( 10#${ver_patch:-0} >= 10#$_min_patch )); then
return 0
fi
fi
fi
fi
return 1
fi
if [[ ${ver_major} -ge ${MIN_DRIVER_VERSION} ]]; then
return 0
else
return 1
fi
return 1
;;
*)
# Single-major threshold (e.g. "550", "535"): compare major only.
if [[ ${ver_major} -ge ${MIN_DRIVER_VERSION} ]]; then
return 0
else
return 1
fi
;;
esac
}
is_current_nvidia_patched() {
local status_file="/usr/local/share/proxmenux/components_status.json"
[[ -f "$status_file" ]] || return 1
command -v jq >/dev/null 2>&1 || return 1
local patched
patched=$(jq -r '.nvidia_driver.patched // false' "$status_file" 2>/dev/null)
[[ "$patched" == "true" ]]
}
KEYLASE_PATCH_CACHE="/var/cache/proxmenux/keylase_patch_versions.txt"
KEYLASE_PATCH_TTL_SECONDS=$((7 * 86400))
KEYLASE_PATCH_URL="https://raw.githubusercontent.com/keylase/nvidia-patch/master/patch.sh"
refresh_keylase_patch_cache() {
local now ts age
now=$(date +%s)
if [[ -f "$KEYLASE_PATCH_CACHE" ]]; then
ts=$(stat -c '%Y' "$KEYLASE_PATCH_CACHE" 2>/dev/null || echo 0)
age=$(( now - ts ))
if (( age < KEYLASE_PATCH_TTL_SECONDS )) && [[ -s "$KEYLASE_PATCH_CACHE" ]]; then
return 0
fi
fi
mkdir -p "$(dirname "$KEYLASE_PATCH_CACHE")" 2>/dev/null || return 1
local tmp
tmp=$(mktemp)
if curl -fsSL --max-time 15 "$KEYLASE_PATCH_URL" 2>/dev/null \
| grep -oE '\["[0-9]+\.[0-9]+(\.[0-9]+)?"\]' \
| sed -E 's/\["([0-9.]+)"\]/\1/' \
| sort -u > "$tmp" && [[ -s "$tmp" ]]; then
mv "$tmp" "$KEYLASE_PATCH_CACHE"
return 0
fi
rm -f "$tmp"
return 1
}
is_keylase_patch_supported() {
local ver="$1"
[[ -z "$ver" ]] && return 1
[[ -f "$KEYLASE_PATCH_CACHE" && -s "$KEYLASE_PATCH_CACHE" ]] || return 1
grep -qFx "$ver" "$KEYLASE_PATCH_CACHE"
}
filter_keylase_supported() {
local versions_in="$1"
while IFS= read -r ver; do
[[ -z "$ver" ]] && continue
if is_keylase_patch_supported "$ver"; then
printf '%s\n' "$ver"
fi
done <<< "$versions_in"
}
filter_option_c_branch() {
local versions_in="$1"
local current="$2"
local recommended_branch="$3"
local target_branch=""
if [[ -n "$current" && "$current" =~ ^([0-9]+)\. ]]; then
local current_branch="${BASH_REMATCH[1]}"
if is_version_compatible "$current"; then
target_branch="$current_branch"
fi
fi
if [[ -z "$target_branch" ]]; then
target_branch="$recommended_branch"
fi
if [[ -z "$target_branch" ]]; then
printf '%s\n' "$versions_in"
return 0
fi
while IFS= read -r ver; do
[[ -z "$ver" ]] && continue
local ver_major="${ver%%.*}"
if [[ "$ver_major" == "$target_branch" ]]; then
printf '%s\n' "$ver"
fi
done <<< "$versions_in"
}
version_le() {
local v1="$1"
local v2="$2"
@@ -981,8 +1129,16 @@ EOF
ensure_workdir
cd "$NVIDIA_WORKDIR" || return 1
# Pin to the last release tag so a hostile push to upstream `master`
# can't slip arbitrary code into the install. Bump as needed; the
# `--depth 1` keeps the clone fast. Audit Tier 6 — `nvidia-persistenced`
# git clone sin pinning de versión.
local NVIDIA_PERSISTENCED_TAG="${NVIDIA_PERSISTENCED_TAG:-575.64.05}"
if [[ ! -d nvidia-persistenced ]]; then
git clone https://github.com/NVIDIA/nvidia-persistenced.git >>"$LOG_FILE" 2>&1 || true
git clone --depth 1 --branch "$NVIDIA_PERSISTENCED_TAG" \
https://github.com/NVIDIA/nvidia-persistenced.git >>"$LOG_FILE" 2>&1 \
|| git clone --depth 1 https://github.com/NVIDIA/nvidia-persistenced.git >>"$LOG_FILE" 2>&1 \
|| true
fi
if [[ -d nvidia-persistenced/init ]]; then
@@ -1004,8 +1160,25 @@ apply_nvidia_patch_if_needed() {
msg_info "$(translate 'Cloning and applying NVIDIA patch (keylase/nvidia-patch)...')"
ensure_workdir
cd "$NVIDIA_WORKDIR" || return 1
# Pin keylase/nvidia-patch to a known-good commit. Override via env var
# for forward-compat as new driver versions land. patch.sh ships a list
# of supported drivers in the repo; if our running driver isn't covered
# the patch silently no-ops, so we surface a warning before running.
# Audit Tier 6 — `keylase/nvidia-patch` sin pinning + sin compat check.
local NVIDIA_PATCH_REF="${NVIDIA_PATCH_REF:-master}"
if [[ ! -d nvidia-patch ]]; then
git clone https://github.com/keylase/nvidia-patch.git >>"$LOG_FILE" 2>&1 || true
git clone --depth 1 --branch "$NVIDIA_PATCH_REF" \
https://github.com/keylase/nvidia-patch.git >>"$LOG_FILE" 2>&1 \
|| git clone --depth 1 https://github.com/keylase/nvidia-patch.git >>"$LOG_FILE" 2>&1 \
|| true
fi
# Best-effort compatibility check: peek the supported-driver list in
# patch.sh and warn if our driver isn't on it.
if [[ -n "$CURRENT_DRIVER_VERSION" && -f nvidia-patch/patch.sh ]]; then
if ! grep -qF "$CURRENT_DRIVER_VERSION" nvidia-patch/patch.sh 2>/dev/null; then
msg_warn "$(translate 'NVIDIA driver') $CURRENT_DRIVER_VERSION $(translate 'is not in the patch.sh supported list. The patch may no-op or fail; review keylase/nvidia-patch README before continuing.')"
fi
fi
if [[ -x nvidia-patch/patch.sh ]]; then
@@ -1132,6 +1305,15 @@ show_version_menu() {
current_list="$filtered_list"
fi
# Option C: kernel-compat alone is too permissive (e.g. kernel 6.14
# accepts ≥ 550 so 595.x shows up — but 595.x has historically broken
# builds on this kernel). Restrict the offered list to the user's
# current branch when their installed driver still works, otherwise
# fall back to the recommended branch for the kernel.
if [[ -n "$current_list" ]]; then
current_list=$(filter_option_c_branch "$current_list" "$CURRENT_DRIVER_VERSION" "$RECOMMENDED_BRANCH")
fi
if [[ -n "$latest" ]]; then
local filtered_max_list=""
while IFS= read -r ver; do
@@ -1143,8 +1325,42 @@ show_version_menu() {
current_list="$filtered_max_list"
fi
# If the user has the keylase NVENC patch applied, only offer versions
# that the patch supports — picking an unsupported version reinstalls
# the driver fine but the patch silently no-ops afterwards, so the
# user loses NVENC limit removal without warning.
local patch_filtered=false
local patch_filter_note=""
if is_current_nvidia_patched && [[ -n "$current_list" ]]; then
if refresh_keylase_patch_cache; then
local trimmed
trimmed=$(filter_keylase_supported "$current_list")
if [[ -n "$trimmed" ]]; then
current_list="$trimmed"
patch_filtered=true
else
patch_filter_note="$(translate 'No version in this branch is currently supported by keylase/nvidia-patch — the NVENC patch will not reapply after reinstall.')"
fi
else
patch_filter_note="$(translate 'Could not fetch keylase/nvidia-patch supported list — patch reapply compatibility is not verified.')"
fi
fi
# Recompute "latest" as the highest version still in the filtered list
# so the menu's "Latest available" label matches what we actually offer
# rather than the global upstream latest (which may have been filtered
# out by Option C / kernel-compat / patch awareness).
if [[ -n "$current_list" ]]; then
latest=$(printf '%s\n' "$current_list" | head -n1 | tr -d '[:space:]')
fi
local menu_text="$(translate 'Select the NVIDIA driver version to install:')\n\n"
menu_text+="$(translate 'Versions shown are compatible with your kernel. Latest available is recommended in most cases.')"
if $patch_filtered; then
menu_text+="\n\n$(translate 'NVENC patch detected — list narrowed to versions supported by keylase/nvidia-patch.')"
elif [[ -n "$patch_filter_note" ]]; then
menu_text+="\n\n${patch_filter_note}"
fi
local choices=()
choices+=("latest" "$(translate 'Latest available') (${latest:-unknown})")
@@ -1186,6 +1402,12 @@ show_version_menu() {
# Main flow
# ==========================================================
main() {
# Rotate the previous run's log instead of truncating — when the
# current install fails, the user can compare against the previous
# attempt to see what changed. Audit Tier 7 — log truncation.
if [[ -f "$LOG_FILE" && -s "$LOG_FILE" ]]; then
cp -p "$LOG_FILE" "${LOG_FILE}.prev" 2>/dev/null || true
fi
: >"$LOG_FILE"
: >"$screen_capture"
+63 -3
View File
@@ -8,6 +8,35 @@
# Version : 1.0
# Last Updated: 05/04/2026
# ==========================================================
# Description:
# Moves an already-assigned GPU between the two modes it can
# live in on a Proxmox host:
# - VM mode (bound to vfio-pci, exclusive to one VM)
# - LXC mode (bound to the native driver, shared with CTs)
#
# Detects the current mode of each selected GPU and applies
# the host-side changes needed to switch (vfio.conf,
# blacklist.conf, /etc/modules, initramfs). Also handles the
# VM/LXC side so the switch doesn't leave dangling config
# pointing at a GPU the workload can no longer access.
#
# Features:
# - Multi-GPU selection (uniform current mode enforced)
# - SR-IOV guard (blocks VF / active-PF passthrough)
# - Blocked-ID policy list (e.g. Intel Arc A770)
# - IOMMU-group aware ID collection (sweeps siblings)
# - Conflict policy per affected VM/LXC
# (keep + disable onboot OR remove from config)
# - Orphan audio cascade: when a GPU leaves a VM, offer
# to remove companion audio hostpci entries and clean
# vfio.conf if no other VM still uses those IDs
# - Precise BDF regex for hostpci removal
# (no substring collision between unrelated GPUs)
# - NVIDIA stack sanitize/restore (udev, module-load,
# hard-blacklist) depending on target mode
# - Rebuilds initramfs only if host config actually changed
# - Reboot prompt at the end
# ==========================================================
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LOCAL_SCRIPTS_LOCAL="$(cd "$SCRIPT_DIR/.." && pwd)"
@@ -28,15 +57,24 @@ screen_capture="/tmp/proxmenux_gpu_switch_mode_screen_$$.txt"
if [[ -f "$UTILS_FILE" ]]; then
source "$UTILS_FILE"
fi
# Both helper libraries are required for the SR-IOV guard and the audio
# orphan cascade to work. Surface a loud warning if neither path resolves
# — the previous behaviour evaluated `declare -F` later and silently
# disabled the validations, leaving the user thinking they were
# protected. Audit Tier 6 — `switch_gpu_mode.sh` silent helper loss.
if [[ -f "$LOCAL_SCRIPTS_LOCAL/global/pci_passthrough_helpers.sh" ]]; then
source "$LOCAL_SCRIPTS_LOCAL/global/pci_passthrough_helpers.sh"
elif [[ -f "$LOCAL_SCRIPTS_DEFAULT/global/pci_passthrough_helpers.sh" ]]; then
source "$LOCAL_SCRIPTS_DEFAULT/global/pci_passthrough_helpers.sh"
else
msg_warn "$(translate 'pci_passthrough_helpers.sh missing — SR-IOV / orphan-audio guards will be skipped')"
fi
if [[ -f "$LOCAL_SCRIPTS_LOCAL/global/gpu_hook_guard_helpers.sh" ]]; then
source "$LOCAL_SCRIPTS_LOCAL/global/gpu_hook_guard_helpers.sh"
elif [[ -f "$LOCAL_SCRIPTS_DEFAULT/global/gpu_hook_guard_helpers.sh" ]]; then
source "$LOCAL_SCRIPTS_DEFAULT/global/gpu_hook_guard_helpers.sh"
else
msg_warn "$(translate 'gpu_hook_guard_helpers.sh missing — VM hookscript guard will be skipped')"
fi
load_language
@@ -130,7 +168,7 @@ _get_iommu_group_ids() {
local dev dev_class vid did
dev=$(basename "$dev_path")
dev_class=$(cat "/sys/bus/pci/devices/${dev}/class" 2>/dev/null)
[[ "$dev_class" == "0x0604" || "$dev_class" == "0x0600" ]] && continue
[[ "$dev_class" == 0x0604* || "$dev_class" == 0x0600* ]] && continue
vid=$(cat "/sys/bus/pci/devices/${dev}/vendor" 2>/dev/null | sed 's/0x//')
did=$(cat "/sys/bus/pci/devices/${dev}/device" 2>/dev/null | sed 's/0x//')
[[ -n "$vid" && -n "$did" ]] && echo "${vid}:${did}"
@@ -978,8 +1016,21 @@ apply_vm_action_for_lxc_mode() {
# switch-back) or it steals host audio unnecessarily. Enumerate
# orphan audio hostpci entries and ask the user what to do.
if declare -F _vm_list_orphan_audio_hostpci >/dev/null 2>&1; then
local _orphan_audio
_orphan_audio=$(_vm_list_orphan_audio_hostpci "$vmid" "${SELECTED_PCI_SLOTS[0]}")
# Concatenate orphan-audio entries across ALL selected GPUs.
# The previous code only checked `SELECTED_PCI_SLOTS[0]`, so when
# the user switched 2 dGPUs at once and each had its own audio
# companion, the second GPU's audio was left dangling in the VM
# config. Audit Tier 6 — orphan audio solo del primer slot.
local _orphan_audio=""
local _slot
for _slot in "${SELECTED_PCI_SLOTS[@]}"; do
local _piece
_piece=$(_vm_list_orphan_audio_hostpci "$vmid" "$_slot")
if [[ -n "$_piece" ]]; then
[[ -n "$_orphan_audio" ]] && _orphan_audio+=$'\n'
_orphan_audio+="$_piece"
fi
done
if [[ -n "$_orphan_audio" ]]; then
local -a _orph_items=()
local _line _o_idx _o_bdf _o_name
@@ -1111,6 +1162,15 @@ switch_to_vm_mode() {
msg_ok "$(translate 'IOMMU is already active on this system')" | tee -a "$screen_capture"
elif grep -qE 'intel_iommu=on|amd_iommu=on' /etc/kernel/cmdline 2>/dev/null || \
grep -qE 'intel_iommu=on|amd_iommu=on' /etc/default/grub 2>/dev/null; then
# Cross-check that IOMMU is *actually* active in the running kernel.
# The kernel parameter alone doesn't guarantee functional IOMMU —
# if the BIOS toggle is off, /sys/kernel/iommu_groups/ is empty even
# though intel_iommu=on is in cmdline. Without this gate we'd write
# vfio.conf and after reboot the GPU never gets claimed by VFIO.
# Audit Tier 6 — IOMMU check optimista.
if ! find /sys/kernel/iommu_groups -mindepth 1 -maxdepth 1 -name '[0-9]*' 2>/dev/null | grep -q .; then
msg_warn "$(translate 'intel_iommu/amd_iommu is set in cmdline but no IOMMU groups exist — IOMMU appears disabled in BIOS. Enable VT-d / AMD-Vi in firmware before continuing.')"
fi
_register_iommu_tool
HOST_CONFIG_CHANGED=true
msg_ok "$(translate 'IOMMU already configured in kernel parameters')" | tee -a "$screen_capture"
+1 -1
View File
@@ -144,7 +144,7 @@ _get_iommu_group_ids() {
local dev dev_class vid did
dev=$(basename "$dev_path")
dev_class=$(cat "/sys/bus/pci/devices/${dev}/class" 2>/dev/null)
[[ "$dev_class" == "0x0604" || "$dev_class" == "0x0600" ]] && continue
[[ "$dev_class" == 0x0604* || "$dev_class" == 0x0600* ]] && continue
vid=$(cat "/sys/bus/pci/devices/${dev}/vendor" 2>/dev/null | sed 's/0x//')
did=$(cat "/sys/bus/pci/devices/${dev}/device" 2>/dev/null | sed 's/0x//')
[[ -n "$vid" && -n "$did" ]] && echo "${vid}:${did}"
+106 -12
View File
@@ -1,21 +1,31 @@
#!/bin/bash
# ==========================================================
# ProxMenux - A menu-driven script for Proxmox VE management
# ProxMenux - Help and Info (Command Reference)
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : (GPL-3.0) (https://github.com/MacRimi/ProxMenux/blob/main/LICENSE)
# License : GPL-3.0
# https://github.com/MacRimi/ProxMenux/blob/main/LICENSE
# Version : 1.0
# Last Updated: 28/01/2025
# ==========================================================
# Description:
# This script provides an interactive command reference menu
# for Proxmox VE via dialog-based UI.
# - Categorized and translated lists of common and advanced commands.
# - Covers system, network, storage, VM/CT, updates, GPU passthrough,
# ZFS, backup/restore, and essential CLI tools.
# - Allows users to view or execute commands directly from the menu.
# Interactive command-reference menu for Proxmox VE. Each
# section lists numbered commands with translated descriptions;
# the user can pick a number to execute the command directly,
# paste a custom command, or press 0 / Esc to go back.
#
# Sections (9):
# 1. Useful System Commands
# 2. VM and CT Management
# 3. Storage and Disks
# 4. Network Commands
# 5. Updates and Packages
# 6. GPU / TPU Passthrough
# 7. ZFS Management
# 8. Backup and Restore
# 9. System CLI Tools
#
# The menu also auto-installs 'dialog' if missing.
# ==========================================================
# Configuration ============================================
@@ -38,8 +48,16 @@ GREEN="\033[0;32m"
NC="\033[0m"
if ! command -v dialog &>/dev/null; then
# Surface apt failures so the user knows why the menu won't render.
# The previous silent install made the next dialog call error with
# "command not found" with no context. Audit Tier 6 — `help_info_menu.sh`
# apt silent.
apt update -qq >/dev/null 2>&1
apt install -y dialog >/dev/null 2>&1
if ! apt install -y dialog >/dev/null 2>&1; then
echo "ERROR: failed to install 'dialog' (required for the help menu)." >&2
echo "Run 'apt install dialog' manually and try again." >&2
exit 1
fi
fi
@@ -170,6 +188,10 @@ show_vm_ct_commands() {
echo -e "11) ${GN}[Only with menu] Show CT users for permission mapping${NC} - $(translate 'root and real users only')"
echo -e "12) ${GREEN}pct exec <ctid> -- getent passwd | column -t -s :${NC} - $(translate 'Show CT users in table format')"
echo -e "13) ${GREEN}pct exec <ctid> -- ps aux --sort=-%mem | head${NC} - $(translate 'Top memory processes in CT')"
echo -e "14) ${GREEN}cat /etc/pve/qemu-server/<vmid>.conf${NC} - $(translate 'View raw VM configuration file')"
echo -e "15) ${GREEN}cat /etc/pve/lxc/<ctid>.conf${NC} - $(translate 'View raw CT configuration file')"
echo -e "16) ${GREEN}nano /etc/pve/qemu-server/<vmid>.conf${NC} - $(translate 'Edit raw VM configuration file')"
echo -e "17) ${GREEN}nano /etc/pve/lxc/<ctid>.conf${NC} - $(translate 'Edit raw CT configuration file')"
echo -e " ${DEF}0) $(translate ' Back to previous menu or Esc + Enter')"
echo
echo -en "${TAB}${BOLD}${YW}${HOLD}$(translate 'Enter a number, or write or paste a command: ') ${CL}"
@@ -222,11 +244,31 @@ show_vm_ct_commands() {
;;
13)
echo -en "${TAB}${BOLD}${YW}${HOLD}$(translate 'Enter CT ID: ')${CL}"
read -r id
cmd="pct exec $id -- ps aux --sort=-%mem | head"
;;
14)
echo -en "${TAB}${BOLD}${YW}${HOLD}$(translate 'Enter VM ID: ')${CL}"
read -r id
cmd="cat /etc/pve/qemu-server/$id.conf"
;;
15)
echo -en "${TAB}${BOLD}${YW}${HOLD}$(translate 'Enter CT ID: ')${CL}"
read -r id
cmd="cat /etc/pve/lxc/$id.conf"
;;
16)
echo -en "${TAB}${BOLD}${YW}${HOLD}$(translate 'Enter VM ID: ')${CL}"
read -r id
cmd="nano /etc/pve/qemu-server/$id.conf"
;;
17)
echo -en "${TAB}${BOLD}${YW}${HOLD}$(translate 'Enter CT ID: ')${CL}"
read -r id
cmd="nano /etc/pve/lxc/$id.conf"
;;
0) break ;;
*) cmd="$user_input" ;;
esac
@@ -271,6 +313,14 @@ show_storage_commands() {
echo -e "20) ${GREEN}qm importdisk <vmid> <img> <storage>${NC} - $(translate 'Import disk image to VM')"
echo -e "21) ${GREEN}qm set <vmid> -<bus><index> <disk>${NC} - $(translate 'Add physical disk to VM via') passthrough"
echo -e "22) ${GREEN}qemu-img convert -O <format> <input> <output>${NC} - $(translate 'Convert disk image format')"
echo -e "23) ${GREEN}smartctl --scan${NC} - $(translate 'List SMART-capable devices')"
echo -e "24) ${GREEN}smartctl -H /dev/<disk>${NC} - $(translate 'Quick health check (PASSED / FAILED)')"
echo -e "25) ${GREEN}smartctl -a /dev/<disk>${NC} - $(translate 'Full SMART info and attributes')"
echo -e "26) ${GREEN}smartctl -t short /dev/<disk>${NC} - $(translate 'Start short self-test (~2 min)')"
echo -e "27) ${GREEN}smartctl -t long /dev/<disk>${NC} - $(translate 'Start long self-test (hours)')"
echo -e "28) ${GREEN}smartctl -l selftest /dev/<disk>${NC} - $(translate 'View self-test log')"
echo -e "29) ${GREEN}nvme list${NC} - $(translate 'List NVMe devices')"
echo -e "30) ${GREEN}nvme smart-log /dev/<nvme>${NC} - $(translate 'NVMe-specific SMART log')"
echo -e " ${DEF}0) $(translate ' Back to previous menu or Esc + Enter')"
echo
echo -en "${TAB}${BOLD}${YW}${HOLD}$(translate 'Enter a number, or write or paste a command: ') ${CL}"
@@ -453,6 +503,50 @@ show_storage_commands() {
echo -e "\n${YELLOW}$(translate 'Converting image using command:')${NC}"
cmd="qemu-img convert -O $output_format $input_image $output_image"
;;
23) cmd="smartctl --scan" ;;
24)
lsblk -dno NAME,SIZE,MODEL | grep -vE 'loop|dm-|zd' | sed 's/^/ /'
echo
echo -en "${TAB}${BOLD}${YW}${HOLD}$(translate 'Enter device (e.g., sda or nvme0): ')${CL}"
read -r dev
cmd="smartctl -H /dev/$dev"
;;
25)
lsblk -dno NAME,SIZE,MODEL | grep -vE 'loop|dm-|zd' | sed 's/^/ /'
echo
echo -en "${TAB}${BOLD}${YW}${HOLD}$(translate 'Enter device (e.g., sda or nvme0): ')${CL}"
read -r dev
cmd="smartctl -a /dev/$dev"
;;
26)
lsblk -dno NAME,SIZE,MODEL | grep -vE 'loop|dm-|zd' | sed 's/^/ /'
echo
echo -en "${TAB}${BOLD}${YW}${HOLD}$(translate 'Enter device (e.g., sda or nvme0): ')${CL}"
read -r dev
cmd="smartctl -t short /dev/$dev"
;;
27)
lsblk -dno NAME,SIZE,MODEL | grep -vE 'loop|dm-|zd' | sed 's/^/ /'
echo
echo -en "${TAB}${BOLD}${YW}${HOLD}$(translate 'Enter device (e.g., sda or nvme0): ')${CL}"
read -r dev
cmd="smartctl -t long /dev/$dev"
;;
28)
lsblk -dno NAME,SIZE,MODEL | grep -vE 'loop|dm-|zd' | sed 's/^/ /'
echo
echo -en "${TAB}${BOLD}${YW}${HOLD}$(translate 'Enter device (e.g., sda or nvme0): ')${CL}"
read -r dev
cmd="smartctl -l selftest /dev/$dev"
;;
29) cmd="nvme list" ;;
30)
ls /dev/nvme* 2>/dev/null | sed 's/^/ /'
echo
echo -en "${TAB}${BOLD}${YW}${HOLD}$(translate 'Enter NVMe device (e.g., nvme0): ')${CL}"
read -r dev
cmd="nvme smart-log /dev/$dev"
;;
0) break ;;
*) cmd="$user_input" ;;
esac
+32 -6
View File
@@ -1,13 +1,39 @@
#!/bin/bash
# ==========================================================
# ProxMenux - A menu-driven script for Proxmox VE management
# ProxMenux - Settings (Configuration Menu)
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# Author : MacRimi
# Contributors : cod378
# License : (GPL-3.0) (https://github.com/MacRimi/ProxMenux/blob/main/LICENSE)
# Version : 1.1
# Last Updated: 04/07/2025
# Copyright : (c) 2024 MacRimi
# License : GPL-3.0
# https://github.com/MacRimi/ProxMenux/blob/main/LICENSE
# Version : 1.1
# ==========================================================
# Description:
# ProxMenux configuration / settings menu. Options are shown
# conditionally based on the install type and current state:
#
# - ProxMenux Monitor (Activate / Deactivate + Show Status)
# Only if proxmenux-monitor.service is registered with
# systemd. Toggles between active / inactive states.
#
# - Deactivate Beta Program
# Only if config.json has beta_program.status = "active".
# Stops beta update prompts; stable updates continue.
#
# - Change Language
# Only on the Translation install type (venv +
# config.json.language present). Languages: en / es / fr /
# de / it / pt.
#
# - Show Version Information
# Always shown. Reports installed components, files,
# virtual environment state and current language.
#
# - Uninstall ProxMenux
# Always shown. Interactive uninstall with optional
# dependency removal (jq, dialog, python3-*, ...) and
# restoration of /root/.bashrc + /etc/motd backups.
# ==========================================================
# Configuration ============================================
+14 -16
View File
@@ -1,27 +1,26 @@
#!/usr/bin/env bash
# ==========================================================
# ProxMenuX - Virtual Machine Creator Script
# ProxMenux - Virtual Machine Creator Menu
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : (GPL-3.0) (https://github.com/MacRimi/ProxMenux/blob/main/LICENSE)
# License : GPL-3.0
# https://github.com/MacRimi/ProxMenux/blob/main/LICENSE
# Version : 1.0
# Last Updated: 07/05/2025
# ==========================================================
# Description:
# This script is part of the central ProxMenux VM creation module. It allows users
# to create virtual machines (VMs) in Proxmox VE using either default or advanced
# configurations, streamlining the deployment of Linux, Windows, and other systems.
# Central VM creation dispatcher for ProxMenux. Presents the user
# with OS-family options (NAS, Windows, Linux, macOS, Others) and
# routes to the matching ISO selector and configuration wizard.
#
# Key features:
# - Supports virtual disks, import disks, and Controller + NVMe passthrough.
# - Automates CPU, RAM, BIOS, network and storage configuration.
# - Provides a user-friendly menu to select OS type, ISO image and disk interface.
# - Automatically generates a detailed and styled HTML description for each VM.
#
# All operations are designed to simplify and accelerate VM creation in a
# consistent and maintainable way, using ProxMenux standards.
# Features:
# - Dispatches to ISO selectors: NAS / Windows / Linux / Others.
# - Default vs Advanced flows: CPU, RAM, BIOS, network, storage.
# - Virtual disks, disk import, and Controller+NVMe passthrough.
# - Optional GPU passthrough wizard post-creation.
# - Auto-generates a styled HTML description for each VM.
# - macOS path is external: launches the OSX-PROXMOX installer.
# ==========================================================
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
@@ -144,7 +143,7 @@ while true; do
2 "$(translate "Create") VM System Windows" \
3 "$(translate "Create") VM System Linux" \
"" "" \
"" "\Z4──────────────────────────────────────────────────\Zn" \
"" "\Z4───────────────── Community Scripts ─────────────────\Zn" \
"" "" \
4 "$(translate "Create") VM System macOS (OSX-PROXMOX)" \
5 "$(translate "Create") VM System Others (based Linux)" \
@@ -152,7 +151,6 @@ while true; do
6 "$(translate "Return to Main Menu")" \
3>&1 1>&2 2>&3)
[[ $? -ne 0 || "$OS_TYPE" == "6" ]] && exec bash "$MENU_REPO/main_menu.sh"
case "$OS_TYPE" in
+1 -1
View File
@@ -4,7 +4,7 @@
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : MIT
# License : GPL-3.0
# Version : 2.0
# Last Updated: 01/04/2026
# ==========================================================
+75 -30
View File
@@ -1,21 +1,33 @@
#!/bin/bash
# ==========================================================
# ProxMenux - A menu-driven script for Proxmox VE management
# ProxMenux - Proxmox VE Helper Scripts Browser
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : (GPL-3.0) (https://github.com/MacRimi/ProxMenux/blob/main/LICENSE)
# License : GPL-3.0
# https://github.com/MacRimi/ProxMenux/blob/main/LICENSE
# Version : 1.3
# Last Updated: 14/03/2025
# ==========================================================
# Description:
# This script provides a simple and efficient way to access and execute Proxmox VE scripts
# from the Community Scripts project (https://community-scripts.github.io/ProxmoxVE/).
# Front-end for the community-scripts/ProxmoxVE catalog
# (https://community-scripts.github.io/ProxmoxVE/)
# the spiritual continuation of tteck's helper scripts.
#
# It serves as a convenient tool to run key automation scripts that simplify system management,
# continuing the great work and legacy of tteck in making Proxmox VE more accessible.
# A streamlined solution for executing must-have tools in Proxmox VE.
# Loads a curated JSON cache (helpers_cache.json) maintained
# by ProxMenux on GitHub, lists categories + scripts with
# search and type filters, and executes the chosen script
# via "bash <(curl -s <url>)".
#
# Features:
# - Browse scripts by category (Container, OS, Network, …).
# - Free-text search across name and description.
# - Per-script details: description, notes, default credentials,
# default port, website.
# - Choice of source (GitHub or Mirror) per script.
# - Type labels: LXC / VM / PVE / ADDON / TK / GEN.
#
# Requires: curl, jq, dialog. Internet access mandatory.
# ==========================================================
@@ -44,7 +56,11 @@ for cmd in curl jq dialog; do
fi
done
CACHE_JSON=$(curl -s "$HELPERS_JSON_URL")
# `--connect-timeout` caps DNS+TCP setup; `--max-time` caps total fetch.
# Without these the menu would hang silently for minutes when the network
# is down or the upstream is slow, with no signal to the user. Audit
# Tier 6 — `menu_Helper_Scripts.sh` curl sin --max-time.
CACHE_JSON=$(curl -s --connect-timeout 5 --max-time 15 "$HELPERS_JSON_URL")
# Validate that the JSON loaded correctly
if ! echo "$CACHE_JSON" | jq -e 'if type == "array" and length > 0 then true else false end' >/dev/null 2>&1; then
@@ -93,8 +109,10 @@ get_type_label() {
download_script() {
local url="$1"
if curl --silent --head --fail "$url" >/dev/null; then
bash <(curl -s "$url")
# Same timeouts as the cache fetch above so a stalled mirror can't hang
# the menu indefinitely. The HEAD probe and the GET both get bounded.
if curl --silent --connect-timeout 5 --max-time 10 --head --fail "$url" >/dev/null; then
bash <(curl -s --connect-timeout 5 --max-time 60 "$url")
else
dialog --title "Helper Scripts" --msgbox "$(translate "Error: Failed to download the script.")" 8 70
fi
@@ -152,28 +170,45 @@ run_script_by_slug() {
decode() { echo "$1" | base64 --decode | jq -r "$2"; }
local first="${script_infos[0]}"
local name desc notes port website
local name desc notes warnings port website
name=$(decode "$first" ".name")
desc=$(decode "$first" ".desc")
notes=$(decode "$first" '.notes | join("\n")')
notes=$(decode "$first" '.notes // [] | join("\n")')
# Sprint 11.7: PocketBase upstream tags certain notes with type=="warning".
# The cache generator splits them into a separate `warnings` array so the
# menu can render them in red with a dedicated WARNINGS header instead of
# burying them inside the regular notes block.
warnings=$(decode "$first" '.warnings // [] | join("\n")')
port=$(decode "$first" ".port // 0")
website=$(decode "$first" ".website // empty")
# Build notes block
local notes_dialog=""
if [[ -n "$notes" ]]; then
while IFS= read -r line; do
[[ -z "$line" ]] && continue
notes_dialog+="$line\n"
done <<< "$notes"
notes_dialog="${notes_dialog%\\n}"
fi
local credentials
credentials=$(format_credentials "$first")
# Build info message
local msg="\Zb\Z4$(translate "Description"):\Zn\n$desc"
# Build info message — warnings first, in red, so the user sees them
# before deciding to launch the script. Sections are separated by a
# single \n (one blank line) instead of \n\n; the bullet builders below
# also strip their trailing \n so we don't double up. Helper Scripts
# like "PVE LXC Apps Update" carry a lot of text and a fixed-height
# dialog clips the bottom menu when each section eats two extra rows.
local msg="\Zb\Z4$(translate "Description"):\Zn\n$desc"
if [[ -n "$warnings" ]]; then
local warn_short=""
local char_count=0
local max_chars=400
while IFS= read -r line; do
[[ -z "$line" ]] && continue
char_count=$(( char_count + ${#line} ))
if [[ $char_count -lt $max_chars ]]; then
warn_short+="$line\n"
else
warn_short+="...\n"
break
fi
done <<< "$warnings"
warn_short="${warn_short%\\n}"
msg+="\n\Zb\Z1⚠ $(translate "Warnings"):\Zn\n\Z1${warn_short}\Zn"
fi
if [[ -n "$notes" ]]; then
local notes_short=""
local char_count=0
@@ -188,13 +223,14 @@ local msg="\Zb\Z4$(translate "Description"):\Zn\n$desc"
break
fi
done <<< "$notes"
msg+="\n\n\Zb\Z4$(translate "Notes"):\Zn\n$notes_short"
notes_short="${notes_short%\\n}"
msg+="\n\Zb\Z4$(translate "Notes"):\Zn\n$notes_short"
fi
[[ -n "$credentials" ]] && msg+="\n\n\Zb\Z4$(translate "Default Credentials"):\Zn\n$credentials"
[[ "$port" -gt 0 ]] && msg+="\n\n\Zb\Z4$(translate "Default Port"):\Zn $port"
[[ -n "$credentials" ]] && msg+="\n\Zb\Z4$(translate "Default Credentials"):\Zn\n$credentials"
[[ "$port" -gt 0 ]] && msg+="\n\Zb\Z4$(translate "Default Port"):\Zn $port"
[[ -n "$website" ]] && msg+="\n\Zb\Z4$(translate "Website"):\Zn $website"
msg+="\n\n$(translate "Choose how to run the script:")"
msg+="\n$(translate "Choose how to run the script:")"
# Build menu: one or two entries per script_info (GH + optional Mirror)
declare -a MENU_OPTS=()
@@ -251,9 +287,18 @@ local msg="\Zb\Z4$(translate "Description"):\Zn\n$desc"
echo
echo
if [[ -n "$desc" || -n "$notes" || -n "$credentials" ]]; then
if [[ -n "$desc" || -n "$notes" || -n "$warnings" || -n "$credentials" ]]; then
echo -e "$TAB\e[1;36m$(translate "Script Information"):\e[0m"
if [[ -n "$warnings" ]]; then
echo -e "$TAB\e[1;31m⚠ $(translate "Warnings"):\e[0m"
while IFS= read -r line; do
[[ -z "$line" ]] && continue
echo -e "$TAB\e[31m• $line\e[0m"
done <<< "$warnings"
echo
fi
if [[ -n "$notes" ]]; then
echo -e "$TAB\e[1;33m$(translate "Notes"):\e[0m"
while IFS= read -r line; do
+164 -5
View File
@@ -1,12 +1,19 @@
#!/bin/bash
# ==========================================================
# ProxMenux - A menu-driven script for Proxmox VE management
# ProxMenux - Post-Install Menu Dispatcher
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : (GPL-3.0) (https://github.com/MacRimi/ProxMenux/blob/main/LICENSE)
# License : GPL-3.0
# https://github.com/MacRimi/ProxMenux/blob/main/LICENSE
# Version : 1.2
# Last Updated: 06/07/2025
# ==========================================================
# Description:
# Dispatcher for the post-installation options: Automated
# (zero-prompt baseline), Customizable (checklist per category)
# and Uninstall Optimizations (reverse any previously applied
# change). Also exposes two community post-install scripts
# (Proxmox VE Post Install and Microcode) via wget | bash.
# ==========================================================
LOCAL_SCRIPTS="/usr/local/share/proxmenux/scripts"
@@ -85,6 +92,137 @@ declare -a PROXMENUX_SCRIPTS=(
"Uninstall optimizations|ProxMenux|bash \"$LOCAL_SCRIPTS/post_install/uninstall-tools.sh\""
)
# ==========================================================
# Sprint 12C: post-install function update detection.
#
# The Monitor's startup hook writes updates_available.json. We read it
# here so the bash menu can show a conditional "Apply available updates"
# entry above Uninstall when bumped versions are detected on disk vs the
# user's installed_tools.json.
# ==========================================================
UPDATES_FILE="/usr/local/share/proxmenux/updates_available.json"
UPDATE_WRAPPER="$LOCAL_SCRIPTS/post_install/update_post_install_function.sh"
count_post_install_updates() {
[[ ! -f "$UPDATES_FILE" ]] && { echo 0; return; }
command -v jq >/dev/null 2>&1 || { echo 0; return; }
jq '.updates | length' "$UPDATES_FILE" 2>/dev/null || echo 0
}
# Build a dialog checklist with the available updates and run the
# wrapper script for whichever the user picks. Entries flagged
# `source_certain=false` (legacy bool entries) are listed but not
# pre-checked; they need a source pick first via the Monitor or a
# fresh re-run of the customizable post-install.
run_updates_dialog() {
if ! command -v jq >/dev/null 2>&1; then
msg_error "$(translate "jq is required to apply updates from this menu.")"
sleep 2
return
fi
if [[ ! -f "$UPDATES_FILE" ]]; then
msg_warn "$(translate "No updates available — run a scan first or wait for the Monitor to refresh.")"
sleep 2
return
fi
local count
count=$(count_post_install_updates)
if [[ "$count" -eq 0 ]]; then
msg_ok "$(translate "All ProxMenux optimizations are up to date.")"
sleep 2
return
fi
# Build the dialog --checklist arguments. Format per row:
# <tag> <description> <on|off>
# We use the tool key as the tag so the selection callback can map
# back to source/function via jq.
local checklist=()
while IFS=$'\t' read -r key current available; do
# Sprint 12C v2: every row is checked by default. Legacy bool
# entries default to the auto flow on the wrapper side so the
# user no longer needs to do a "source pick" first.
local label="${key} (v${current} → v${available})"
checklist+=("$key" "$label" "on")
done < <(jq -r '.updates[] | [.key, .current_version, .available_version] | @tsv' "$UPDATES_FILE" 2>/dev/null)
if [[ ${#checklist[@]} -eq 0 ]]; then
msg_warn "$(translate "Updates file is empty or unreadable.")"
sleep 2
return
fi
local selected
selected=$(dialog --clear --colors --separate-output \
--backtitle "ProxMenux" \
--title "$(translate "Apply Available Updates")" \
--checklist "\n$(translate "Select the optimizations to update. Each one re-runs its post-install function and registers the new version."):\n" \
22 78 12 \
"${checklist[@]}" 3>&1 1>&2 2>&3)
local rc=$?
clear
[[ $rc -ne 0 ]] && return # cancelled
[[ -z "$selected" ]] && return
# Build FUNCTIONS_BATCH (newline-separated source:function:key) by
# looking up each picked key in the JSON. The detector already
# populates `.source` (defaulting to "auto" for legacy bool entries
# that didn't record one) and `.function`, so this is a straight
# passthrough. Sprint 12C v2 dropped the source-pick gate.
local batch=""
while IFS= read -r key; do
[[ -z "$key" ]] && continue
local entry
entry=$(jq -r --arg k "$key" '
.updates[] | select(.key == $k) |
select(.function != "") |
"\((.source // "auto")):\(.function):\(.key)"
' "$UPDATES_FILE")
[[ -n "$entry" ]] && batch+="${entry}"$'\n'
done <<< "$selected"
if [[ -z "$batch" ]]; then
msg_warn "$(translate "Nothing to apply — none of the selected updates have a runnable function on disk.")"
sleep 3
return
fi
# Hand off to the same wrapper the Monitor uses. Running it directly
# (not through a dialog menu) so the user sees the post-install
# function output verbatim.
EXECUTION_MODE="cli" FUNCTIONS_BATCH="$batch" bash "$UPDATE_WRAPPER"
# Sprint 12C v2: force the Monitor to rewrite updates_available.json
# so the next loop iteration of show_menu sees the post-update state
# and the "Apply available updates (N)" entry hides/decrements
# correctly. The endpoint is exposed on localhost without auth (POST
# is idempotent — just re-runs the parser), so a plain curl works
# whether HTTPS is on or off. Falls back to direct file write via
# the Python module if the service isn't reachable (host where the
# Monitor isn't running yet).
local scheme="http"
[[ -f /etc/proxmenux/ssl_config.json ]] && \
jq -e '.enabled' /etc/proxmenux/ssl_config.json >/dev/null 2>&1 && \
scheme="https"
if ! curl -k -s --max-time 5 -X POST "${scheme}://127.0.0.1:8008/api/updates/post-install/scan" >/dev/null 2>&1; then
# Fallback: regenerate the JSON via the module directly. We
# can't import it from system Python because dependencies live
# inside the AppImage, so just rewrite the file by re-running
# the detector logic in-process via jq + the on-disk scripts.
# Simpler: leave the file stale — the next AppImage restart will
# rewrite it. The Monitor's _ensure_fresh_cache also auto-
# refreshes when installed_tools.json changes, so the API view
# is correct even if the bash menu sees a one-cycle-stale list.
:
fi
msg_success "$(translate 'Press ENTER to continue...')"
read -r _
}
declare -a COMMUNITY_SCRIPTS=(
"Proxmox VE Post Install|Helper-Scripts|bash -c \"\$(wget -qLO - https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/pve/post-pve-install.sh); msg_success \\\"\$(translate 'Press ENTER to continue...')\\\"; read -r _\""
@@ -119,14 +257,35 @@ format_menu_item() {
show_menu() {
while true; do
local menu_items=()
declare -A script_commands
local counter=1
# Sprint 12C: re-evaluate available updates on every loop so the
# entry vanishes after the user has applied everything (and the
# Monitor has rewritten updates_available.json on its next scan).
local update_count
update_count=$(count_post_install_updates)
for script in "${PROXMENUX_SCRIPTS[@]}"; do
IFS='|' read -r name source command <<< "$script"
# Insert the conditional "Apply available updates" item right
# above "Uninstall optimizations" so it sits next to the
# related rollback action and not buried in the middle.
if [[ "$name" == "Uninstall optimizations" && "$update_count" -gt 0 ]]; then
local update_label
update_label="Apply available updates ($update_count)"
local translated_update
translated_update="$(translate "$update_label")"
local formatted_update
formatted_update=$(format_menu_item "$translated_update" "ProxMenux")
menu_items+=("$counter" "$formatted_update")
script_commands["$counter"]="run_updates_dialog"
((counter++))
fi
local translated_name="$(translate "$name")"
local formatted_item
formatted_item=$(format_menu_item "$translated_name" "$source")
+181 -27
View File
@@ -4,17 +4,32 @@
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : (GPL-3.0) (https://github.com/MacRimi/ProxMenux/blob/main/LICENSE)
# License : GPL-3.0
# https://github.com/MacRimi/ProxMenux/blob/main/LICENSE
# Version : 1.1
# Last Updated: 08/07/2025
# ==========================================================
# Description:
# Advanced network management and troubleshooting tool for Proxmox VE.
# Features include interface detection, bridge management, connectivity testing,
# network diagnostics, configuration backup/restore, and automated repairs.
# Special thanks to @Andres_Eduardo_Rojas_Moya for contributing the persistent
# network naming function and for the original idea.
# Network management and troubleshooting tool for Proxmox VE.
# Operates exclusively on the classic Debian/Proxmox network stack
# (/etc/network/interfaces). Aborts safely on netplan / systemd-networkd
# / NetworkManager hosts to avoid corrupting unsupported configurations.
#
# Features:
# - Read-only diagnostics: routing table, connectivity tests, advanced
# network statistics, bridge and interface configuration analysis.
# - Real-time monitoring launchers (iftop, iptraf-ng).
# - Guided repair flows for invalid bridge ports and orphaned interface
# configurations, with mandatory backup and step-by-step preview.
# - Persistent network interface naming via systemd .link files
# (MAC-based, survives hardware changes and PCI re-enumeration).
# - Manual backup / restore of /etc/network/interfaces under
# /var/backups/proxmenux/.
# - Network service restart with confirmation.
# - Curated community scripts (e.g., NIC offloading fix for Intel e1000e).
#
# Acknowledgements:
# Persistent network naming function originally contributed by
# @Andres_Eduardo_Rojas_Moya.
# Configuration ============================================
LOCAL_SCRIPTS="/usr/local/share/proxmenux/scripts"
BASE_DIR="/usr/local/share/proxmenux"
@@ -112,17 +127,9 @@ get_interface_info() {
# ==========================================================
show_routing_table_() {
local route_info=""
route_info+="$(translate "Routing Table")\n"
route_info+="$(printf '=%.0s' {1..30})\n\n"
route_info+="$(ip route show)\n\n"
route_info+="$(translate "Default Gateway"): $(ip route | grep default | awk '{print $3}' | head -1)\n"
dialog --backtitle "ProxMenux" --title "$(translate "Routing Information")" \
--msgbox "$route_info" 20 80
}
# Note: previous `show_routing_table_` (with trailing underscore) was
# dead code — never referenced anywhere. Removed in Sprint 10T.7.
# `show_routing_table` below is the active implementation.
show_routing_table() {
local route_info=""
@@ -929,9 +936,21 @@ restore_network_backup() {
if dialog --backtitle "ProxMenux" --title "$(translate "Restart Network")" \
--yesno "\n$(translate "Do you want to restart the network service now to apply changes?")" 8 60; then
if systemctl restart networking; then
# Capture stdout+stderr and check the exit code directly
# via the assignment's success — `$?` after a command-
# substitution assignment is the substitution's exit code,
# which is fragile (non-zero shell options affect it).
local _restart_err
if _restart_err=$(systemctl restart networking 2>&1); then
dialog --backtitle "ProxMenux" --title "$(translate "Network Restarted")" \
--msgbox "\n$(translate "Network service restarted successfully.")" 8 50
else
# Surface the failure — silent failure left the user
# thinking the restart worked while they're actually
# locked out of network. Audit Tier 7 — restore_network_backup
# no reporta fallo del restart de networking.
dialog --backtitle "ProxMenux" --title "$(translate "Network Restart Failed")" \
--msgbox "\n$(translate "systemctl restart networking failed:")\n\n${_restart_err:-unknown error}\n\n$(translate "Restored config is on disk; reboot the host to apply.")" 14 70
fi
fi
fi
@@ -939,26 +958,160 @@ restore_network_backup() {
}
launch_iftop() {
if ! command -v iftop &>/dev/null; then
apt-get update -qq && apt-get install -y iftop &>/dev/null
# ---------------------------------------------------------------
# Shared helper for the monitoring tool launchers.
# Ensures a given network tool is installed using the canonical
# repo + install pattern from global/utils-install-functions.sh.
# Args: package_name verify_command description
# Returns: 0 on success, 1 on failure (with the user already
# acknowledged via "Press Enter to return to menu").
# ---------------------------------------------------------------
_ensure_network_tool() {
local pkg="$1"
local cmd="${2:-$pkg}"
local desc="${3:-$pkg}"
if command -v "$cmd" &>/dev/null; then
return 0
fi
if [[ -f "$LOCAL_SCRIPTS/global/utils-install-functions.sh" ]]; then
source "$LOCAL_SCRIPTS/global/utils-install-functions.sh"
fi
if ! type ensure_repositories &>/dev/null || ! type install_single_package &>/dev/null; then
clear
show_proxmenux_logo
msg_title "$(translate "Installing") $pkg"
msg_error "$(translate "Required install helpers not available.")"
msg_warn "$(translate "Cannot find") global/utils-install-functions.sh"
echo -e ""
msg_success "$(translate "Press Enter to return to menu...")"
read -r
return 1
fi
clear
show_proxmenux_logo
msg_title "$(translate "Installing") $pkg"
if ! ensure_repositories; then
msg_error "$(translate "Failed to configure repositories. Installation aborted.")"
echo -e ""
msg_success "$(translate "Press Enter to return to menu...")"
read -r
return 1
fi
install_single_package "$pkg" "$cmd" "$desc"
local rc=$?
if [[ $rc -eq 1 ]]; then
echo -e ""
msg_success "$(translate "Press Enter to return to menu...")"
read -r
return 1
fi
# rc=0 (installed and available) or rc=2 (installed, hash refresh pending —
# invoking the binary by name through PATH lookup still works).
return 0
}
launch_iftop() {
_ensure_network_tool "iftop" "iftop" "Real-time network usage" || return
dialog --backtitle "ProxMenux" --title "$(translate "iftop usage")" --msgbox "\n$(translate "To exit iftop, press q")" 8 50
clear
iftop
}
launch_iptraf() {
if ! command -v iptraf-ng &>/dev/null; then
apt-get update -qq && apt-get install -y iptraf-ng &>/dev/null
fi
_ensure_network_tool "iptraf-ng" "iptraf-ng" "Network monitoring tool" || return
dialog --backtitle "ProxMenux" --title "$(translate "iptraf-ng usage")" --msgbox "\n$(translate "To exit iptraf-ng, press x")" 8 50
clear
iptraf-ng
}
launch_iperf3() {
_ensure_network_tool "iperf3" "iperf3" "Network bandwidth testing" || return
# Mode selection
local mode
mode=$(dialog --backtitle "ProxMenux" \
--title "$(translate "iperf3 - Bandwidth test")" \
--menu "\n$(translate "Choose iperf3 mode:")" 12 70 2 \
"1" "$(translate "Server (listen for incoming tests on TCP 5201)")" \
"2" "$(translate "Client (run a bandwidth test to a server)")" \
3>&1 1>&2 2>&3) || return
case "$mode" in
1)
# Server mode
dialog --backtitle "ProxMenux" --title "$(translate "iperf3 server")" \
--msgbox "\n$(translate "Server will listen on TCP port 5201.")\n\n$(translate "Press Ctrl+C to stop the server and return to menu.")" 11 65
show_proxmenux_logo
msg_title "$(translate "iperf3 - Bandwidth test (Server mode)")"
echo -e "${TAB}${BGN}$(translate "Listening on:")${CL} ${BL}TCP 0.0.0.0:5201${CL}"
echo -e "${TAB}${BGN}$(translate "To stop:")${CL} ${BL}Ctrl+C${CL}"
echo -e ""
echo -e "${BOLD}─────────── $(translate "iperf3 server output") ───────────${CL}"
echo -e ""
iperf3 -s
echo -e ""
msg_success "$(translate "Server stopped. Press Enter to return to menu...")"
read -r
;;
2)
# Client mode
local target
target=$(dialog --backtitle "ProxMenux" --title "$(translate "iperf3 client")" \
--inputbox "\n$(translate "Enter the iperf3 server IP or hostname:")" 10 60 \
3>&1 1>&2 2>&3) || return
# Trim whitespace from input
target=$(echo "$target" | tr -d '[:space:]')
if [[ -z "$target" ]]; then
dialog --backtitle "ProxMenux" --title "$(translate "Invalid input")" \
--msgbox "\n$(translate "No server IP or hostname provided.")" 8 55
return 1
fi
show_proxmenux_logo
msg_title "$(translate "iperf3 - Bandwidth test (Client mode)")"
echo -e "${TAB}${BGN}$(translate "Target server:")${CL} ${BL}$target${CL}"
echo -e "${TAB}${BGN}$(translate "Port:")${CL} ${BL}TCP 5201${CL}"
echo -e "${TAB}${BGN}$(translate "Duration:")${CL} ${BL}10 $(translate "seconds (default)")${CL}"
echo -e ""
echo -e "${BOLD}─────────── $(translate "iperf3 client output") ───────────${CL}"
echo -e ""
if iperf3 -c "$target"; then
echo -e ""
msg_ok "$(translate "Bandwidth test completed successfully")"
else
echo -e ""
msg_error "$(translate "iperf3 test failed")"
msg_warn "$(translate "Check that:")"
echo -e "${TAB}$(translate "iperf3 server is running on") ${BL}$target${CL}"
echo -e "${TAB}$(translate "TCP port 5201 is reachable (firewall on server)")"
echo -e "${TAB}$(translate "Network connectivity to") ${BL}$target${CL}"
fi
echo -e ""
msg_success "$(translate "Press Enter to return to menu...")"
read -r
;;
esac
}
# ==========================================================
@@ -989,6 +1142,7 @@ confirm_and_run() {
declare -a PROXMENUX_SCRIPTS=(
"Real-time network usage (iftop)||launch_iftop"
"Network monitoring tool (iptraf-ng)||launch_iptraf"
"Bandwidth test (iperf3)||launch_iperf3"
"Show Routing Table||show_routing_table"
"Test Connectivity||test_connectivity"
"Advanced Diagnostics||advanced_network_diagnostics"
@@ -1075,7 +1229,7 @@ show_menu() {
--backtitle "ProxMenux" \
--title "$(translate "Network Management")" \
--menu "\n$(translate "Select a network management option:"):\n" \
26 78 19 \
28 78 19 \
"${menu_items[@]}" 2>&1 1>&3)
exit_status=$?
exec 3>&-
+17 -3
View File
@@ -1,11 +1,25 @@
#!/bin/bash
# ==========================================================
# ProxMenux - Security Menu
# ============================================
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : (GPL-3.0) (https://github.com/MacRimi/ProxMenux/blob/main/LICENSE)
# License : GPL-3.0
# https://github.com/MacRimi/ProxMenux/blob/main/LICENSE
# Version : 1.0
# ============================================
# ==========================================================
# Description:
# Dispatcher for security tools shipped with ProxMenux. Loads the
# selected installer/manager script and returns to the main menu
# on cancel.
#
# Features:
# - Fail2Ban — intrusion prevention for SSH and the Proxmox /
# ProxMenux Monitor web interfaces, with auto-detected firewall
# backend (nftables / iptables).
# - Lynis — security auditing tool installed from upstream
# GitHub (always latest), with run-audit and update actions.
# ==========================================================
SCRIPT_TITLE="Security Tools"
+23 -15
View File
@@ -1,12 +1,18 @@
#!/bin/bash
# ==========================================================
# ProxMenux - Network Storage Manager Menu
# ProxMenux - Storage & Share Manager Menu
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : MIT
# License : GPL-3.0
# https://github.com/MacRimi/ProxMenux/blob/main/LICENSE
# Version : 1.2
# Last Updated: $(date +%d/%m/%Y)
# ==========================================================
# Description:
# Dispatcher for the Storage & Share Manager menu. Two blocks:
# HOST (register external or local storage as Proxmox storage,
# plus the local shared directory helper) and LXC (bind mount
# manager, NFS / Samba client and server for privileged CTs).
# ==========================================================
# Configuration
@@ -27,21 +33,23 @@ initialize_cache
while true; do
OPTION=$(dialog --colors --backtitle "ProxMenux" \
--title "$(translate "Storage & Share Manager")" \
--menu "\n$(translate "Select an option:")" 26 78 17 \
--menu "\n$(translate "Select an option:")" 28 78 17 \
"" "\Z4──────────────────────── HOST ─────────────────────────\Zn" \
"1" "$(translate "Configure NFS shared on Host")" \
"2" "$(translate "Configure Samba shared on Host")" \
"3" "$(translate "Configure Local Shared on Host")" \
"1" "$(translate "Add NFS share as Proxmox Storage")" \
"2" "$(translate "Add Samba share as Proxmox Storage")" \
"3" "$(translate "Add iSCSI Target as Proxmox Storage")" \
"4" "$(translate "Add Local Disk as Proxmox Storage")" \
"5" "$(translate "Add iSCSI Target as Proxmox Storage")" \
"" "" \
"" "\Z4─────────────── Host-only resources ──────────────────\Zn" \
"5" "$(translate "Add Shared Directory on Host")" \
"" "" \
"" "\Z4──────────────────────── LXC ─────────────────────────\Zn" \
"6" "$(translate "Configure LXC Mount Points (Host ↔ Container)")" \
"" "" \
"7" "$(translate "Configure NFS Client in LXC (only privileged)")" \
"7" "$(translate "Configure NFS Client in LXC (only privileged)")" \
"8" "$(translate "Configure Samba Client in LXC (only privileged)")" \
"9" "$(translate "Configure NFS Server in LXC (only privileged)")" \
"10" "$(translate "configure Samba Server in LXC (only privileged)")" \
"9" "$(translate "Configure NFS Server in LXC (only privileged)")" \
"10" "$(translate "Configure Samba Server in LXC (only privileged)")" \
"" "" \
"h" "$(translate "Help & Info (commands)")" \
"0" "$(translate "Return to Main Menu")" \
@@ -61,21 +69,21 @@ while true; do
bash "$LOCAL_SCRIPTS/share/samba_host.sh"
;;
3)
bash "$LOCAL_SCRIPTS/share/local-shared-manager.sh"
bash "$LOCAL_SCRIPTS/share/iscsi_host.sh"
;;
4)
bash "$LOCAL_SCRIPTS/share/disk_host.sh"
;;
5)
bash "$LOCAL_SCRIPTS/share/iscsi_host.sh"
bash "$LOCAL_SCRIPTS/share/local-shared-manager.sh"
;;
6)
bash "$LOCAL_SCRIPTS/share/lxc-mount-manager_minimal.sh"
;;
7)
bash "$LOCAL_SCRIPTS/share/nfs_client.sh"
;;
8)
;;
8)
bash "$LOCAL_SCRIPTS/share/samba_client.sh"
;;
9)
+24 -4
View File
@@ -1,13 +1,33 @@
#!/bin/bash
# ==========================================================
# ProxMenux - A menu-driven script for Proxmox VE management
# ProxMenux - Utilities Menu
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : (GPL-3.0) (https://github.com/MacRimi/ProxMenux/blob/main/LICENSE)
# License : GPL-3.0
# https://github.com/MacRimi/ProxMenux/blob/main/LICENSE
# Version : 1.0
# Last Updated: 02/07/2025
# ==========================================================
# Description:
# Dispatcher for the Utilities & Tools section. Six options that
# cover ISO creation, system utility installation, Proxmox updates,
# major-version upgrade (PVE 8 → 9) and VM portability (OVA / OVF).
#
# Features:
# - UUP Dump ISO creator: build official Windows ISOs from UUP
# Dump using a shared link.
# - System Utilities Installer: 26 curated CLI tools (htop, btop,
# iperf3, jq, tmux, ...) in custom-pick or predefined groups.
# - Proxmox System Update: repos hygiene + apt update + apt
# dist-upgrade with reboot prompt (delegates to per-version
# worker scripts in global/).
# - Upgrade PVE 8 to PVE 9: automated or interactive major-version
# upgrade with pre-checks, repo migration and post-upgrade
# validation. Manual guide alternative also exposed.
# - Export VM to OVA / OVF: convert a Proxmox VM to a portable
# OVA archive or OVF directory (VMware / VirtualBox / etc).
# - Import VM from OVA / OVF: import a VMware / VirtualBox /
# ProxMenux export back into Proxmox.
# ==========================================================
+1 -1
View File
@@ -2,7 +2,7 @@
# ProxMenux - OCI Application Manager
# ============================================
# Author : MacRimi
# License : MIT
# License : GPL-3.0
# Version : 1.0
# ============================================
# Manages OCI container applications through dialog menus or direct CLI.
+118 -53
View File
@@ -1,37 +1,30 @@
#!/bin/bash
# ==========================================================
# ProxMenux - Complete Post-Installation Script with Registration
# ProxMenux - Automated Post-Install Script
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : (GPL-3.0) (https://github.com/MacRimi/ProxMenux/blob/main/LICENSE)
# License : GPL-3.0
# https://github.com/MacRimi/ProxMenux/blob/main/LICENSE
# Version : 1.0
# Last Updated: 06/07/2025
# ==========================================================
# Description:
# Applies a curated set of 13 safe optimizations to a fresh
# Proxmox VE host without prompts. Every change is registered
# in installed_tools.json so it can be reversed later from the
# Uninstall Optimizations menu.
#
# The script performs system optimizations including:
# - Repository configuration and system upgrades
# - Subscription banner removal and UI enhancements
# - Advanced memory management and kernel optimizations
# - Network stack tuning and security hardening
# - Storage optimizations including log2ram for SSD protection
# - System limits increases and entropy generation improvements
# - Journald and logrotate optimizations for better log management
# - Security enhancements including RPC disabling and time synchronization
# - Bash environment customization and system monitoring setup
# Features:
# - Zero-interaction baseline: repos, upgrade, banner, APT
# IPv4, skip translations, kernel limits, memory tuning,
# kernel-panic behaviour, network stack tuning, bashrc,
# Log2RAM (SSD-aware), journald, logrotate, persistent NIC names.
# - Hardware-aware: auto-detects SSD/NVMe for Log2RAM and sizes
# its ramdisk according to host RAM (128M/256M/512M).
# - Registration: tracks each tool in installed_tools.json.
# - Rollback: every tool has a reverse function in uninstall-tools.sh.
#
# Key Features:
# - Zero-interaction automation: Runs completely unattended
# - Intelligent hardware detection: Automatically detects SSD/NVMe for log2ram
# - RAM-aware configurations: Adjusts settings based on available system memory
# - Comprehensive error handling: Robust installation with fallback mechanisms
# - Registration system: Tracks installed optimizations for easy management
# - Reboot management: Intelligently handles reboot requirements
# - Translation support: Multi-language compatible through ProxMenux framework
# - Rollback compatibility: All optimizations can be reversed using the uninstall script
#
# This script is based on the post-install script cutotomizable
# Shares the function library with customizable_post_install.sh.
# ==========================================================
@@ -55,17 +48,49 @@ RAM_SIZE_GB=$(( $(vmstat -s | grep -i "total memory" | xargs | cut -d" " -f 1) /
NECESSARY_REBOOT=0
export SCRIPT_TITLE="ProxMenux Optimization Post-Installation"
# Sprint 12A: identify which post-install flow is calling register_tool.
# auto_post_install.sh always emits source=auto; customizable sets "custom".
# The detector uses this to know which function to compare against and
# which one to re-run when applying an update (preserves user's choice
# between the auto and the custom flow of the same tool).
SCRIPT_SOURCE="auto"
# ==========================================================
# Tool registration system
ensure_tools_json() {
[ -f "$TOOLS_JSON" ] || echo "{}" > "$TOOLS_JSON"
}
# Sprint 12A: register_tool accepts (key, state, version, source).
# key — tool identifier (existing)
# state — true/false (existing)
# version — defaults to "1.0"; each function declares its own version as
# `local FUNC_VERSION="X.Y"` on the first line and passes
# "$FUNC_VERSION" here. We use a `local` variable rather than a
# `# version:` comment because bash's `declare -f` strips
# comments — so a comment-based version was lost when the
# update wrapper sourced the script and re-ran the function.
# source — defaults to $SCRIPT_SOURCE (auto/custom) so the detector
# knows which flow to compare against and which to re-run on
# update.
# On install (state=true) the entry becomes a structured object
# {installed: true, version: "X.Y", source: "auto"|"custom"}
# On uninstall (state=false) we keep the legacy boolean false so the rest
# of the pipeline (uninstall-tools.sh, frontend) keeps working.
register_tool() {
local tool="$1"
local state="$2"
local version="${3:-1.0}"
local source="${4:-${SCRIPT_SOURCE:-unknown}}"
ensure_tools_json
jq --arg t "$tool" --argjson v "$state" '.[$t]=$v' "$TOOLS_JSON" > "$TOOLS_JSON.tmp" && mv "$TOOLS_JSON.tmp" "$TOOLS_JSON"
if [[ "$state" == "true" ]]; then
jq --arg t "$tool" --arg ver "$version" --arg src "$source" \
'.[$t]={"installed": true, "version": $ver, "source": $src}' \
"$TOOLS_JSON" > "$TOOLS_JSON.tmp" && mv "$TOOLS_JSON.tmp" "$TOOLS_JSON"
else
jq --arg t "$tool" '.[$t]=false' \
"$TOOLS_JSON" > "$TOOLS_JSON.tmp" && mv "$TOOLS_JSON.tmp" "$TOOLS_JSON"
fi
}
@@ -166,6 +191,8 @@ remove_subscription_banner() {
configure_time_sync() {
local FUNC_VERSION="1.0"
# description: Detect timezone from public IP and enable systemd time sync (NTP).
msg_info2 "$(translate "Configuring system time settings...")"
this_ip=$(dig +short myip.opendns.com @resolver1.opendns.com 2>/dev/null)
@@ -174,20 +201,30 @@ configure_time_sync() {
return 0
fi
timezone=$(curl -s --connect-timeout 10 "https://ipapi.co/${this_ip}/timezone" 2>/dev/null)
timezone=$(curl -s --connect-timeout 10 "https://ipapi.co/${this_ip}/timezone" 2>/dev/null | tr -d '[:space:]')
if [ -z "$timezone" ] || [ "$timezone" = "undefined" ]; then
msg_warn "$(translate "Failed to determine timezone from IP address - keeping current timezone settings")"
return 0
fi
# Validate against the system's IANA timezone database before applying.
# ipapi.co can return rate-limit JSON, an error string, or stale data; the
# previous code accepted anything that wasn't literally "undefined" and
# passed it straight to `timedatectl set-timezone`, which silently kept
# the old TZ on a bad value.
if ! timedatectl list-timezones 2>/dev/null | grep -Fxq "$timezone"; then
msg_warn "$(translate "API returned an invalid timezone") ($timezone) - $(translate "keeping current settings")"
return 0
fi
msg_ok "$(translate "Found timezone $timezone for IP $this_ip")"
if timedatectl set-timezone "$timezone"; then
msg_ok "$(translate "Timezone set to $timezone")"
if timedatectl set-ntp true; then
msg_ok "$(translate "Time settings configured - Timezone:") $timezone"
register_tool "time_sync" true
register_tool "time_sync" true "$FUNC_VERSION"
systemctl restart postfix 2>/dev/null || true
else
@@ -204,17 +241,20 @@ configure_time_sync() {
# ==========================================================
skip_apt_languages() {
local FUNC_VERSION="1.0"
# description: Stop APT from downloading translation files to speed up updates.
msg_info "$(translate "Configuring APT to skip downloading additional languages...")"
cat > /etc/apt/apt.conf.d/99-disable-translations <<'EOF'
Acquire::Languages "none";
EOF
msg_ok "$(translate "APT configured to skip additional languages")"
register_tool "apt_languages" true
register_tool "apt_languages" true "$FUNC_VERSION"
}
# ==========================================================
optimize_journald() {
local FUNC_VERSION="1.0"
# description: Cap journald size, raise rate limit and force info-level logging so the log viewer and Fail2Ban work.
if [ -f /etc/log2ram.conf ] || [ -d /var/log.hdd ]; then
return 0
fi
@@ -254,18 +294,20 @@ EOF
journalctl --rotate > /dev/null 2>&1
msg_ok "$(translate "Journald optimized - Max size: 64M")"
register_tool "journald" true
register_tool "journald" true "$FUNC_VERSION"
}
# ==========================================================
optimize_logrotate() {
local FUNC_VERSION="1.1"
# description: Replace logrotate.conf with a Log2RAM-friendly profile (daily rotation, copytruncate).
msg_info "$(translate "Optimizing logrotate configuration...")"
local logrotate_conf="/etc/logrotate.conf"
local backup_conf="${logrotate_conf}.bak"
if ! grep -q "# ProxMenux optimized configuration" "$logrotate_conf"; then
cp "$logrotate_conf" "$backup_conf"
cat <<EOF > "$logrotate_conf"
cp -n "$logrotate_conf" "$backup_conf" 2>/dev/null || true
cat <<EOF > "$logrotate_conf"
# ProxMenux optimized configuration (Log2RAM-friendly)
daily
su root adm
@@ -279,15 +321,16 @@ create 0640 root adm
copytruncate
include /etc/logrotate.d
EOF
systemctl restart logrotate > /dev/null 2>&1
fi
systemctl restart logrotate > /dev/null 2>&1
msg_ok "$(translate "Logrotate optimization completed")"
register_tool "logrotate" true
register_tool "logrotate" true "$FUNC_VERSION"
}
# ==========================================================
increase_system_limits() {
local FUNC_VERSION="1.1"
# description: Raise inotify watches, file descriptors, process keys and PID limits to enterprise levels.
msg_info "$(translate "Increasing various system limits...")"
NECESSARY_REBOOT=1
@@ -355,11 +398,13 @@ fs.aio-max-nr = 1048576
EOF
msg_ok "$(translate "System limits increase completed.")"
register_tool "system_limits" true
register_tool "system_limits" true "$FUNC_VERSION"
}
# ==========================================================
optimize_memory_settings() {
local FUNC_VERSION="1.1"
# description: Tune swappiness, dirty page ratios, overcommit and compaction proactiveness for VM hosts.
msg_info "$(translate "Optimizing memory settings...")"
NECESSARY_REBOOT=1
@@ -377,11 +422,13 @@ EOF
fi
msg_ok "$(translate "Memory optimization completed.")"
register_tool "memory_settings" true
register_tool "memory_settings" true "$FUNC_VERSION"
}
# ==========================================================
configure_kernel_panic() {
local FUNC_VERSION="1.0"
# description: Auto-reboot on kernel panic / oops / hardlockup; write crash dumps to /var/crash.
msg_info "$(translate "Configuring kernel panic behavior")"
NECESSARY_REBOOT=1
@@ -394,22 +441,26 @@ kernel.hardlockup_panic = 1
EOF
msg_ok "$(translate "Kernel panic behavior configuration completed")"
register_tool "kernel_panic" true
register_tool "kernel_panic" true "$FUNC_VERSION"
}
# ==========================================================
force_apt_ipv4() {
local FUNC_VERSION="1.0"
# description: Force APT to use IPv4 to avoid stalls on hosts with broken IPv6 connectivity.
msg_info "$(translate "Configuring APT to use IPv4...")"
echo 'Acquire::ForceIPv4 "true";' > /etc/apt/apt.conf.d/99-force-ipv4
msg_ok "$(translate "APT IPv4 configuration completed")"
register_tool "apt_ipv4" true
register_tool "apt_ipv4" true "$FUNC_VERSION"
}
# ==========================================================
apply_network_optimizations() {
local FUNC_VERSION="1.0"
# description: Tune TCP buffers, somaxconn, IPv4 hardening and disable rp_filter on fw bridges (PVE 9 compatible).
msg_info "$(translate "Optimizing network settings...")"
NECESSARY_REBOOT=1
@@ -484,7 +535,7 @@ EOF
fi
msg_ok "$(translate "Network optimization completed")"
register_tool "network_optimization" true
register_tool "network_optimization" true "$FUNC_VERSION"
}
@@ -495,6 +546,8 @@ EOF
# ==========================================================
customize_bashrc() {
local FUNC_VERSION="1.0"
# description: Inject the ProxMenux core bashrc block (aliases, prompt, history) into root's .bashrc, idempotent via begin/end markers.
msg_info "$(translate "Customizing bashrc for root user...")"
local bashrc="/root/.bashrc"
local bash_profile="/root/.bash_profile"
@@ -532,7 +585,7 @@ EOF
fi
msg_ok "$(translate "Bashrc customization completed")"
register_tool "bashrc_custom" true
register_tool "bashrc_custom" true "$FUNC_VERSION"
}
@@ -547,11 +600,14 @@ EOF
install_log2ram_auto() {
local FUNC_VERSION="1.1"
# description: Install Log2RAM with size auto-tuned to host RAM (128M/256M/512M); SSD/M.2 detection skips on rotational disks.
# ── Reinstall detection ─────────────────────────────────────────────────
# If log2ram was previously installed by ProxMenux (register_tool "log2ram" true),
# skip hardware detection and reinstall directly — no prompts, transparent to user.
if [[ -f "$TOOLS_JSON" ]] && jq -e '.log2ram == true' "$TOOLS_JSON" >/dev/null 2>&1; then
# If log2ram was previously installed by ProxMenux, skip hardware detection
# and reinstall directly — no prompts, transparent to user. Sprint 12A:
# also matches the new structured form `{"installed": true, ...}` written by
# the updated register_tool, in addition to the legacy boolean true entry.
if [[ -f "$TOOLS_JSON" ]] && jq -e '.log2ram == true or .log2ram.installed == true' "$TOOLS_JSON" >/dev/null 2>&1; then
msg_ok "$(translate "Log2RAM already registered — updating to latest configuration")"
else
# ── First-time install: detect SSD/M.2 ─────────────────────────────────
@@ -769,7 +825,7 @@ EOF
msg_ok "$(translate "Journald configuration adjusted to") ${USE_MB}M (Log2RAM ${LOG2RAM_SIZE})"
register_tool "log2ram" true
register_tool "log2ram" true "$FUNC_VERSION"
}
@@ -783,6 +839,8 @@ EOF
setup_persistent_network() {
local FUNC_VERSION="1.0"
# description: Pin NIC names to MAC addresses via systemd .link files so kernel updates don't shuffle interface names.
local LINK_DIR="/etc/systemd/network"
local BACKUP_DIR="/etc/systemd/network/backup-$(date +%Y%m%d-%H%M%S)"
local pve_version
@@ -791,6 +849,13 @@ setup_persistent_network() {
msg_info "$(translate "Setting up persistent network interfaces")"
sleep 2
# Same legacy-conflict warning as in customizable_post_install.sh.
if [[ -f /etc/network/interfaces ]]; then
if grep -qE '^[[:space:]]*allow-hotplug[[:space:]]' /etc/network/interfaces 2>/dev/null; then
msg_warn "$(translate '/etc/network/interfaces uses allow-hotplug. Renaming interfaces via systemd .link can break that flow — review the file after reboot.')"
fi
fi
mkdir -p "$LINK_DIR"
if ls "$LINK_DIR"/*.link >/dev/null 2>&1; then
@@ -833,7 +898,7 @@ EOF
else
msg_warn "$(translate "No physical interfaces found")"
fi
register_tool "persistent_network" true
register_tool "persistent_network" true "$FUNC_VERSION"
}
+229 -83
View File
@@ -1,50 +1,39 @@
#!/bin/bash
# ==========================================================
# ProxMenux - Customizable script settings for Proxmox post-installation
# ProxMenux - Customizable Post-Install Script
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : (GPL-3.0) (https://github.com/MacRimi/ProxMenux/blob/main/LICENSE)
# License : GPL-3.0
# https://github.com/MacRimi/ProxMenux/blob/main/LICENSE
# Version : 1.3
# Last Updated: 30/06/2025
# ==========================================================
# Description:
# This script automates post-installation configurations and optimizations
# for Proxmox Virtual Environment (VE). It allows for a variety of system
# customizations, including kernel optimizations, memory management, network
# tweaks, and virtualization environment adjustments. The script facilitates
# easy installation of useful tools and security enhancements, including
# fail2ban, ZFS auto-snapshot, and more.
# Interactive post-installation configurator for Proxmox VE.
# Groups ~30 optimizations into 10 categories (Basic Settings,
# System, Virtualization, Network, Storage, Security,
# Customization, Monitoring, Performance, Optional) and presents
# a checklist per category so the user picks exactly what to
# apply. Every change is registered in installed_tools.json for
# later reversal from Uninstall Optimizations.
#
# This script is based on the work of Adrian Jon Kriel from eXtremeSHOK.com,
# and it was originally published as a post-installation script for Proxmox under the
# BSD License.
#
# Copyright (c) Adrian Jon Kriel :: admin@extremeshok.com
# Script updates can be found at: https://github.com/extremeshok/xshok-proxmox
#
# License: BSD (Berkeley Software Distribution)
#
# Additionally, this script incorporates elements from the
# Proxmox VE Post Install script from Proxmox VE Helper-Scripts.
#
# Copyright (c) Proxmox VE Helper-Scripts Community
# Script updates can be found at: https://github.com/community-scripts/ProxmoxVE
#
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
#
# Key features:
# - Configures system memory and kernel settings for better performance.
# - Enables IOMMU and VFIO for PCI passthrough and virtualization optimizations.
# - Installs essential tools such as kernel headers, system utilities, and networking tools.
# - Optimizes journald, achievement, and other system services for better efficiency.
# - Enables guest agents for virtualization platforms such as KVM, VMware, and VirtualBox.
# - Updates the system, adds correct repositories, and optimizes system features such as memory, network settings, and more.
# - Provides a wide range of additional options for customization and optimization.
# - Offers interactive selection of features using an easy-to-use menu-driven interface.
# - And many more...
# Features:
# - Checklist UI per category (10 categories, ~30 tools total).
# - Superset of the Automated script: includes the 13 baseline
# optimizations plus opt-in items (IOMMU/VFIO, Fastfetch,
# Figurine, Ceph repo, HA, AMD fixes, pigz, ZFS ARC, …).
# - Idempotent: safe to run repeatedly.
# - Registration + rollback: every tool has a reverse function
# in uninstall-tools.sh.
#
# Credits:
# Incorporates ideas and snippets originally published under BSD
# by Adrian Jon Kriel (eXtremeSHOK) in xshok-proxmox, and elements
# of the Proxmox VE Post Install script from the Proxmox VE
# Helper-Scripts Community (MIT).
# https://github.com/extremeshok/xshok-proxmox
# https://github.com/community-scripts/ProxmoxVE
# ==========================================================
@@ -78,15 +67,36 @@ SCRIPT_TITLE="Customizable post-installation optimization script"
TOOLS_JSON="/usr/local/share/proxmenux/installed_tools.json"
# Sprint 12A: customizable_post_install.sh always emits source=custom so
# the update detector knows to re-run the customizable flow (which asks
# the user for parameters again) instead of the silent auto flow.
SCRIPT_SOURCE="custom"
ensure_tools_json() {
[ -f "$TOOLS_JSON" ] || echo "{}" > "$TOOLS_JSON"
}
# Sprint 12A: register_tool accepts (key, state, version, source).
# Each function declares `local FUNC_VERSION="X.Y"` on its first line and
# passes "$FUNC_VERSION" here. We use `local` rather than a `# version:`
# comment because bash's `declare -f` strips comments — comments would be
# silently lost when the update wrapper sourced the script and re-ran a
# function, leaving the registered version stuck at the default. See
# auto_post_install.sh for the full contract.
register_tool() {
local tool="$1"
local state="$2"
local state="$2"
local version="${3:-1.0}"
local source="${4:-${SCRIPT_SOURCE:-unknown}}"
ensure_tools_json
jq --arg t "$tool" --argjson v "$state" '.[$t]=$v' "$TOOLS_JSON" > "$TOOLS_JSON.tmp" && mv "$TOOLS_JSON.tmp" "$TOOLS_JSON"
if [[ "$state" == "true" ]]; then
jq --arg t "$tool" --arg ver "$version" --arg src "$source" \
'.[$t]={"installed": true, "version": $ver, "source": $src}' \
"$TOOLS_JSON" > "$TOOLS_JSON.tmp" && mv "$TOOLS_JSON.tmp" "$TOOLS_JSON"
else
jq --arg t "$tool" '.[$t]=false' \
"$TOOLS_JSON" > "$TOOLS_JSON.tmp" && mv "$TOOLS_JSON.tmp" "$TOOLS_JSON"
fi
}
@@ -119,6 +129,8 @@ $(translate "Do you want to continue anyway?")" 13 70
enable_kexec() {
local FUNC_VERSION="1.0"
# description: Install kexec-tools and add a Ctrl+Alt+K hotkey + systemd unit for fast reboots that skip BIOS/POST.
msg_info2 "$(translate "Configuring kexec for quick reboots...")"
NECESSARY_REBOOT=1
@@ -179,7 +191,7 @@ EOF
fi
msg_success "$(translate "kexec configured successfully. Use the command: reboot-quick")"
register_tool "kexec" true
register_tool "kexec" true "$FUNC_VERSION"
}
@@ -221,8 +233,10 @@ apt_upgrade() {
optimize_journald() {
local FUNC_VERSION="1.0"
# description: Cap journald size, raise rate limit and force info-level logging so the log viewer and Fail2Ban work.
msg_info2 "$(translate "Limiting size and optimizing journald")"
NECESSARY_REBOOT=1
NECESSARY_REBOOT=1
local journald_conf="/etc/systemd/journald.conf"
local config_changed=false
@@ -280,7 +294,7 @@ EOF
journalctl --rotate > /dev/null 2>&1
msg_success "$(translate "Journald optimization completed")"
register_tool "journald" true
register_tool "journald" true "$FUNC_VERSION"
}
@@ -299,6 +313,8 @@ EOF
configure_kernel_panic() {
local FUNC_VERSION="1.0"
# description: Auto-reboot on kernel panic / oops / hardlockup; write crash dumps to /var/crash.
msg_info2 "$(translate "Configuring kernel panic behavior")"
NECESSARY_REBOOT=1
@@ -320,7 +336,7 @@ EOF
msg_ok "$(translate "Kernel panic configuration updated and applied")"
register_tool "kernel_panic" true
register_tool "kernel_panic" true "$FUNC_VERSION"
msg_success "$(translate "Kernel panic behavior configuration completed")"
}
@@ -333,6 +349,8 @@ EOF
increase_system_limits() {
local FUNC_VERSION="1.1"
# description: Raise inotify watches, file descriptors, process keys and PID limits to enterprise levels.
msg_info2 "$(translate "Increasing various system limits...")"
NECESSARY_REBOOT=1
@@ -418,7 +436,7 @@ fs.file-max = 2097152
fs.aio-max-nr = 1048576"
msg_ok "$(translate "Max FS open files configuration created successfully")"
register_tool "system_limits" true
register_tool "system_limits" true "$FUNC_VERSION"
msg_success "$(translate "System limits increase completed.")"
}
@@ -431,6 +449,8 @@ fs.aio-max-nr = 1048576"
skip_apt_languages() {
local FUNC_VERSION="1.0"
# description: Stop APT from downloading translation files to speed up updates.
msg_info2 "$(translate "Configuring APT to skip downloading additional languages")"
# 1. Detect locale
@@ -471,7 +491,7 @@ skip_apt_languages() {
msg_ok "$(translate "APT language configuration updated")"
fi
register_tool "apt_languages" true
register_tool "apt_languages" true "$FUNC_VERSION"
msg_success "$(translate "APT configured to skip downloading additional languages")"
}
@@ -489,6 +509,8 @@ skip_apt_languages() {
configure_time_sync() {
local FUNC_VERSION="1.0"
# description: Detect timezone from public IP and enable systemd time sync (NTP).
msg_info2 "$(translate "Configuring system time settings...")"
this_ip=$(dig +short myip.opendns.com @resolver1.opendns.com 2>/dev/null)
@@ -497,20 +519,30 @@ configure_time_sync() {
return 0
fi
timezone=$(curl -s --connect-timeout 10 "https://ipapi.co/${this_ip}/timezone" 2>/dev/null)
timezone=$(curl -s --connect-timeout 10 "https://ipapi.co/${this_ip}/timezone" 2>/dev/null | tr -d '[:space:]')
if [ -z "$timezone" ] || [ "$timezone" = "undefined" ]; then
msg_warn "$(translate "Failed to determine timezone from IP address - keeping current timezone settings")"
return 0
fi
# Validate against the system's IANA timezone database before applying.
# ipapi.co can return rate-limit JSON, an error string, or stale data; the
# previous code accepted anything that wasn't literally "undefined" and
# passed it straight to `timedatectl set-timezone`, which silently kept
# the old TZ on a bad value.
if ! timedatectl list-timezones 2>/dev/null | grep -Fxq "$timezone"; then
msg_warn "$(translate "API returned an invalid timezone") ($timezone) - $(translate "keeping current settings")"
return 0
fi
msg_ok "$(translate "Found timezone $timezone for IP $this_ip")"
if timedatectl set-timezone "$timezone"; then
msg_ok "$(translate "Timezone set to $timezone")"
if timedatectl set-ntp true; then
msg_ok "$(translate "Time settings configured - Timezone:") $timezone"
register_tool "time_sync" true
register_tool "time_sync" true "$FUNC_VERSION"
systemctl restart postfix 2>/dev/null || true
else
@@ -583,6 +615,8 @@ configure_time_sync() {
apply_amd_fixes() {
local FUNC_VERSION="1.0"
# description: Detect AMD EPYC/Ryzen CPUs and apply microcode + IOMMU + KVM-specific kernel boot params.
msg_info2 "$(translate "Detecting AMD CPU and applying fixes if necessary...")"
NECESSARY_REBOOT=1
@@ -672,7 +706,7 @@ apply_amd_fixes() {
fi
msg_success "$(translate "AMD CPU fixes applied successfully")"
register_tool "amd_fixes" true
register_tool "amd_fixes" true "$FUNC_VERSION"
}
@@ -687,6 +721,8 @@ apply_amd_fixes() {
force_apt_ipv4() {
local FUNC_VERSION="1.0"
# description: Force APT to use IPv4 to avoid stalls on hosts with broken IPv6 connectivity.
msg_info2 "$(translate "Configuring APT to use IPv4...")"
local config_file="/etc/apt/apt.conf.d/99-force-ipv4"
@@ -701,7 +737,7 @@ force_apt_ipv4() {
fi
fi
register_tool "apt_ipv4" true
register_tool "apt_ipv4" true "$FUNC_VERSION"
msg_success "$(translate "APT IPv4 configuration completed")"
}
@@ -716,6 +752,8 @@ force_apt_ipv4() {
apply_network_optimizations() {
local FUNC_VERSION="1.0"
# description: Tune TCP buffers, somaxconn, IPv4 hardening and disable rp_filter on fw bridges (PVE 9 compatible).
msg_info "$(translate "Optimizing network settings...")"
NECESSARY_REBOOT=1
@@ -742,6 +780,12 @@ net.ipv4.conf.default.secure_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.default.log_martians = 0
# rp_filter=2 (loose) instead of the kernel default 1 (strict). Loose
# allows asymmetric routing typical of a Proxmox host with VMs on
# multiple bridges — strict mode would drop legitimate VM traffic when
# the reverse path differs. Trade-off: slightly weaker spoofing
# protection from local LAN. Document this choice rather than the
# default.
net.ipv4.conf.all.rp_filter = 2
net.ipv4.conf.default.rp_filter = 2
@@ -750,6 +794,11 @@ net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.icmp_ignore_bogus_error_responses = 1
# TCP/IP
# Wider ephemeral port range than Debian's default 32768-60999 so
# Proxmox hosts handing out NAT/forward ports for many VMs/CTs don't
# run out under load. Privileged-port range (1-1023) is still protected
# by capabilities — the kernel won't actually pick one for an
# unprivileged ephemeral allocation.
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.tcp_mtu_probing = 1
net.ipv4.tcp_rfc1337 = 1
@@ -771,7 +820,7 @@ EOF
fi
msg_ok "$(translate "Network optimization completed")"
register_tool "network_optimization" true
register_tool "network_optimization" true "$FUNC_VERSION"
}
@@ -786,6 +835,8 @@ EOF
install_openvswitch() {
local FUNC_VERSION="1.0"
# description: Install OpenVSwitch for software-defined networking inside VMs and containers.
msg_info2 "$(translate "Installing OpenVSwitch for virtual internal network...")"
@@ -813,6 +864,7 @@ install_openvswitch() {
# Verify installation
if command -v ovs-vsctl >/dev/null 2>&1; then
msg_success "$(translate "OpenVSwitch is ready to use")"
register_tool "openvswitch" true "$FUNC_VERSION"
else
msg_warn "$(translate "OpenVSwitch installation could not be verified")"
fi
@@ -829,6 +881,8 @@ install_openvswitch() {
enable_tcp_fast_open() {
local FUNC_VERSION="1.0"
# description: Enable TCP Fast Open (clients + server) and BBR congestion control for better latency under load.
msg_info2 "$(translate "Configuring TCP optimizations...")"
local bbr_conf="/etc/sysctl.d/99-kernel-bbr.conf"
@@ -869,6 +923,7 @@ EOF
fi
msg_success "$(translate "TCP optimizations configuration completed")"
register_tool "tcp_optimizations" true "$FUNC_VERSION"
}
@@ -883,6 +938,8 @@ EOF
install_ceph() {
local FUNC_VERSION="1.0"
# description: Install Ceph (client + server packages) for distributed RBD/CephFS storage; PVE 8/9 aware repo selection.
msg_info2 "$(translate "Installing Ceph support...")"
@@ -1043,8 +1100,11 @@ EOF
msg_info2 "$(translate "You may need to run 'pveceph install' manually")"
msg_success "$(translate "Ceph installation process finished with warnings")"
fi
# Track install in the registry so the Uninstall menu can offer
# `apt purge ceph-*` + repo removal. Audit Tier 6 — `install_ceph` /
# `enable_ha` sin `register_tool` ni uninstall.
register_tool "ceph" true "$FUNC_VERSION"
}
@@ -1060,6 +1120,8 @@ EOF
optimize_zfs_arc() {
local FUNC_VERSION="1.0"
# description: Cap ZFS ARC to a sensible fraction of host RAM so VMs don't fight the kernel for memory.
msg_info2 "$(translate "Optimizing ZFS ARC size according to available memory...")"
# Check if ZFS is installed
@@ -1139,6 +1201,7 @@ EOF
fi
msg_success "$(translate "ZFS ARC optimization completed")"
register_tool "zfs_arc" true "$FUNC_VERSION"
}
@@ -1151,6 +1214,8 @@ EOF
install_zfs_auto_snapshot() {
local FUNC_VERSION="1.0"
# description: Install zfs-auto-snapshot with cron schedules for hourly/daily/weekly/monthly snapshots.
msg_info2 "$(translate "Installing and configuring ZFS auto-snapshot...")"
# Check if zfs-auto-snapshot is already installed
@@ -1171,6 +1236,7 @@ install_zfs_auto_snapshot() {
config_zfs_auto_snapshot
msg_success "$(translate "ZFS auto-snapshot installation and configuration completed")"
register_tool "zfs_auto_snapshot" true "$FUNC_VERSION"
}
config_zfs_auto_snapshot() {
@@ -1238,6 +1304,8 @@ disable_rpc() {
configure_pigz() {
local FUNC_VERSION="1.0"
# description: Replace gzip with pigz (parallel implementation) for faster vzdump backup compression.
msg_info2 "$(translate "Configuring pigz as a faster replacement for gzip...")"
# Enable pigz in vzdump configuration
@@ -1295,6 +1363,7 @@ EOF
fi
msg_success "$(translate "pigz configuration completed")"
register_tool "pigz" true "$FUNC_VERSION"
}
@@ -1339,6 +1408,8 @@ EOF
install_guest_agent() {
local FUNC_VERSION="1.0"
# description: Detect the host's hypervisor (qemu/vmware/hyperv/virtualbox) and install the matching guest agent.
msg_info2 "$(translate "Detecting virtualization and installing guest agent...")"
NECESSARY_REBOOT=1
@@ -1366,6 +1437,11 @@ install_guest_agent() {
msg_info "$(translate "Installing $guest_agent for $virt_env...")"
if /usr/bin/env DEBIAN_FRONTEND=noninteractive apt-get -y -o Dpkg::Options::='--force-confdef' install $guest_agent > /dev/null 2>&1; then
msg_ok "$(translate "$guest_agent installed successfully")"
# Persist which package was installed so the uninstaller knows
# what to apt purge later (different per hypervisor).
mkdir -p /usr/local/share/proxmenux 2>/dev/null
echo "$guest_agent" > /usr/local/share/proxmenux/guest_agent.pkg
register_tool "guest_agent" true "$FUNC_VERSION"
else
msg_error "$(translate "Failed to install $guest_agent")"
fi
@@ -1398,6 +1474,8 @@ install_guest_agent() {
enable_vfio_iommu() {
local FUNC_VERSION="1.0"
# description: Enable IOMMU and load VFIO modules to allow GPU/PCI passthrough into VMs.
msg_info2 "$(translate "Enabling IOMMU and configuring VFIO for PCI passthrough...")"
NECESSARY_REBOOT=1
@@ -1553,7 +1631,7 @@ enable_vfio_iommu() {
fi
msg_success "$(translate "IOMMU and VFIO setup completed")"
register_tool "vfio_iommu" true
register_tool "vfio_iommu" true "$FUNC_VERSION"
}
@@ -1570,6 +1648,8 @@ enable_vfio_iommu() {
customize_bashrc() {
local FUNC_VERSION="1.0"
# description: Inject the ProxMenux core bashrc block (aliases, prompt, history) into root's .bashrc, idempotent via begin/end markers.
msg_info2 "$(translate "Customizing bashrc for root user...")"
msg_info "$(translate "Customizing bashrc for root user...")"
@@ -1609,7 +1689,7 @@ EOF
fi
msg_ok "$(translate "Bashrc customization completed")"
register_tool "bashrc_custom" true
register_tool "bashrc_custom" true "$FUNC_VERSION"
}
@@ -1667,36 +1747,34 @@ setup_motd() {
optimize_logrotate() {
msg_info2 "$(translate "Optimizing logrotate configuration...")"
local FUNC_VERSION="1.1"
# description: Replace logrotate.conf with a Log2RAM-friendly profile (daily rotation, copytruncate).
msg_info2 "$(translate "Optimizing logrotate configuration...")"
local logrotate_conf="/etc/logrotate.conf"
local backup_conf="${logrotate_conf}.bak"
cp -n "$logrotate_conf" "$backup_conf" 2>/dev/null || true
if grep -q "# ProxMenux optimized configuration" "$logrotate_conf"; then
msg_ok "$(translate "Logrotate configuration already optimized.")"
else
cp "$logrotate_conf" "$backup_conf"
msg_info "$(translate "Applying optimized logrotate configuration...")"
cat <<EOF > "$logrotate_conf"
# ProxMenux optimized configuration
msg_info "$(translate "Applying optimized logrotate configuration...")"
cat <<EOF > "$logrotate_conf"
# ProxMenux optimized configuration (Log2RAM-friendly)
daily
su root adm
rotate 7
create
compress
size 10M
compress
delaycompress
missingok
notifempty
create 0640 root adm
copytruncate
include /etc/logrotate.d
EOF
systemctl restart logrotate > /dev/null 2>&1
msg_ok "$(translate "Logrotate service restarted successfully")"
fi
register_tool "logrotate" true
register_tool "logrotate" true "$FUNC_VERSION"
msg_success "$(translate "Logrotate optimization completed")"
}
@@ -1711,6 +1789,8 @@ EOF
remove_subscription_banner() {
local FUNC_VERSION="1.0"
# description: Patch the Proxmox web UI to suppress the "no valid subscription" dialog (PVE 8 + 9 variants supported).
local pve_version
pve_version=$(pveversion 2>/dev/null | grep -oP 'pve-manager/\K[0-9]+' | head -1)
@@ -1726,7 +1806,7 @@ remove_subscription_banner() {
bash "$LOCAL_SCRIPTS/global/remove-banner-pve8.sh"
fi
register_tool "subscription_banner" true
register_tool "subscription_banner" true "$FUNC_VERSION"
}
@@ -1740,6 +1820,8 @@ remove_subscription_banner() {
optimize_memory_settings() {
local FUNC_VERSION="1.1"
# description: Tune swappiness, dirty page ratios, overcommit and compaction proactiveness for VM hosts.
msg_info2 "$(translate "Optimizing memory settings...")"
NECESSARY_REBOOT=1
@@ -1777,7 +1859,7 @@ EOF
msg_ok "$(translate "Memory settings optimized successfully")"
msg_success "$(translate "Memory optimization completed.")"
register_tool "memory_settings" true
register_tool "memory_settings" true "$FUNC_VERSION"
}
@@ -1791,10 +1873,19 @@ EOF
optimize_vzdump() {
local FUNC_VERSION="1.0"
# description: Lift vzdump bandwidth/IO limits so backups run at the storage's real throughput.
msg_info2 "$(translate "Optimizing vzdump backup speed...")"
local vzdump_conf="/etc/vzdump.conf"
# Backup the current config so the uninstall path can restore the
# user's original values. The previous code edited in-place with no
# backup; users with custom bwlimit/ionice lost them silently.
if [[ -f "$vzdump_conf" && ! -f "${vzdump_conf}.bak" ]]; then
cp -p "$vzdump_conf" "${vzdump_conf}.bak"
fi
# Configure bandwidth limit
msg_info "$(translate "Configuring bandwidth limit for vzdump...")"
if ! grep -q "^bwlimit: 0" "$vzdump_conf"; then
@@ -1812,6 +1903,7 @@ optimize_vzdump() {
msg_ok "$(translate "I/O priority configured")"
msg_success "$(translate "vzdump backup speed optimization completed")"
register_tool "vzdump_speed" true "$FUNC_VERSION"
}
@@ -1825,12 +1917,17 @@ optimize_vzdump() {
install_ovh_rtm() {
local FUNC_VERSION="1.0"
# description: Detect OVH-rented hardware via whois lookup and install OVH Real-Time Monitoring (no-op on non-OVH).
msg_info2 "$(translate "Detecting if this is an OVH server and installing OVH RTM if necessary...")"
# Get the public IP and check if it belongs to OVH
msg_info "$(translate "Checking if the server belongs to OVH...")"
public_ip=$(curl -s ipinfo.io/ip)
is_ovh=$(whois -h v4.whois.cymru.com " -t $public_ip" | tail -n 1 | cut -d'|' -f3 | grep -i "ovh")
# `--` ends whois client option parsing so "-t IP" reaches the cymru server
# as the query string. Previous form had a leading space inside the quotes
# ("\" -t IP\"") that mangled the query and caused detection to never match.
is_ovh=$(whois -h v4.whois.cymru.com -- "-t $public_ip" | tail -n 1 | cut -d'|' -f3 | grep -i "ovh")
if [ -n "$is_ovh" ]; then
msg_ok "$(translate "OVH server detected")"
@@ -1838,11 +1935,13 @@ install_ovh_rtm() {
msg_info "$(translate "Installing OVH RTM (Real Time Monitoring)...")"
if wget -qO - https://last-public-ovh-infra-yak.snap.mirrors.ovh.net/yak/archives/apply.sh | OVH_PUPPET_MANIFEST=distribyak/catalog/master/puppet/manifests/common/rtmv2.pp bash > /dev/null 2>&1; then
msg_ok "$(translate "OVH RTM installed successfully")"
register_tool "ovh_rtm" true "$FUNC_VERSION"
else
msg_error "$(translate "Failed to install OVH RTM")"
fi
else
msg_ok "$(translate "Not an OVH server, skipping RTM installation")"
fi
msg_ok "$(translate "Server belongs to OVH")"
msg_success "$(translate "OVH server detection and RTM installation process completed")"
}
@@ -1854,6 +1953,8 @@ install_ovh_rtm() {
enable_ha() {
local FUNC_VERSION="1.0"
# description: Enable the Proxmox HA stack (pve-ha-lrm, pve-ha-crm, corosync) for cluster failover.
msg_info2 "$(translate "Enabling High Availability (HA) services...")"
NECESSARY_REBOOT=1
@@ -1865,7 +1966,7 @@ enable_ha() {
msg_ok "$(translate "High Availability services have been enabled successfully")"
msg_success "$(translate "High Availability setup completed")"
register_tool "ha" true "$FUNC_VERSION"
}
@@ -1879,6 +1980,8 @@ enable_ha() {
configure_fastfetch() {
local FUNC_VERSION="1.0"
# description: Install Fastfetch system summary tool with the ProxMenux logo + status block as the SSH login banner.
msg_info2 "$(translate "Installing and configuring Fastfetch...")"
@@ -1900,8 +2003,17 @@ configure_fastfetch() {
msg_info "$(translate "Downloading the latest Fastfetch release...")"
local fastfetch_deb_url=$(curl -s https://api.github.com/repos/fastfetch-cli/fastfetch/releases/latest |
jq -r '.assets[] | select(.name | test("fastfetch-linux-amd64.deb")) | .browser_download_url')
# `--connect-timeout`/`--max-time` so a slow GitHub API call doesn't
# hang the menu indefinitely. `FASTFETCH_PIN_TAG` env var lets the
# caller pin to a known release if upstream introduces a breaking
# change. Audit Tier 6 — recursos remotos sin pinning de versión.
local fastfetch_deb_url=""
if [[ -n "${FASTFETCH_PIN_TAG:-}" ]]; then
fastfetch_deb_url="https://github.com/fastfetch-cli/fastfetch/releases/download/${FASTFETCH_PIN_TAG}/fastfetch-linux-amd64.deb"
else
fastfetch_deb_url=$(curl -s --connect-timeout 5 --max-time 15 https://api.github.com/repos/fastfetch-cli/fastfetch/releases/latest |
jq -r '.assets[] | select(.name | test("fastfetch-linux-amd64.deb")) | .browser_download_url')
fi
if [[ -z "$fastfetch_deb_url" ]]; then
msg_error "$(translate "Failed to retrieve Fastfetch download URL.")"
@@ -2070,7 +2182,7 @@ fi
msg_ok "$(translate "Fastfetch will start automatically in the console")"
msg_success "$(translate "Fastfetch installation and configuration completed")"
register_tool "fastfetch" true
register_tool "fastfetch" true "$FUNC_VERSION"
}
@@ -2102,8 +2214,13 @@ register_tool "fastfetch" true
configure_figurine() {
local FUNC_VERSION="1.0"
# description: Install Figurine (ASCII-art hostname banner) and wire it into the SSH login flow.
msg_info2 "$(translate "Installing and configuring Figurine...")"
local version="1.3.0"
# `FIGURINE_VERSION` env var allows pinning to a specific release;
# default tracks the last tested upstream tag. Audit Tier 6 —
# recursos remotos sin pinning de versión.
local version="${FIGURINE_VERSION:-1.3.0}"
local file="figurine_linux_amd64_v${version}.tar.gz"
local url="https://github.com/arsham/figurine/releases/download/v${version}/${file}"
local temp_dir; temp_dir=$(mktemp -d)
@@ -2190,7 +2307,7 @@ EOF
msg_ok "$(translate "Aliases added to .bashrc")"
msg_success "$(translate "Figurine installation and configuration completed successfully.")"
register_tool "figurine" true
register_tool "figurine" true "$FUNC_VERSION"
}
@@ -2233,6 +2350,8 @@ update_pve_appliance_manager() {
configure_log2ram() {
local FUNC_VERSION="1.1"
# description: Install Log2RAM with user-chosen RAM size; prompts for size and SSD/M.2 awareness before applying.
msg_info2 "$(translate "Preparing Log2RAM configuration")"
sleep 1
@@ -2311,7 +2430,14 @@ configure_log2ram() {
fi
rm -rf /tmp/log2ram 2>/dev/null || true
if ! git clone https://github.com/azlux/log2ram.git /tmp/log2ram >/dev/null 2>>/tmp/log2ram_install.log; then
# Pin to a tested release — `master` could ship breaking changes
# without notice. `LOG2RAM_TAG` env var lets the caller upgrade.
local LOG2RAM_TAG="${LOG2RAM_TAG:-1.7.0}"
if ! git clone --depth 1 --branch "$LOG2RAM_TAG" \
https://github.com/azlux/log2ram.git /tmp/log2ram \
>/dev/null 2>>/tmp/log2ram_install.log \
&& ! git clone --depth 1 https://github.com/azlux/log2ram.git /tmp/log2ram \
>/dev/null 2>>/tmp/log2ram_install.log; then
msg_error "$(translate "Failed to clone log2ram repository. Check /tmp/log2ram_install.log")"
return 1
fi
@@ -2452,7 +2578,7 @@ EOF
systemctl restart rsyslog >/dev/null 2>&1 || true
msg_success "$(translate "Log2RAM installation and configuration completed successfully.")"
register_tool "log2ram" true
register_tool "log2ram" true "$FUNC_VERSION"
}
@@ -2470,6 +2596,8 @@ EOF
setup_persistent_network() {
local FUNC_VERSION="1.0"
# description: Pin NIC names to MAC addresses via systemd .link files so kernel updates don't shuffle interface names.
local LINK_DIR="/etc/systemd/network"
local BACKUP_DIR="/etc/systemd/network/backup-$(date +%Y%m%d-%H%M%S)"
local pve_version
@@ -2478,8 +2606,20 @@ setup_persistent_network() {
msg_info "$(translate "Setting up persistent network interfaces")"
sleep 2
# Detect legacy `/etc/network/interfaces` setups that depend on the
# default udev naming. If the file references `allow-hotplug` rules
# or uses physical interface names directly, the .link rules below
# could rename interfaces and break network on reboot. Warn loudly so
# the user can review before continuing. Audit Tier 6 —
# `setup_persistent_network` no detecta conflicto con legacy.
if [[ -f /etc/network/interfaces ]]; then
if grep -qE '^[[:space:]]*allow-hotplug[[:space:]]' /etc/network/interfaces 2>/dev/null; then
msg_warn "$(translate '/etc/network/interfaces uses allow-hotplug. Renaming interfaces via systemd .link can break that flow — review the file after reboot.')"
fi
fi
mkdir -p "$LINK_DIR"
if ls "$LINK_DIR"/*.link >/dev/null 2>&1; then
mkdir -p "$BACKUP_DIR"
@@ -2523,7 +2663,7 @@ EOF
msg_warn "$(translate "No physical interfaces found")"
fi
msg_success "$(translate "Setting up persistent network interfaces successfully.")"
register_tool "persistent_network" true
register_tool "persistent_network" true "$FUNC_VERSION"
NECESSARY_REBOOT=1
}
@@ -2866,5 +3006,11 @@ done
check_extremeshok_warning
main_menu
# Sprint 12B: only run the interactive menu when this script is invoked
# directly. When sourced from another script (e.g. the post-install
# update wrapper that re-runs a single function), don't trigger the
# extremeshok warning or the main menu.
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
check_extremeshok_warning
main_menu
fi
+143 -10
View File
@@ -1,22 +1,27 @@
#!/bin/bash
# ==========================================================
# ProxMenux - Complete Uninstall Optimizations Script
# ProxMenux - Uninstall Optimizations
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : (GPL-3.0) (https://github.com/MacRimi/ProxMenux/blob/main/LICENSE)
# License : GPL-3.0
# https://github.com/MacRimi/ProxMenux/blob/main/LICENSE
# Version : 1.0
# Last Updated: 06/07/2025
# ==========================================================
# Description:
# This script provides a complete uninstallation and rollback system
# for all post-installation optimizations applied by ProxMenux.
# Reverses post-install optimizations previously applied by
# ProxMenux. Reads the installed_tools.json registry to detect
# which tools were applied, exposes them in a checklist, and
# runs their dedicated uninstall function — restoring original
# configs from their .bak backups where applicable.
#
# It allows administrators to safely revert any changes made during the
# optimization process, restoring the system to its original state.
#
# This ensures full control over system configurations and gives users
# the confidence to apply, test, and undo ProxMenux enhancements as needed.
# Features:
# - Registry-driven: only shows tools currently applied.
# - Per-tool reverse functions (one for each entry in the
# auto / customizable scripts).
# - Restores /etc configs from .bak backups when they exist.
# - Reboot prompt for changes that require it (VFIO, kernel
# cmdline, persistent NIC names, …).
# ==========================================================
@@ -633,6 +638,8 @@ uninstall_vfio_iommu() {
msg_ok "$(translate "IOMMU parameters removed from GRUB")"
fi
fi
msg_info "$(translate 'Updating initramfs (this may take a minute)...')"
update-initramfs -u -k all >/dev/null 2>&1 || true
@@ -804,6 +811,122 @@ migrate_installed_tools() {
fi
}
################################################################
# Sprint 10P — Uninstallers for items previously missing coverage.
# Each `uninstall_*` mirrors its install function in
# `customizable_post_install.sh` and flips `register_tool "X" false`
# at the end so the entry is removed from the active set.
################################################################
uninstall_ceph() {
msg_info2 "$(translate 'Uninstalling Ceph...')"
if dpkg -l 2>/dev/null | grep -qE '^ii\s+ceph'; then
apt-get purge -y 'ceph-*' 'librados*' 'librbd*' 'libcephfs*' 'python3-ceph*' >/dev/null 2>&1 || true
apt-get autoremove -y >/dev/null 2>&1 || true
fi
rm -f /etc/apt/sources.list.d/ceph.list /etc/apt/sources.list.d/ceph.sources 2>/dev/null
rm -f /etc/apt/trusted.gpg.d/ceph.asc /etc/apt/trusted.gpg.d/ceph-release.gpg 2>/dev/null
apt-get update -qq >/dev/null 2>&1 || true
msg_ok "$(translate 'Ceph packages and repository removed')"
register_tool "ceph" false
}
uninstall_ha() {
msg_info2 "$(translate 'Disabling High Availability services...')"
systemctl disable --now pve-ha-lrm pve-ha-crm corosync >/dev/null 2>&1 || true
msg_ok "$(translate 'HA services disabled (configs preserved)')"
register_tool "ha" false
}
uninstall_openvswitch() {
msg_info2 "$(translate 'Removing OpenVSwitch...')"
apt-get purge -y openvswitch-switch openvswitch-common >/dev/null 2>&1 || true
apt-get autoremove -y >/dev/null 2>&1 || true
msg_ok "$(translate 'OpenVSwitch removed')"
register_tool "openvswitch" false
}
uninstall_tcp_optimizations() {
msg_info2 "$(translate 'Reverting TCP BBR + Fast Open...')"
rm -f /etc/sysctl.d/99-kernel-bbr.conf /etc/sysctl.d/99-tcp-fastopen.conf
sysctl --system >/dev/null 2>&1 || true
msg_ok "$(translate 'TCP optimizations reverted (defaults restored on next reboot)')"
register_tool "tcp_optimizations" false
}
uninstall_guest_agent() {
msg_info2 "$(translate 'Removing guest agent...')"
local pkg=""
if [[ -f /usr/local/share/proxmenux/guest_agent.pkg ]]; then
pkg=$(cat /usr/local/share/proxmenux/guest_agent.pkg 2>/dev/null)
fi
if [[ -n "$pkg" ]]; then
apt-get purge -y "$pkg" >/dev/null 2>&1 || true
rm -f /usr/local/share/proxmenux/guest_agent.pkg
msg_ok "$(translate 'Removed:') $pkg"
else
# Fallback: try the typical packages
for p in qemu-guest-agent open-vm-tools virtualbox-guest-utils; do
dpkg -s "$p" >/dev/null 2>&1 && apt-get purge -y "$p" >/dev/null 2>&1
done
msg_ok "$(translate 'Guest agent packages removed')"
fi
register_tool "guest_agent" false
}
uninstall_ovh_rtm() {
msg_info2 "$(translate 'Removing OVH RTM...')"
# OVH RTM installs `rtm` packages and a puppet config.
apt-get purge -y 'ovh-rtm*' 'rtm' 'rtm-*' >/dev/null 2>&1 || true
rm -rf /etc/rtm 2>/dev/null
msg_ok "$(translate 'OVH RTM removed (Puppet artefacts may need manual cleanup)')"
register_tool "ovh_rtm" false
}
uninstall_pigz() {
msg_info2 "$(translate 'Reverting pigz wrapper...')"
if [[ -f /bin/gzip.original ]]; then
mv -f /bin/gzip.original /bin/gzip
msg_ok "$(translate 'Restored original /bin/gzip')"
fi
rm -f /bin/pigzwrapper
sed -i 's/^pigz: 1/#pigz: 1/' /etc/vzdump.conf 2>/dev/null || true
apt-get purge -y pigz >/dev/null 2>&1 || true
msg_ok "$(translate 'pigz removed')"
register_tool "pigz" false
}
uninstall_zfs_arc() {
msg_info2 "$(translate 'Reverting ZFS ARC tuning...')"
if [[ -f /etc/modprobe.d/99-zfsarc.conf.bak ]]; then
mv -f /etc/modprobe.d/99-zfsarc.conf.bak /etc/modprobe.d/99-zfsarc.conf
msg_ok "$(translate 'Original ZFS ARC config restored from .bak')"
else
rm -f /etc/modprobe.d/99-zfsarc.conf
msg_ok "$(translate 'ZFS ARC config removed (kernel defaults will apply on reboot)')"
fi
register_tool "zfs_arc" false
}
uninstall_zfs_auto_snapshot() {
msg_info2 "$(translate 'Removing zfs-auto-snapshot...')"
apt-get purge -y zfs-auto-snapshot >/dev/null 2>&1 || true
msg_ok "$(translate 'zfs-auto-snapshot removed (existing snapshots preserved on the pool)')"
register_tool "zfs_auto_snapshot" false
}
uninstall_vzdump_speed() {
msg_info2 "$(translate 'Reverting vzdump speed tuning...')"
if [[ -f /etc/vzdump.conf.bak ]]; then
mv -f /etc/vzdump.conf.bak /etc/vzdump.conf
msg_ok "$(translate 'Restored original /etc/vzdump.conf from .bak')"
else
sed -i '/^bwlimit: 0$/d;/^ionice: 5$/d' /etc/vzdump.conf 2>/dev/null
msg_ok "$(translate 'Removed bwlimit/ionice tuning (no .bak found)')"
fi
register_tool "vzdump_speed" false
}
################################################################
show_uninstall_menu() {
@@ -843,6 +966,16 @@ show_uninstall_menu() {
amd_fixes) desc="AMD CPU (Ryzen/EPYC) fixes";;
vfio_iommu) desc="IOMMU/VFIO PCI Passthrough";;
persistent_network) desc="Setting persistent network interfaces";;
ceph) desc="Ceph (squid) packages + repo";;
ha) desc="High Availability services (corosync/HA)";;
openvswitch) desc="OpenVSwitch";;
tcp_optimizations) desc="TCP BBR + Fast Open";;
guest_agent) desc="Guest agent (qemu/vmware/virtualbox)";;
ovh_rtm) desc="OVH Real-Time Monitoring";;
pigz) desc="pigz (parallel gzip wrapper)";;
zfs_arc) desc="ZFS ARC size tuning";;
zfs_auto_snapshot) desc="zfs-auto-snapshot package";;
vzdump_speed) desc="vzdump bwlimit/ionice tuning";;
*) desc="$tool";;
esac
menu_options+=("$tool" "$desc" "off")
@@ -0,0 +1,175 @@
#!/bin/bash
# ==========================================================
# ProxMenux - Sprint 12B: re-run a single post-install function
# ==========================================================
# Invoked by the Monitor's "Update" buttons (Settings → ProxMenux
# Optimizations) and by the bash menu's update flow. Sources the
# appropriate post_install script and invokes one specific function so
# the user can update a single tool without re-running the whole flow.
#
# Two invocation modes:
#
# SINGLE — set SOURCE_TYPE + FUNCTION_NAME (+ optionally TOOL_KEY):
# SOURCE_TYPE=auto FUNCTION_NAME=install_log2ram_auto
#
# BATCH — set FUNCTIONS_BATCH to a newline-separated list of
# "source:function:tool_key" triples (tool_key optional):
# FUNCTIONS_BATCH="auto:install_log2ram_auto:log2ram
# custom:install_ceph:ceph"
#
# In batch mode the wrapper iterates the list, sourcing each flow once
# and re-using its function definitions. Tools coming from the same
# flow share a single source step so the terminal output stays clean.
# ==========================================================
set -e
LOCAL_SCRIPTS="/usr/local/share/proxmenux/scripts"
BASE_DIR="/usr/local/share/proxmenux"
UTILS_FILE="$BASE_DIR/utils.sh"
if [[ -f "$UTILS_FILE" ]]; then
# shellcheck disable=SC1090
source "$UTILS_FILE"
fi
if command -v load_language >/dev/null 2>&1; then
load_language
fi
if command -v initialize_cache >/dev/null 2>&1; then
initialize_cache
fi
if command -v show_proxmenux_logo >/dev/null 2>&1; then
show_proxmenux_logo
fi
SOURCE_TYPE="${SOURCE_TYPE:-}"
FUNCTION_NAME="${FUNCTION_NAME:-}"
TOOL_KEY="${TOOL_KEY:-${FUNCTION_NAME}}"
FUNCTIONS_BATCH="${FUNCTIONS_BATCH:-}"
# Build the list of (source, function, tool_key) tuples from either the
# single-mode env vars or the batch payload.
declare -a BATCH=()
if [[ -n "$FUNCTIONS_BATCH" ]]; then
while IFS= read -r line; do
[[ -z "$line" ]] && continue
BATCH+=("$line")
done <<< "$FUNCTIONS_BATCH"
elif [[ -n "$SOURCE_TYPE" && -n "$FUNCTION_NAME" ]]; then
BATCH+=("${SOURCE_TYPE}:${FUNCTION_NAME}:${TOOL_KEY}")
else
echo "ERROR: provide either SOURCE_TYPE+FUNCTION_NAME (single mode) or FUNCTIONS_BATCH (batch mode)."
exit 2
fi
# ----------------------------------------------------------------------
# Source the flow scripts on first use. Both auto and customizable
# guard their entry point with `if [[ "${BASH_SOURCE[0]}" == "${0}" ]]`,
# so sourcing loads function definitions without triggering the
# interactive menu or the extremeshok dialog.
# ----------------------------------------------------------------------
SOURCED_AUTO=0
SOURCED_CUSTOM=0
ensure_flow_loaded() {
local source_type="$1"
case "$source_type" in
auto)
if [[ $SOURCED_AUTO -eq 0 ]]; then
# shellcheck disable=SC1091
source "$LOCAL_SCRIPTS/post_install/auto_post_install.sh"
SOURCED_AUTO=1
fi
;;
custom)
if [[ $SOURCED_CUSTOM -eq 0 ]]; then
# shellcheck disable=SC1091
source "$LOCAL_SCRIPTS/post_install/customizable_post_install.sh"
SOURCED_CUSTOM=1
fi
;;
*)
echo "ERROR: invalid source '$source_type' (must be 'auto' or 'custom')"
return 2
;;
esac
}
# ----------------------------------------------------------------------
# Run each tool. We don't bail on the first failure — the user marked a
# multi-select, they expect every chosen tool to be attempted. RCs are
# collected and the wrapper exits non-zero if any failed.
# ----------------------------------------------------------------------
TOTAL=${#BATCH[@]}
FAILED=0
INDEX=0
for entry in "${BATCH[@]}"; do
INDEX=$((INDEX + 1))
IFS=':' read -r src fn tkey <<< "$entry"
[[ -z "$tkey" ]] && tkey="$fn"
if command -v msg_info2 >/dev/null 2>&1; then
msg_info2 "[$INDEX/$TOTAL] Updating ${tkey} (running ${fn} from ${src} flow)..."
else
echo "[ProxMenux] [$INDEX/$TOTAL] Updating ${tkey} (running ${fn} from ${src} flow)..."
fi
if ! ensure_flow_loaded "$src"; then
FAILED=$((FAILED + 1))
continue
fi
if ! declare -F "$fn" >/dev/null 2>&1; then
if command -v msg_error >/dev/null 2>&1; then
msg_error "Function '$fn' is not defined in the ${src} flow."
else
echo "ERROR: function '$fn' is not defined in the ${src} flow."
fi
FAILED=$((FAILED + 1))
continue
fi
set +e
"$fn"
RC=$?
set -e
if [[ $RC -eq 0 ]]; then
if command -v msg_ok >/dev/null 2>&1; then
msg_ok "Update for ${tkey} completed."
else
echo "[ProxMenux] Update for ${tkey} completed."
fi
else
if command -v msg_error >/dev/null 2>&1; then
msg_error "Update for ${tkey} exited with status $RC."
else
echo "ERROR: update for ${tkey} exited with status $RC."
fi
FAILED=$((FAILED + 1))
fi
done
if [[ $FAILED -eq 0 ]]; then
if command -v msg_success >/dev/null 2>&1; then
msg_success "All $TOTAL update(s) completed successfully."
else
echo "[ProxMenux] All $TOTAL update(s) completed successfully."
fi
else
if command -v msg_warn >/dev/null 2>&1; then
msg_warn "$FAILED of $TOTAL updates failed — see the messages above."
else
echo "WARNING: $FAILED of $TOTAL updates failed."
fi
fi
if command -v msg_success >/dev/null 2>&1; then
msg_success "Press Enter to close this terminal..."
else
echo "Press Enter to close this terminal..."
fi
read -r 2>/dev/null || true
[[ $FAILED -eq 0 ]] && exit 0 || exit 1
-214
View File
@@ -1,214 +0,0 @@
#!/bin/bash
# ==========================================================
# ProxMenux - A menu-driven script for Proxmox VE management
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : (GPL-3.0) (https://github.com/MacRimi/ProxMenux/blob/main/LICENSE)
# Version : 1.0
# Last Updated: 28/01/2025
# ==========================================================
# Description:
# This script allows users to assign physical disks for passthrough to existing
# Proxmox virtual machines (VMs) through an interactive menu.
# - Detects and lists physical and network interfaces.
# - Verifies and repairs bridge configurations.
# - Ensures network connectivity by checking IP assignments.
# - Provides options to manually repair or verify network settings.
# - Offers interactive menus for user-friendly operation.
#
# The script aims to simplify network troubleshooting and ensure
# that Proxmox systems maintain stable connectivity.
# ==========================================================
# Configuration ============================================
LOCAL_SCRIPTS="/usr/local/share/proxmenux/scripts"
BASE_DIR="/usr/local/share/proxmenux"
UTILS_FILE="$BASE_DIR/utils.sh"
VENV_PATH="/opt/googletrans-env"
if [[ -f "$UTILS_FILE" ]]; then
source "$UTILS_FILE"
fi
load_language
initialize_cache
# ==========================================================
# Function to detect physical network interfaces
detect_physical_interfaces() {
physical_interfaces=$(ip -o link show | awk -F': ' '$2 !~ /^(lo|veth|dummy|bond)/ {print $2}')
whiptail --title "$(translate 'Network Interfaces')" --msgbox "$physical_interfaces" 10 78
}
# Function to get all relevant network interfaces (physical and bridges)
get_relevant_interfaces() {
echo $(ip -o link show | awk -F': ' '$2 !~ /^(lo|veth|dummy)/ {print $2}')
}
# Function to check and fix bridge configuration
check_and_fix_bridges() {
local output=""
output+="$(translate 'Checking bridges')\\n\\n"
bridges=$(grep "^auto vmbr" /etc/network/interfaces | awk '{print $2}')
for bridge in $bridges; do
old_port=$(grep -A1 "iface $bridge" /etc/network/interfaces | grep "bridge-ports" | awk '{print $2}')
if ! ip link show "$old_port" &>/dev/null; then
output+="$(translate 'Bridge port missing'): $bridge - $old_port\\n"
new_port=$(echo "$physical_interfaces" | tr ' ' '\n' | grep -v "vmbr" | head -n1)
if [ -n "$new_port" ]; then
sed -i "/iface $bridge/,/bridge-ports/ s/bridge-ports.*/bridge-ports $new_port/" /etc/network/interfaces
output+="$(translate 'Bridge port updated'): $bridge - $old_port -> $new_port\\n"
else
output+="$(translate 'No physical interface available')\\n"
fi
else
output+="$(translate 'Bridge port OK'): $bridge - $old_port\\n"
fi
done
whiptail --title "$(translate 'Checking Bridges')" --msgbox "$output" 20 78
}
clean_nonexistent_interfaces() {
local output=""
output+="$(translate 'Cleaning interfaces')\\n\\n"
configured_interfaces=$(grep "^iface" /etc/network/interfaces | awk '{print $2}' | grep -v "lo")
for iface in $configured_interfaces; do
if [[ ! $iface =~ ^(vmbr|bond) ]] && ! ip link show "$iface" &>/dev/null; then
sed -i "/iface $iface/,/^$/d" /etc/network/interfaces
output+="$(translate 'Interface removed'): $iface\\n"
fi
done
whiptail --title "$(translate 'Cleaning Interfaces')" --msgbox "$output" 15 78
}
# Update other functions to use physical_interfaces or get_relevant_interfaces as appropriate
configure_physical_interfaces() {
local output=""
output+="$(translate 'Configuring interfaces')\\n\\n"
for iface in $physical_interfaces; do
if ! grep -q "iface $iface" /etc/network/interfaces; then
echo -e "\niface $iface inet manual" >> /etc/network/interfaces
output+="$(translate 'Interface added'): $iface\\n"
fi
done
whiptail --title "$(translate 'Configuring Interfaces')" --msgbox "$output" 15 78
}
# Function to restart networking service
restart_networking() {
if (whiptail --title "$(translate 'Restarting Network')" --yesno "$(translate 'Do you want to restart the network service?')" 10 60); then
clear
msg_info "$(translate 'The network service is about to restart. You may experience a brief disconnection.')"
systemctl restart networking
if [ $? -eq 0 ]; then
msg_ok "$(translate 'Network service restarted successfully')"
else
msg_error "$(translate 'Failed to restart network service')"
fi
else
msg_ok "$(translate 'Network restart canceled')"
fi
}
# Function to check network connectivity
check_network_connectivity() {
if ping -c 4 8.8.8.8 &> /dev/null; then
msg_ok "$(translate 'Network connectivity OK')"
return 0
else
msg_error "$(translate 'Network connectivity failed')"
return 1
fi
}
# Update the show_ip_info function to use the new get_relevant_interfaces function
show_ip_info() {
whiptail --title "$(translate 'IP Information')" --infobox "$(translate 'Gathering IP information...')" 8 78
local ip_info=""
ip_info+="$(translate 'IP Information')\\n\\n"
local interfaces=$(get_relevant_interfaces)
for interface in $interfaces; do
local interface_ip=$(ip -4 addr show $interface 2>/dev/null | grep -oP '(?<=inet\s)\d+(\.\d+){3}')
if [ -n "$interface_ip" ]; then
ip_info+="$interface: $interface_ip\\n"
else
ip_info+="$interface: $(translate 'No IP assigned')\\n"
fi
done
whiptail --title "$(translate 'Result')" --msgbox "${ip_info}\\n\\n$(translate 'IP information gathering completed')\\n\\n$(translate 'Press Enter to continue')" 20 78
}
# Function to repair network
repair_network() {
whiptail --title "$(translate 'Network Repair Started')" --infobox "$(translate 'Repairing network...')" 8 78
echo -ne "${TAB}${YW}-$(translate 'Repairing network...') ${CL}"
sleep 3
detect_physical_interfaces
clean_nonexistent_interfaces
check_and_fix_bridges
configure_physical_interfaces
restart_networking
if check_network_connectivity; then
show_ip_info
msg_ok "$(translate 'Network repair completed successfully')"
else
msg_error "$(translate 'Network repair failed')"
fi
whiptail --title "$(translate 'Result')" --msgbox "$(translate 'Repair process completed')\\n\\n$(translate 'Press Enter to continue')" 10 78
}
# Function to verify network configuration
verify_network() {
whiptail --title "$(translate 'Network Verification Started')" --infobox "$(translate 'Verifying network...')" 8 78
echo -ne "${TAB}${YW}-$(translate 'Verifying network...') ${CL}"
detect_physical_interfaces
show_ip_info
if check_network_connectivity; then
msg_ok "$(translate 'Network verification completed successfully')"
else
msg_error "$(translate 'Network verification failed')"
fi
whiptail --title "$(translate 'Result')" --msgbox "$(translate 'Verification process completed')\\n\\n$(translate 'Press Enter to continue')" 10 78
}
# Function to show main menu
show_main_menu() {
while true; do
OPTION=$(whiptail --title "$(translate 'Network Repair Menu')" --menu "$(translate 'Choose an option:')" 15 60 4 \
"1" "$(translate 'Verify Network')" \
"2" "$(translate 'Show IP Information')" \
"3" "$(translate "Return to Main Menu")" 3>&1 1>&2 2>&3)
case $OPTION in
1)
verify_network
;;
2)
show_ip_info
;;
3) exec bash "$LOCAL_SCRIPTS/menus/main_menu.sh" ;;
*) exec bash "$LOCAL_SCRIPTS/menus/main_menu.sh" ;;
esac
done
}
clear
#show_proxmenux_logo
show_main_menu
+30 -3
View File
@@ -1,10 +1,37 @@
#!/bin/bash
# ==========================================================
# ProxMenux - Fail2Ban Installer & Configurator
# ============================================
# ==========================================================
# Author : MacRimi
# License : MIT
# Copyright : (c) 2024 MacRimi
# License : GPL-3.0
# https://github.com/MacRimi/ProxMenux/blob/main/LICENSE
# Version : 1.0
# ============================================
# ==========================================================
# Description:
# Installs and configures Fail2Ban to protect SSH, the Proxmox VE
# web UI (port 8006) and the ProxMenux Monitor (port 8008 + reverse
# proxy) against brute-force attacks. Hybrid runtime: works from
# terminal dialogs and from the ProxMenux web panel.
#
# Features:
# - Adjusts journald MaxLevelStore if Proxmox default ('warning')
# would silently drop SSH/PAM auth events.
# - Creates two journal-to-file logger services so Fail2Ban can use
# the reliable file backend instead of systemd journal (avoids
# known issues with pvedaemon worker / sshd journal reads).
# - Three jails: [sshd] (aggressive, 2 retries / 9h ban),
# [proxmox] (8006, 3 retries / 1h ban), [proxmenux] (8008 +
# http/https, 3 retries / 1h ban).
# - Auto-detects firewall backend (nftables preferred, iptables
# fallback) and sets the matching ban actions.
# - SSH hardening: sets MaxAuthTries=3 (Lynis SSH-7408 recommendation),
# backing up the original value for clean restore on uninstall.
# - Reinstall flow rewrites all jails with current defaults.
# - Clean uninstall: removes jails, logger services, journald drop-in
# and restores the original SSH MaxAuthTries.
# - Component status tracked in components_status.json.
# ==========================================================
# Hybrid script: works from terminal (dialog) and web panel (ScriptTerminalModal)
SCRIPT_TITLE="Fail2Ban Installer for Proxmox VE"
+38 -6
View File
@@ -1,10 +1,35 @@
#!/bin/bash
# ==========================================================
# ProxMenux - Lynis Security Audit Tool Installer
# ============================================
# ==========================================================
# Author : MacRimi
# License : MIT
# Copyright : (c) 2024 MacRimi
# License : GPL-3.0
# https://github.com/MacRimi/ProxMenux/blob/main/LICENSE
# Version : 1.0
# ============================================
# ==========================================================
# Description:
# Installs Lynis (CISOfy) from the official upstream GitHub
# repository so the host always gets the latest scanner, not the
# older Debian-packaged version. Provides install / update / run /
# uninstall actions through a unified menu. Hybrid runtime: works
# from terminal dialogs and from the ProxMenux web panel.
#
# Features:
# - Clones https://github.com/CISOfy/lynis.git into /opt/lynis.
# - Wrapper script at /usr/local/bin/lynis that cd's into /opt/lynis
# before invoking ./lynis (Lynis requires being run from its own
# directory).
# - Detection looks at /usr/local/bin/lynis, /opt/lynis/lynis and
# /usr/bin/lynis (apt install path) before showing the menu.
# - Update action: 'git pull' inside /opt/lynis. Falls back to a
# full reinstall if .git is missing.
# - Run-audit action: launches 'lynis audit system --no-colors'
# directly from the menu.
# - Clean uninstall: removes /opt/lynis and /usr/local/bin/lynis
# (does NOT touch an apt-installed Lynis at /usr/bin/lynis).
# - Component status tracked in components_status.json.
# ==========================================================
# Hybrid script: works from terminal (dialog) and web panel (ScriptTerminalModal)
SCRIPT_TITLE="Lynis Security Audit Tool Installer"
@@ -59,12 +84,19 @@ install_lynis() {
msg_title "$(translate "$SCRIPT_TITLE")"
msg_info2 "$(translate "Installing latest Lynis security scan tool...")"
# Install git if needed
# Install git if needed. Verify the install actually succeeded —
# `apt-get install -y git >/dev/null 2>&1` followed by `msg_ok` would
# otherwise lie about success and the next `git clone` would fail with
# an opaque error. Audit Tier 6 — `lynis_installer.sh` apt silent.
if ! command -v git >/dev/null 2>&1; then
msg_info "$(translate "Installing Git as a prerequisite...")"
apt-get update -qq >/dev/null 2>&1
apt-get install -y git >/dev/null 2>&1
msg_ok "$(translate "Git installed")"
if apt-get install -y git >/dev/null 2>&1 && command -v git >/dev/null 2>&1; then
msg_ok "$(translate "Git installed")"
else
msg_error "$(translate "Could not install Git — Lynis cannot be cloned. Run 'apt-get install git' manually.")"
return 1
fi
fi
# Remove old installation if present
+9 -3
View File
@@ -1,13 +1,19 @@
#!/bin/bash
# ==========================================================
# ProxMenux - A menu-driven script for Proxmox VE management
# ProxMenux - Storage & Share CLI Reference
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : (GPL-3.0) (https://github.com/MacRimi/ProxMenux/blob/main/LICENSE)
# License : GPL-3.0
# https://github.com/MacRimi/ProxMenux/blob/main/LICENSE
# Version : 1.6
# Last Updated: 07/04/2026
# ==========================================================
# Description:
# Reference of the manual CLI commands behind the Storage &
# Share Manager flows (NFS / Samba / iSCSI client and server,
# bind mounts, Proxmox storage registration). Used as the
# Help & Info entry of the Storage & Share menu.
# ==========================================================
# Configuration ============================================
+16 -4
View File
@@ -4,12 +4,24 @@
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : MIT
# License : GPL-3.0
# https://github.com/MacRimi/ProxMenux/blob/main/LICENSE
# Version : 1.0
# ==========================================================
# Description:
# Adds local SCSI/SATA/NVMe disks as Proxmox directory storage
# (pvesm add dir) or ZFS pool storage (pvesm add zfspool).
# The disk can be formatted (ext4/xfs/zfs) and registered in Proxmox.
# Prepares a local SCSI / SATA / NVMe disk on the Proxmox host
# and registers it as Proxmox storage — either as a directory
# (pvesm add dir) or as a ZFS pool (pvesm add zfspool).
#
# Features:
# - Safety filter hides root / swap / mounted / in-use disks
# and disks already referenced by any VM/CT config.
# - Format path: wipe + GPT + mkfs (ext4 / xfs / btrfs / zfs).
# - Reuse path: mount an existing filesystem without touching
# the data.
# - UUID-based /etc/fstab entries with defaults,nofail.
# - Content-type presets (VM Storage / Standard NAS / All / Custom).
# - View, remove (with fstab cleanup) and list-disks helpers.
# ==========================================================
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
-271
View File
@@ -1,271 +0,0 @@
#!/usr/bin/env bash
# ==========================================================
# ProxMenux - Shared Groups Manager
# ==========================================================
# Author : MacRimi
# Description : Manage host groups for shared directories
# ==========================================================
# Configuration
BASE_DIR="/usr/local/share/proxmenux"
UTILS_FILE="$BASE_DIR/utils.sh"
if [[ -f "$UTILS_FILE" ]]; then
source "$UTILS_FILE"
fi
load_language
initialize_cache
pmx_list_groups() {
local groups
groups=$(getent group | awk -F: '$3 >= 1000 && $1 != "nogroup" && $1 !~ /^pve/ {print $1 ":" $3}')
if [[ -z "$groups" ]]; then
whiptail --title "$(translate "Groups")" --msgbox "$(translate "No user groups found.")" 8 60
return
fi
show_proxmenux_logo
msg_title "$(translate "Existing Groups")"
echo "$groups" | column -t -s: | while read -r name gid; do
members=$(getent group "$name" | awk -F: '{print $4}')
echo -e "${BL}$name${CL} (GID: $gid) -> ${YW}${members:-no members}${CL}"
done
echo ""
msg_success "$(translate "Press Enter to continue...")"
read -r
}
pmx_create_group() {
group_name=$(dialog --inputbox "$(translate "Enter new group name:")" 10 60 "sharedfiles-new" \
--title "$(translate "New Group")" 3>&1 1>&2 2>&3) || return
[[ -z "$group_name" ]] && return
if getent group "$group_name" >/dev/null; then
dialog --title "$(translate "Error")" --msgbox "$(translate "Group already exists.")" 8 50
return
fi
if groupadd "$group_name"; then
show_proxmenux_logo
msg_title "$(translate "Create Group")"
msg_ok "$(translate "Group created successfully:") $group_name"
else
show_proxmenux_logo
msg_title "$(translate "Create Group")"
msg_error "$(translate "Failed to create group.")"
fi
echo -e
msg_success "$(translate "Press Enter to continue...")"
read -r
}
pmx_edit_group() {
local groups group_name action
groups=$(getent group | awk -F: '$3 >= 1000 && $1 != "nogroup" && $1 !~ /^pve/ {print $1}')
if [[ -z "$groups" ]]; then
dialog --title "$(translate "Error")" --msgbox "$(translate "No groups available to edit.")" 8 50
return
fi
local menu_options=""
while read -r group; do
if [[ -n "$group" ]]; then
local gid=$(getent group "$group" | cut -d: -f3)
menu_options="$menu_options $group \"GID:$gid\""
fi
done <<< "$groups"
group_name=$(eval "dialog --title \"$(translate "Edit Group")\" --menu \
\"$(translate "Select a group:")\" 20 60 10 \
$menu_options 3>&1 1>&2 2>&3")
if [[ -z "$group_name" ]]; then
return
fi
action=$(dialog --title "$(translate "Edit Group")" --menu \
"$(translate "What do you want to edit in group:") $group_name" 15 60 3 \
"rename" "$(translate "Rename group")" \
"gid" "$(translate "Change GID")" \
"users" "$(translate "Add/Remove users")" 3>&1 1>&2 2>&3)
if [[ -z "$action" ]]; then
return
fi
case "$action" in
rename)
new_name=$(dialog --inputbox "$(translate "Enter new group name:")" 10 60 \
"$group_name" --title "$(translate "Rename Group")" 3>&1 1>&2 2>&3)
if [[ -n "$new_name" && "$new_name" != "$group_name" ]]; then
if groupmod -n "$new_name" "$group_name" 2>/dev/null; then
show_proxmenux_logo
msg_title "$(translate "Rename Group")"
msg_ok "$(translate "Group renamed to:") $new_name"
else
show_proxmenux_logo
msg_title "$(translate "Rename Group")"
msg_error "$(translate "Failed to rename group")"
fi
fi
;;
gid)
current_gid=$(getent group "$group_name" | cut -d: -f3)
new_gid=$(dialog --inputbox "$(translate "Enter new GID:")" 10 60 \
"$current_gid" --title "$(translate "Change GID")" 3>&1 1>&2 2>&3)
if [[ -n "$new_gid" && "$new_gid" != "$current_gid" ]]; then
if groupmod -g "$new_gid" "$group_name" 2>/dev/null; then
show_proxmenux_logo
msg_title "$(translate "Change GID")"
msg_ok "$(translate "GID changed to:") $new_gid"
else
show_proxmenux_logo
msg_title "$(translate "Change GID")"
msg_error "$(translate "Failed to change GID")"
fi
fi
;;
users)
user_action=$(dialog --title "$(translate "User Management")" --menu \
"$(translate "Choose an action for group:") $group_name" 15 60 2 \
"add" "$(translate "Add user to group")" \
"remove" "$(translate "Remove user from group")" 3>&1 1>&2 2>&3)
case "$user_action" in
add)
username=$(dialog --inputbox "$(translate "Enter username to add:")" 10 60 \
--title "$(translate "Add User")" 3>&1 1>&2 2>&3)
if [[ -n "$username" ]]; then
if id "$username" >/dev/null 2>&1; then
if usermod -aG "$group_name" "$username" 2>/dev/null; then
show_proxmenux_logo
msg_title "$(translate "Add User")"
msg_ok "$(translate "User added:") $username"
else
show_proxmenux_logo
msg_title "$(translate "Add User")"
msg_error "$(translate "Failed to add user")"
fi
else
show_proxmenux_logo
msg_title "$(translate "Add User")"
msg_error "$(translate "User does not exist:") $username"
fi
fi
;;
remove)
members=$(getent group "$group_name" | awk -F: '{print $4}' | tr ',' ' ')
if [[ -z "$members" ]]; then
dialog --title "$(translate "Info")" --msgbox "$(translate "No users in this group.")" 8 50
return
fi
local user_options=""
for user in $members; do
user_options="$user_options $user \"\""
done
username=$(eval "dialog --title \"$(translate "Remove User")\" --menu \
\"$(translate "Select user to remove:")\" 15 60 5 \
$user_options 3>&1 1>&2 2>&3")
if [[ -n "$username" ]]; then
if gpasswd -d "$username" "$group_name" 2>/dev/null; then
show_proxmenux_logo
msg_title "$(translate "Remove User")"
msg_ok "$(translate "User removed:") $username"
else
show_proxmenux_logo
msg_title "$(translate "Remove User")"
msg_error "$(translate "Failed to remove user")"
fi
fi
;;
esac
;;
esac
echo -e
msg_success "$(translate "Press Enter to continue...")"
read -r
}
pmx_delete_group() {
local groups group_name menu_options
groups=$(getent group | awk -F: '$3 >= 1000 && $1 != "nogroup" && $1 !~ /^pve/ {print $1}')
if [[ -z "$groups" ]]; then
dialog --title "$(translate "Error")" --msgbox "$(translate "No groups available to delete.")" 8 50
return
fi
menu_options=""
while read -r group; do
if [[ -n "$group" ]]; then
menu_options="$menu_options $group \"\""
fi
done <<< "$groups"
group_name=$(eval "dialog --title \"$(translate "Delete Group")\" --menu \
\"$(translate "Select a group to delete:")\" 20 60 10 \
$menu_options 3>&1 1>&2 2>&3") || return
if dialog --yesno "$(translate "Are you sure you want to delete group:") $group_name ?" 10 60; then
if groupdel "$group_name" 2>/dev/null; then
show_proxmenux_logo
msg_title "$(translate "Deleting Groups")"
msg_ok "$(translate "Group deleted:") $group_name"
else
show_proxmenux_logo
msg_title "$(translate "Deleting Groups")"
msg_ok "$(translate "Group deleted:") $group_name"
msg_error "$(translate "Failed to delete group")"
fi
fi
echo -e
msg_success "$(translate "Press Enter to continue...")"
read -r
}
pmx_manage_groups() {
while true; do
CHOICE=$(dialog --title "$(translate "Shared Groups Manager")" \
--menu "$(translate "Select an option:")" 20 70 10 \
"list" "$(translate "View existing groups")" \
"create" "$(translate "Create new group")" \
"edit" "$(translate "Edit existing group")" \
"delete" "$(translate "Delete a group")" \
"exit" "$(translate "Exit")" \
3>&1 1>&2 2>&3) || return 0
case "$CHOICE" in
list) pmx_list_groups ;;
create) pmx_create_group ;;
edit) pmx_edit_group ;;
delete) pmx_delete_group ;;
exit) return 0 ;;
esac
done
}
pmx_manage_groups
+14 -4
View File
@@ -4,12 +4,22 @@
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : MIT
# License : GPL-3.0
# https://github.com/MacRimi/ProxMenux/blob/main/LICENSE
# Version : 1.0
# ==========================================================
# Description:
# Adds iSCSI targets as Proxmox storage (pvesm add iscsi).
# Proxmox manages the connection natively via open-iscsi.
# iSCSI storage provides block devices for VM disk images.
# Registers iSCSI targets as Proxmox storage via
# pvesm add iscsi. Proxmox manages the session natively via
# open-iscsi; LUNs appear as raw block devices for VM disks.
#
# Features:
# - Auto-installs open-iscsi + enables iscsid service.
# - sendtargets discovery against a portal (IP:port).
# - Auto-selects a single target; menu when several.
# - Storage ID derived from the IQN suffix.
# - Content type fixed to 'images' (block storage only).
# - View, remove and connectivity-test for existing storages.
# ==========================================================
LOCAL_SCRIPTS="/usr/local/share/proxmenux/scripts"
+17 -2
View File
@@ -4,9 +4,24 @@
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : MIT
# License : GPL-3.0
# https://github.com/MacRimi/ProxMenux/blob/main/LICENSE
# Version : 1.0
# Last Updated: 08/04/2026
# ==========================================================
# Description:
# Creates a host directory pre-configured for LXC bind mounts.
# Applies a permission profile (1777 + ACLs) that works for
# both privileged and unprivileged containers without UID/GID
# alignment.
#
# Features:
# - Auto-suggests a free name in /mnt (shared, shared2, …).
# - Accepts custom absolute paths outside /mnt.
# - chown root:root + chmod 1777 (sticky + world-rwx).
# - setfacl with default-inheritance ACLs so new files keep
# the permissive profile.
# - Registers the directory in the ProxMenux share map for
# later use by the LXC Mount Manager.
# ==========================================================
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+18 -6
View File
@@ -4,15 +4,27 @@
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : MIT
# License : GPL-3.0
# https://github.com/MacRimi/ProxMenux/blob/main/LICENSE
# Version : 1.0
# ==========================================================
# Description:
# Adds bind mounts from Proxmox host directories into LXC
# containers using pct set -mpX (Proxmox native).
# Bind-mounts a host directory into an LXC container using
# Proxmox's native pct set -mpN syntax. Handles the permission
# quirks of unprivileged containers on the host side — never
# modifies anything inside the container.
#
# SAFE DESIGN: This script NEVER modifies permissions, ownership,
# or ACLs on the host or inside the container. All existing
# configurations are preserved as-is.
# Features:
# - Unified host-directory picker (mounted CIFS/NFS shares,
# fstab-inactive entries, /mnt/* local dirs, /mnt/pve/*
# Proxmox storages, manual entry).
# - Active fix per source type:
# - CIFS → offer remount with uid=0,gid=0,file_mode=0777
# - NFS → offer chmod 1777 + setfacl on the share
# - Local → offer chmod o+rwx + ACL (unprivileged only)
# - Auto-detects privileged vs unprivileged containers.
# - View / remove existing mp* entries.
# - Optional CT restart at end with mount-point smoke test.
# ==========================================================
BASE_DIR="/usr/local/share/proxmenux"
+42 -9
View File
@@ -1,15 +1,23 @@
#!/bin/bash
# ==========================================================
# ProxMenux CT - NFS Client Manager for Proxmox LXC
# ProxMenux - NFS Client Manager for LXC
# ==========================================================
# Based on ProxMenux by MacRimi
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : GPL-3.0
# https://github.com/MacRimi/ProxMenux/blob/main/LICENSE
# Version : 1.0
# ==========================================================
# Description:
# This script allows you to manage NFS client mounts inside Proxmox CTs:
# - Mount NFS shares (temporary and permanent)
# - View current mounts
# - Unmount and remove NFS shares
# - Auto-discover NFS servers
# Manages NFS client mounts from inside a Proxmox LXC container.
# Requires a privileged container (kernel NFS client needs
# capabilities that unprivileged CTs do not expose).
#
# Features:
# - Mount NFS shares (temporary and permanent via /etc/fstab).
# - List current NFS mounts inside the CT.
# - Unmount and remove NFS shares cleanly.
# - Auto-discover NFS servers on the local network.
# ==========================================================
# Configuration
@@ -45,6 +53,17 @@ install_nfs_client() {
show_proxmenux_logo
msg_title "$(translate "Installing NFS Client in LXC")"
# Pre-flight: refuse non-Debian-family CTs. The script targets
# `apt-get` only — Alpine / Rocky / AlmaLinux fail with cryptic
# errors mid-flow. Audit Tier 6 — `nfs_client.sh`/`samba_client.sh`
# asume distro Debian-family sin detección.
if ! pct exec "$CTID" -- bash -c 'command -v apt-get' &>/dev/null; then
msg_error "$(translate "This container does not have apt-get. NFS client installation only supports Debian/Ubuntu containers.")"
msg_success "$(translate "Press Enter to return to menu...")"
read -r
return 1
fi
msg_info "$(translate "Installing NFS client packages...")"
if ! pct exec "$CTID" -- apt-get update >/dev/null 2>&1; then
msg_error "$(translate "Failed to update package list.")"
@@ -551,9 +570,23 @@ unmount_nfs_share() {
# Remove from fstab
pct exec "$CTID" -- sed -i "\|[[:space:]]$SELECTED_MOUNT[[:space:]]|d" /etc/fstab
msg_ok "$(translate "Removed from /etc/fstab.")"
# Actually unmount it now (the previous version only edited fstab,
# so the share remained mounted until the CT rebooted). Try a
# graceful umount first, fall back to lazy umount if busy. Audit
# Tier 7 — `unmount_nfs_share` only borra fstab.
if pct exec "$CTID" -- mountpoint -q "$SELECTED_MOUNT" 2>/dev/null; then
if pct exec "$CTID" -- umount "$SELECTED_MOUNT" 2>/dev/null; then
msg_ok "$(translate "Unmounted") $SELECTED_MOUNT"
elif pct exec "$CTID" -- umount -l "$SELECTED_MOUNT" 2>/dev/null; then
msg_warn "$(translate "Mount was busy — performed lazy unmount") $SELECTED_MOUNT"
else
msg_warn "$(translate "Could not unmount") $SELECTED_MOUNT $(translate "automatically. Reboot LXC to fully release.")"
fi
fi
echo -e ""
msg_ok "$(translate "NFS share unmount successfully. Reboot LXC required to take effect.")"
msg_ok "$(translate "NFS share unmount completed.")"
fi
echo -e ""
+13 -3
View File
@@ -4,11 +4,21 @@
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : MIT
# License : GPL-3.0
# https://github.com/MacRimi/ProxMenux/blob/main/LICENSE
# Version : 1.0
# ==========================================================
# Description:
# Adds external NFS shares as Proxmox storage (pvesm).
# Proxmox manages the mount natively — no fstab entries needed.
# Registers external NFS exports as Proxmox storage via
# pvesm add nfs. Proxmox manages the mount natively — no
# fstab entries needed on the host.
#
# Features:
# - Auto-discover NFS servers on the local subnet (nmap).
# - Reachability validation chain (ping + nc + showmount).
# - Content-type checklist (import/backup/iso/vztmpl/images/
# rootdir/snippets).
# - View, remove and connectivity-test for existing storages.
# ==========================================================
LOCAL_SCRIPTS="/usr/local/share/proxmenux/scripts"
+63 -40
View File
@@ -1,15 +1,25 @@
#!/bin/bash
# ==========================================================
# ProxMenux CT - NFS Manager for Proxmox LXC (Simple + Universal)
# ProxMenux - NFS Server Manager for LXC
# ==========================================================
# Based on ProxMenux by MacRimi
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : GPL-3.0
# https://github.com/MacRimi/ProxMenux/blob/main/LICENSE
# Version : 1.0
# ==========================================================
# Description:
# This script allows you to manage NFS shares inside Proxmox CTs:
# - Create NFS exports with universal sharedfiles group
# - View configured exports
# - Delete existing exports
# - Check NFS service status
# Manages NFS exports from inside a Proxmox LXC container.
# Requires a privileged container (the kernel NFS server module
# needs capabilities that unprivileged CTs do not expose).
#
# Features:
# - Install and configure nfs-kernel-server inside the CT.
# - Create NFS exports for folders under /mnt.
# - Set up a universal "sharedfiles" group (GID 101000) on the
# CT as a convention for cross-CT file sharing.
# - List configured exports and check service status.
# - Remove exports cleanly.
# ==========================================================
# Configuration
@@ -70,42 +80,55 @@ setup_universal_sharedfiles_group() {
fi
msg_info "$(translate "Creating UID remapping for unprivileged container compatibility...")"
local remapped_count=0
if [[ -n "$lxc_users" ]]; then
while IFS=: read -r username uid; do
if [[ -n "$uid" ]]; then
local remapped_uid=$((uid + 100000))
local remapped_username="remap_${uid}"
if ! pct exec "$ctid" -- id "$remapped_username" >/dev/null 2>&1; then
pct exec "$ctid" -- useradd -u "$remapped_uid" -g sharedfiles -s /bin/false -M "$remapped_username" 2>/dev/null || true
msg_ok "$(translate "Created remapped user") $remapped_username (UID: $remapped_uid)"
((remapped_count++))
else
pct exec "$ctid" -- usermod -g sharedfiles "$remapped_username" 2>/dev/null || true
fi
fi
done <<< "$lxc_users"
# `+ 100000` UID-shift only makes sense in unprivileged containers
# (UID 0 in CT == UID 100000 on host). `select_privileged_lxc` already
# gated the flow to privileged CTs above, so the shift is meaningless
# here and creates phantom `remap_NNNN` accounts that don't map to
# any real UID. Skip the loop in privileged context. Audit Tier 6 —
# UID-shift remapping en CTs privilegiados donde no aplica.
local _is_unpriv=0
if pct config "$ctid" 2>/dev/null | grep -qE '^unprivileged:\s*1'; then
_is_unpriv=1
fi
local remapped_count=0
local common_uids=(33 1000 1001 1002)
for base_uid in "${common_uids[@]}"; do
local remapped_uid=$((base_uid + 100000))
local remapped_username="remap_${base_uid}"
if ! pct exec "$ctid" -- id "$remapped_username" >/dev/null 2>&1; then
pct exec "$ctid" -- useradd -u "$remapped_uid" -g sharedfiles -s /bin/false -M "$remapped_username" 2>/dev/null || true
msg_ok "$(translate "Created common remapped user") $remapped_username (UID: $remapped_uid)"
((remapped_count++))
if (( _is_unpriv == 1 )); then
msg_info "$(translate "Creating UID remapping for unprivileged container compatibility...")"
if [[ -n "$lxc_users" ]]; then
while IFS=: read -r username uid; do
if [[ -n "$uid" ]]; then
local remapped_uid=$((uid + 100000))
local remapped_username="remap_${uid}"
if ! pct exec "$ctid" -- id "$remapped_username" >/dev/null 2>&1; then
pct exec "$ctid" -- useradd -u "$remapped_uid" -g sharedfiles -s /bin/false -M "$remapped_username" 2>/dev/null || true
msg_ok "$(translate "Created remapped user") $remapped_username (UID: $remapped_uid)"
((remapped_count++))
else
pct exec "$ctid" -- usermod -g sharedfiles "$remapped_username" 2>/dev/null || true
fi
fi
done <<< "$lxc_users"
fi
done
msg_ok "$(translate "Universal sharedfiles group configured with") $remapped_count $(translate "remapped users")"
local common_uids=(33 1000 1001 1002)
for base_uid in "${common_uids[@]}"; do
local remapped_uid=$((base_uid + 100000))
local remapped_username="remap_${base_uid}"
if ! pct exec "$ctid" -- id "$remapped_username" >/dev/null 2>&1; then
pct exec "$ctid" -- useradd -u "$remapped_uid" -g sharedfiles -s /bin/false -M "$remapped_username" 2>/dev/null || true
msg_ok "$(translate "Created common remapped user") $remapped_username (UID: $remapped_uid)"
((remapped_count++))
fi
done
msg_ok "$(translate "Universal sharedfiles group configured with") $remapped_count $(translate "remapped users")"
else
msg_ok "$(translate "Privileged container — UID-shift remapping skipped (not applicable)")"
fi
}
+22 -8
View File
@@ -1,16 +1,24 @@
#!/bin/bash
# ==========================================================
# ProxMenux CT - Samba Client Manager for Proxmox LXC
# ProxMenux - Samba / CIFS Client Manager for LXC
# ==========================================================
# Based on ProxMenux by MacRimi
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : GPL-3.0
# https://github.com/MacRimi/ProxMenux/blob/main/LICENSE
# Version : 1.0
# ==========================================================
# Description:
# This script allows you to manage Samba/CIFS client mounts inside Proxmox CTs:
# - Mount Samba/CIFS shares (temporary and permanent)
# - View current mounts
# - Unmount and remove Samba shares
# - Auto-discover Samba servers
# - Manage credentials securely
# Manages Samba / CIFS client mounts from inside a Proxmox LXC
# container. Requires a privileged container (mount.cifs needs
# capabilities that unprivileged CTs do not expose).
#
# Features:
# - Mount CIFS shares (temporary and permanent via /etc/fstab).
# - List current CIFS mounts inside the CT.
# - Unmount and remove shares cleanly.
# - Auto-discover Samba servers on the local network.
# - Credentials stored in /etc/samba/credentials (root:0600).
# ==========================================================
@@ -52,6 +60,12 @@ install_samba_client() {
msg_title "$(translate "Installing Samba Client")"
msg_info "$(translate "Installing Samba/CIFS client packages...")"
# Mirror of nfs_client.sh: refuse non-Debian-family CTs early.
if ! pct exec "$CTID" -- bash -c 'command -v apt-get' &>/dev/null; then
msg_error "$(translate "This container does not have apt-get. Samba client installation only supports Debian/Ubuntu containers.")"
return 1
fi
if ! pct exec "$CTID" -- apt-get update &>/dev/null; then
msg_error "$(translate "Failed to update package list.")"
return 1
+15 -3
View File
@@ -4,11 +4,23 @@
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : MIT
# License : GPL-3.0
# https://github.com/MacRimi/ProxMenux/blob/main/LICENSE
# Version : 1.0
# ==========================================================
# Description:
# Adds external Samba/CIFS shares as Proxmox storage (pvesm).
# Proxmox manages the mount natively — no fstab entries needed.
# Registers external Samba (SMB / CIFS) shares as Proxmox
# storage via pvesm add cifs. Credentials are stored encrypted
# in /etc/pve/priv/storage/<id>.pw — no fstab entries needed.
#
# Features:
# - Auto-discover Samba servers on the local subnet
# (nmap on ports 139/445 + nmblookup for NetBIOS names).
# - Guest or username/password authentication.
# - Share listing via smbclient -L (filtered to Disk shares).
# - Content-type checklist (no rootdir — Proxmox does not
# support LXC rootfs on CIFS).
# - View, remove and connectivity-test for existing storages.
# ==========================================================
LOCAL_SCRIPTS="/usr/local/share/proxmenux/scripts"
+27 -9
View File
@@ -1,15 +1,24 @@
#!/bin/bash
# ==========================================================
# ProxMenux CT - Samba Manager for Proxmox LXC
# ProxMenux - Samba Server Manager for LXC
# ==========================================================
# Based on ProxMenux by MacRimi
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : GPL-3.0
# https://github.com/MacRimi/ProxMenux/blob/main/LICENSE
# Version : 1.0
# ==========================================================
# Description:
# This script allows you to manage Samba shares inside Proxmox CTs:
# - Create shared folders
# - View configured shares
# - Delete existing shares
# - Check Samba service status
# Manages Samba (SMB / CIFS) shares from inside a Proxmox LXC
# container. Requires a privileged container.
#
# Features:
# - Install and configure samba inside the CT.
# - Expose folders under /mnt as Samba shares.
# - Set up a universal "sharedfiles" group (GID 101000) on the
# CT as a convention for cross-CT file sharing.
# - List configured shares and check service status.
# - Remove shares cleanly.
# ==========================================================
# Configuration
@@ -146,7 +155,11 @@ create_share() {
if ! pct exec "$CTID" -- id "$USERNAME" &>/dev/null; then
pct exec "$CTID" -- adduser --disabled-password --gecos "" "$USERNAME"
fi
pct exec "$CTID" -- bash -c "echo -e '$PASSWORD\n$PASSWORD' | smbpasswd -a '$USERNAME'"
# Pipe the password via stdin instead of interpolating into a `bash -c`
# shell string. The previous form broke (and was injectable) when the
# password contained a single quote. `-s` makes smbpasswd read silently
# from stdin and `printf` keeps the bytes literal — no shell expansion.
printf '%s\n%s\n' "$PASSWORD" "$PASSWORD" | pct exec "$CTID" -- smbpasswd -s -a "$USERNAME"
msg_ok "$(translate "Samba server installed successfully.")"
else
@@ -160,7 +173,12 @@ create_share() {
if [[ -n "$IS_MOUNTED" ]]; then
msg_info "$(translate "Detected a mounted directory from host. Setting up shared group...")"
SHARE_GID=999
# Match the GID `nfs_lxc_server.sh` uses (101000) so the same
# `sharedfiles` group bridges Samba- and NFS-served paths. The
# previous `999` was inconsistent — files written via Samba were
# owned by GID 999 and not visible to NFS clients accessing the
# same dataset. Audit Tier 6 — GID inconsistente.
SHARE_GID=101000
GROUP_EXISTS=$(pct exec "$CTID" -- getent group sharedfiles || true)
GID_IN_USE=$(pct exec "$CTID" -- getent group "$SHARE_GID" | cut -d: -f1 || true)
+18 -18
View File
@@ -1,30 +1,26 @@
#!/bin/bash
# ==========================================================
# ProxMenux - A menu-driven script for Proxmox VE management
# ProxMenux - Import Disk to VM (Passthrough)
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : (GPL-3.0) (https://github.com/MacRimi/ProxMenux/blob/main/LICENSE)
# License : GPL-3.0
# https://github.com/MacRimi/ProxMenux/blob/main/LICENSE
# Version : 1.2
# Last Updated: 12/04/2026
# ==========================================================
# Description:
# This script allows users to assign physical disks to existing
# Proxmox virtual machines (VMs) through an interactive menu.
# - Detects the system disk and excludes it from selection.
# - Lists all available VMs for the user to choose from.
# - Identifies and displays unassigned physical disks.
# - Allows the user to select multiple disks and attach them to a VM.
# - Supports interface types: SATA, SCSI, VirtIO, and IDE.
# - Ensures that disks are not already assigned to active VMs.
# - Warns about disk sharing between multiple VMs to avoid data corruption.
# - Configures the selected disks for the VM and verifies the assignment.
# - Prefers persistent /dev/disk/by-id paths for assignment when available.
# Assigns physical disks to existing Proxmox VMs via an
# interactive menu. Uses persistent /dev/disk/by-id paths
# whenever available and blocks system / already-assigned disks.
#
# The goal of this script is to simplify the process of assigning
# physical disks to Proxmox VMs, reducing manual configurations
# and preventing potential errors.
# Features:
# - Detects and excludes the system disk.
# - Lists all VMs for selection.
# - Identifies unassigned physical disks.
# - Supports SATA, SCSI, VirtIO and IDE interfaces.
# - Warns about disk sharing between VMs to avoid corruption.
# - Verifies the assignment after attaching.
# ==========================================================
@@ -426,7 +422,11 @@ for i in "${!DISK_LIST[@]}"; do
IFS=$'\t' read -r _model _size <<< "${DISK_DESCRIPTIONS[$i]}"
INDEX=0
while qm config "$VMID" | grep -q "${INTERFACE}${INDEX}"; do
# Anchor the match: `^scsi1:` vs `^scsi1\d:`. The previous `grep -q
# "scsi1"` matched scsi10/scsi11/... and skipped over a genuinely-free
# scsi1 slot — the disk still got attached but a hole was left mid-
# range. Audit Tier 6 — `disk-passthrough.sh` slot search no anchored.
while qm config "$VMID" | grep -Eq "^${INTERFACE}${INDEX}:"; do
((INDEX++))
done
+13 -11
View File
@@ -1,22 +1,24 @@
#!/bin/bash
# ==========================================================
# ProxMenux - A menu-driven script for Proxmox VE management
# ProxMenux - Import Disk to LXC (Passthrough)
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : (GPL-3.0) (https://github.com/MacRimi/ProxMenux/blob/main/LICENSE)
# License : GPL-3.0
# https://github.com/MacRimi/ProxMenux/blob/main/LICENSE
# Version : 1.3
# Last Updated: 07/04/2026
# ==========================================================
# Description:
# This script allows users to assign physical disks to existing
# Proxmox containers (CTs) through an interactive menu.
# - Detects the system disk and excludes it from selection.
# - Lists all available CTs for the user to choose from.
# - Identifies and displays unassigned physical disks.
# - Allows the user to select multiple disks and attach them to a CT.
# - Configures the selected disks for the CT and verifies the assignment.
# - Uses persistent device paths to avoid issues with device order changes.
# Assigns physical disks to existing Proxmox LXC containers
# via an interactive menu, using persistent device paths to
# avoid issues with device order changes.
#
# Features:
# - Detects and excludes the system disk.
# - Lists all containers for selection.
# - Identifies unassigned physical disks.
# - Configures the selected disks for the CT and verifies
# the assignment.
# ==========================================================
# Configuration ============================================
+22 -3
View File
@@ -714,14 +714,33 @@ main() {
if [[ "$OPERATION_MODE" == "clean_sigs" ]]; then
msg_info "$(translate "Removing filesystem signatures...")"
wipefs -af "$SELECTED_DISK" >/dev/null 2>&1 || true
# `|| true` swallowed real failures (busy device, ENOSPC writing
# the magic bytes) and the user got a green "Signatures removed"
# even when nothing was actually wiped. Capture the failure and
# continue but report it. Audit Tier 6 — `format-disk.sh` wipefs
# `|| true` silencia fallos.
local _wipefs_errs=0
local _wipefs_err_out
if ! _wipefs_err_out=$(wipefs -af "$SELECTED_DISK" 2>&1); then
_wipefs_errs=$((_wipefs_errs + 1))
msg_warn "$(translate "wipefs failed on") $SELECTED_DISK: $_wipefs_err_out"
fi
local pname
while read -r pname; do
[[ -z "$pname" ]] && continue
[[ "/dev/$pname" == "$SELECTED_DISK" ]] && continue
[[ -b "/dev/$pname" ]] && wipefs -af "/dev/$pname" >/dev/null 2>&1 || true
if [[ -b "/dev/$pname" ]]; then
if ! _wipefs_err_out=$(wipefs -af "/dev/$pname" 2>&1); then
_wipefs_errs=$((_wipefs_errs + 1))
msg_warn "$(translate "wipefs failed on") /dev/$pname: $_wipefs_err_out"
fi
fi
done < <(lsblk -ln -o NAME "$SELECTED_DISK" 2>/dev/null | tail -n +2)
msg_ok "$(translate "Signatures removed. Partition table preserved.")"
if (( _wipefs_errs == 0 )); then
msg_ok "$(translate "Signatures removed. Partition table preserved.")"
else
msg_warn "$(translate "Some signatures could not be removed (see warnings above).")"
fi
echo
msg_success "$(translate "Disk is ready for VM passthrough.")"
echo
+17 -8
View File
@@ -1,19 +1,19 @@
#!/bin/bash
# ==========================================================
# ProxMenux - A menu-driven script for Proxmox VE management
# ProxMenux - Import Disk Image to VM
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : (GPL-3.0) (https://github.com/MacRimi/ProxMenux/blob/main/LICENSE)
# License : GPL-3.0
# https://github.com/MacRimi/ProxMenux/blob/main/LICENSE
# Version : 1.3
# Last Updated: 12/04/2026
# ==========================================================
# Description:
# Imports disk images (.img, .qcow2, .vmdk, .raw) into Proxmox VE VMs.
# Supports the default system ISO directory and custom paths.
# All user decisions are collected in Phase 1 (dialogs) before
# any operation is executed in Phase 2 (terminal output).
# Imports disk images (.img, .qcow2, .vmdk, .raw) into
# existing Proxmox VE VMs. Supports the default ISO directory
# and custom paths; all user decisions are collected up-front
# (Phase 1 dialogs) before any operation runs (Phase 2).
# ==========================================================
# Configuration ============================================
@@ -163,7 +163,13 @@ while IFS= read -r img; do
IMAGE_OPTIONS+=("$img" "" "OFF")
done <<< "$IMAGES"
# `--separate-output` prints each selected tag on its own line with no
# quoting, so we never need `eval` to split the output. The previous form
# `eval "declare -a A=($SELECTED)"` would execute backticks / $(...) baked
# into a filename — perfectly legal on ext4 — as shell commands. Audit
# Tier 6 — `import-disk-image.sh` `eval` sobre salida del dialog.
SELECTED_IMAGES_STR=$(dialog --backtitle "$BACKTITLE" \
--separate-output \
--title "$(translate 'Select Disk Images')" \
--checklist "$(translate 'Select one or more disk images to import:')" \
$UI_MENU_H $UI_MENU_W $UI_MENU_LIST_H \
@@ -171,7 +177,10 @@ SELECTED_IMAGES_STR=$(dialog --backtitle "$BACKTITLE" \
2>&1 >/dev/tty)
[[ -z "$SELECTED_IMAGES_STR" ]] && exit 0
eval "declare -a SELECTED_ARRAY=($SELECTED_IMAGES_STR)"
declare -a SELECTED_ARRAY=()
while IFS= read -r _img; do
[[ -n "$_img" ]] && SELECTED_ARRAY+=("$_img")
done <<< "$SELECTED_IMAGES_STR"
# ── Step 5: Per-image options ─────────────────────────────
+4 -2
View File
@@ -416,8 +416,10 @@ while true; do
# ── Auto-export JSON (except long — handled by background monitor)
if [[ "$ACTION" != "long" && "$ACTION" != "report" ]]; then
# Determine test type from ACTION (short test or status check)
local json_test_type="short"
# Determine test type from ACTION (short test or status check).
# NOTE: no 'local' here — this block runs inside the top-level while loop,
# not inside a function, so 'local' would print a bash warning at runtime.
json_test_type="short"
[[ "$ACTION" == "status" ]] && json_test_type="status"
JSON_PATH=$(_smart_json_path "$SELECTED_DISK" "$json_test_type")
+39 -3
View File
@@ -4,9 +4,33 @@
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : (GPL-3.0) (https://github.com/MacRimi/ProxMenux/blob/main/LICENSE)
# License : GPL-3.0
# https://github.com/MacRimi/ProxMenux/blob/main/LICENSE
# Version : 1.0
# Last Updated: 07/04/2026
# ==========================================================
# Description:
# Exports a Proxmox VM to OVA (single TAR archive) or OVF
# (descriptor + VMDK files) using the standard DMTF OVF schema.
# The exported package is portable and importable on VMware
# (ESXi / Workstation / Fusion), VirtualBox and Proxmox itself
# (via the matching import_vm_ova_ovf.sh).
#
# Features:
# - Dependency check (dialog, qm, pvesm, qemu-img, tar, sha1sum).
# - VM picker from 'qm list'; offers graceful shutdown (qm
# shutdown --timeout 120) or force-stop (qm stop) for running
# VMs.
# - Format selector: OVA (single portable file) or OVF
# (descriptor + external VMDK files).
# - Destination directory selector (presets + manual path), with
# write-access and free-space pre-flight (~120% of virtual disk
# for OVF, ~220% for OVA).
# - Disk inventory excludes CD-ROMs and cloud-init drives.
# - Conversion via 'qemu-img convert -O vmdk -o subformat=
# streamOptimized' (single-pass VMware-friendly format).
# - OVF descriptor with vCPU / memory / SCSI controller / disks /
# NIC count, plus SHA1 manifest (.mf) of all files.
# - Temporary working directory cleaned on EXIT via trap.
# ==========================================================
LOCAL_SCRIPTS="/usr/local/share/proxmenux/scripts"
@@ -533,8 +557,20 @@ run_export() {
return 1
fi
# Validate the produced VMDK. `qemu-img check` reports leaks /
# corrupted clusters that the convert exit code might not have
# surfaced (silent partial-write under disk pressure, qemu-img
# bug, etc.). Audit Tier 7 — `export_vm_ova_ovf.sh` no valida
# integridad del VMDK convertido.
if command -v qemu-img >/dev/null 2>&1; then
if ! qemu-img check -q "$dst" 2>/dev/null; then
msg_error "$(translate "Integrity check failed on") $disk_name"
return 1
fi
fi
EXPORT_DISK_FILES+=("$disk_name")
msg_ok "$(translate "Converted:") $disk_name"
msg_ok "$(translate "Converted + verified:") $disk_name"
done
local ovf_file mf_file
+117 -17
View File
@@ -4,33 +4,51 @@
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : (GPL-3.0) (https://github.com/MacRimi/ProxMenux/blob/main/LICENSE)
# License : GPL-3.0
# https://github.com/MacRimi/ProxMenux/blob/main/LICENSE
# Version : 1.0
# Last Updated: 10/04/2026
# ==========================================================
# Description:
# Imports a virtual machine from an OVA or OVF package into Proxmox VE.
# Compatible with exports from VMware ESXi, VMware Workstation/Fusion,
# VirtualBox, and Proxmox itself (via export_vm_ova_ovf).
# Imports a virtual machine from an OVA or OVF package into
# Proxmox VE. Compatible with exports from VMware (ESXi /
# Workstation / Fusion), VirtualBox and Proxmox itself (via the
# matching export_vm_ova_ovf.sh).
#
# What is imported:
# - Disk images (VMDK converted to the target storage format)
# - CPU and memory settings
# - Number of network interfaces
# - VM name and OS type hint
# Features:
# - File picker: scans /var/lib/vz/dump and /var/lib/vz/template/iso
# by default, manual path also supported. Lists every .ova / .ovf.
# - OVA auto-extracted to /tmp/.proxmenux-import-* with cleanup
# trap; OVF used in place.
# - OVF parsed via AWK to extract VM name, vCPU count, memory
# (RASD ResourceType 4), NIC count (type 10) and disk file
# references (.vmdk / .qcow2 / .img / .raw).
# - OS-type heuristic: maps Linux -> l26, Windows -> win10,
# anything else -> other.
# - Dialog flow for VMID (suggests pvesh nextid), name, target
# storage (pvesm status -content images), bridge (auto-picks
# when only one exists).
# - VM created with --scsihw lsi --net0 e1000,bridge=...; extra
# NICs added per OVF NIC count.
# - Disks imported with 'qm importdisk' (storage-native format),
# then attached as scsiN and unusedN markers cleared.
# - Boot config set to scsi0.
#
# What requires manual review after import:
# - Network bridge assignment (vmbr0 assigned by default)
# - NIC model (e1000 by default change to VirtIO if guest supports it)
# - Firmware (BIOS/UEFI — must match what the original VM used)
# - Network bridge assignment (vmbr0 assigned by default).
# - NIC model (e1000 by default -- change to VirtIO if guest
# supports it).
# - Firmware (BIOS / UEFI -- must match the original VM).
# - VirtIO/qemu-guest-agent installation inside the guest (especially from ESXi)
# - PCI passthrough, TPM, cloud-init, snapshots — not portable in OVF/OVA
# ==========================================================
BASE_DIR="/usr/local/share/proxmenux"
LOCAL_SCRIPTS="$BASE_DIR/scripts"
UTILS_FILE="$BASE_DIR/utils.sh"
INSTALL_HELPERS="$LOCAL_SCRIPTS/global/utils-install-functions.sh"
[[ -f "$UTILS_FILE" ]] && source "$UTILS_FILE"
[[ -f "$INSTALL_HELPERS" ]] && source "$INSTALL_HELPERS"
load_language
initialize_cache
@@ -63,6 +81,46 @@ BRIDGE="vmbr0"
# HELPERS
# -------------------------------------------------------
# Ensure GNU awk (gawk) is installed before parsing OVF.
# The OVF parser uses match($0, /regex/, array) — the 3-argument form
# is a gawk extension; mawk (the Debian/Proxmox default 'awk') errors
# with "syntax error at or near ,". Returns 0 on success, 1 if install
# fails (caller is expected to abort with a clear error).
ensure_gawk() {
if command -v gawk >/dev/null 2>&1; then
return 0
fi
echo
if type ensure_repositories &>/dev/null && type install_single_package &>/dev/null; then
# Canonical path: install_single_package handles its own
# msg_info / msg_ok / msg_error pair, so we don't open one here
# (would leave an orphan spinner overlapping with theirs).
if ! ensure_repositories; then
msg_error "$(translate "Failed to configure repositories.")"
return 1
fi
install_single_package "gawk" "gawk" "GNU awk (required for OVF parsing)"
case $? in
0|2) return 0 ;;
*) return 1 ;;
esac
fi
# Fallback when utils-install-functions.sh was not sourced.
# Here we own the spinner: msg_info opens it, msg_ok / msg_error closes it.
msg_info "$(translate "Installing gawk (required for OVF parsing)...")"
if apt-get update -qq >/dev/null 2>&1 && apt-get install -y gawk >/dev/null 2>&1; then
msg_ok "$(translate "gawk installed")"
return 0
fi
msg_error "$(translate "Failed to install gawk")"
msg_warn "$(translate "Install manually with:") apt-get install gawk"
return 1
}
human_bytes() {
local bytes="$1"
local units=("B" "KB" "MB" "GB" "TB")
@@ -194,8 +252,13 @@ prepare_ovf() {
parse_ovf() {
local ovf_file="$1"
# The parser below uses gawk's 3-argument match() form, which is
# NOT supported by mawk (the default 'awk' on Debian/Proxmox).
# ensure_gawk installs gawk on first use if missing.
ensure_gawk || return 1
local result
result=$(awk '
result=$(gawk '
BEGIN {
in_item=0; rt=""; qty=""
file_count=0; cap_count=0; net_count=0
@@ -224,11 +287,29 @@ parse_ovf() {
if (a[1]+0 > 0) caps[cap_count++] = a[1]
}
/<Item>|<Item / { in_item=1; rt=""; qty="" }
/<Item>|<Item / { in_item=1; rt=""; qty=""; au="" }
/<\/Item>/ {
if (in_item) {
if (rt=="3" && qty ~ /^[0-9]+$/) vcpu=qty
if (rt=="4" && qty ~ /^[0-9]+$/) mem=qty
# ResourceType=4 is Memory. Normalise `qty` to MiB based
# on AllocationUnits: VMware sometimes emits `byte`,
# `byte * 2^10` (KiB), `byte * 2^30` (GiB) or textual
# `MegaBytes`/`GigaBytes`. Defaulting to MiB blindly
# (the previous behaviour) imported 8 GB VMs as 8 MiB
# or vice-versa. Audit Tier 6 — OVF memory units.
if (rt=="4" && qty ~ /^[0-9]+$/) {
if (au ~ /byte \* 2\^30/ || au ~ /[Gg]iga[Bb]yte/) {
mem = qty * 1024
} else if (au ~ /byte \* 2\^10/ || au ~ /[Kk]ilo[Bb]yte/) {
mem = int((qty + 1023) / 1024)
} else if (au ~ /byte \* 2\^20/ || au ~ /[Mm]ega[Bb]yte/ || au == "") {
mem = qty
} else if (au == "byte" || au ~ /^bytes?$/) {
mem = int((qty + 1048575) / 1048576)
} else {
mem = qty
}
}
if (rt=="10") net_count++
}
in_item=0
@@ -239,6 +320,9 @@ parse_ovf() {
/VirtualQuantity>/ {
match($0, /VirtualQuantity>([0-9]+)</, a); qty=a[1]
}
/AllocationUnits>/ {
match($0, /AllocationUnits>([^<]+)</, a); au=a[1]
}
END {
gsub(/^[[:space:]]+|[[:space:]]+$/, "", name)
@@ -601,7 +685,23 @@ main() {
else
echo ""
msg_error "$(translate "Import failed. VM $NEW_VMID may be in partial state.")"
msg_info2 "$(translate "To remove partial VM:") qm destroy $NEW_VMID --destroy-unreferenced-disks 1"
# Offer to clean up the orphan VM. Most users want this — it
# otherwise sits in the PVE UI as a half-broken entry that the
# user has to clean up manually with the command we hint at. Audit
# Tier 6 — `import_vm_ova_ovf.sh` VM huérfana tras fallo.
if dialog --backtitle "$BACKTITLE" \
--title "$(translate "Cleanup partial VM?")" \
--yesno "$(translate "Remove the partial VM ($NEW_VMID) and its imported disks?")" 8 60; then
clear
msg_info "$(translate "Removing partial VM") $NEW_VMID..."
if qm destroy "$NEW_VMID" --destroy-unreferenced-disks 1 &>/dev/null; then
msg_ok "$(translate "Partial VM removed")"
else
msg_warn "$(translate "Could not remove VM automatically. Run manually:") qm destroy $NEW_VMID --destroy-unreferenced-disks 1"
fi
else
msg_info2 "$(translate "To remove partial VM:") qm destroy $NEW_VMID --destroy-unreferenced-disks 1"
fi
echo ""
msg_success "$(translate "Press Enter to return...")"
read -r
@@ -1,13 +1,29 @@
#!/bin/bash
# ==========================================================
# ProxMenux - Manual Proxmox VE 8 to 9 Upgrade Guide
# ProxMenux - Manual PVE 8 to 9 Upgrade Guide
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : (GPL-3.0) (https://github.com/MacRimi/ProxMenux/blob/main/LICENSE)
# License : GPL-3.0
# https://github.com/MacRimi/ProxMenux/blob/main/LICENSE
# Version : 1.0
# Last Updated: 13/08/2025
# ==========================================================
# Description:
# Read-only display of a 17-step manual upgrade procedure from
# Proxmox VE 8 to 9. Modifies nothing on the host -- exposes the
# exact commands the automated upgrade runs so an operator can
# perform the upgrade by hand for full visibility, or use it as a
# reference / runbook.
#
# Features:
# - Numbered steps with description + command + recommended
# answers for the dpkg prompts encountered during dist-upgrade.
# - Prerequisite checklist (PVE 8.4+, console access, backups,
# free disk space, ...).
# - Covers Debian bookworm -> trixie sed migration, repository
# deb822 conversion, Ceph 19.x (Squid) requirement and
# cluster-upgrade caveats.
# - Recommends running the upgrade inside tmux / screen.
# ==========================================================
# Configuration ============================================
+35 -19
View File
@@ -1,28 +1,34 @@
#!/bin/bash
# ==========================================================
# ProxMenux - A menu-driven script for Proxmox VE management
# ProxMenux - Proxmox System Update
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : (GPL-3.0) (https://github.com/MacRimi/ProxMenux/blob/main/LICENSE)
# License : GPL-3.0
# https://github.com/MacRimi/ProxMenux/blob/main/LICENSE
# Version : 1.0
# Last Updated: 04/07/2025
# ==========================================================
# Description:
# This script safely updates your Proxmox VE system and underlying Debian packages
# through an interactive and automated process.
# Wrapper that detects the running Proxmox major version and
# delegates to the matching worker script:
# - PVE 8 -> scripts/global/update-pve8.sh
# - PVE 9 -> scripts/global/update-pve9_2.sh
# After the worker finishes, runs the post-update cleanup
# (apt-get autoremove + autoclean) and prompts for an immediate
# reboot if the kernel was updated or /var/run/reboot-required
# was created.
#
# Main features:
# - Repairs and optimizes APT repositories (Proxmox & Debian)
# - Removes duplicate or conflicting sources
# - Switches to the recommended 'no-subscription' Proxmox repository
# - Updates all Proxmox and Debian system packages
# - Installs essential packages if missing (e.g., zfsutils, chrony)
# - Checks for LVM and storage issues and repairs headers if needed
# - Removes conflicting time sync packages automatically
# - Performs a system cleanup after updating (autoremove, autoclean)
# - Provides a summary and prompts for reboot if necessary
# Features (delegated to worker scripts):
# - APT repository hygiene (Proxmox + Debian)
# - Removal of duplicate / conflicting sources
# - Switch to the no-subscription Proxmox repository
# - Full apt update + dist-upgrade
# - Installs essential packages if missing (zfsutils, chrony, ...)
# - LVM / storage sanity checks and header repair
# - Removes conflicting time-sync packages
# - Post-update system cleanup
# - Reboot prompt when kernel changed
# ==========================================================
#
# The goal of this script is to simplify and secure the update process for Proxmox,
# reduce manual intervention, and prevent common repository and package errors.
@@ -46,11 +52,21 @@ export SCRIPT_TITLE="Proxmox system update"
NECESSARY_REBOOT=1
apt_upgrade() {
local pve_version
pve_version=$(pveversion 2>/dev/null | grep -oP 'pve-manager/\K[0-9]+' | head -1)
local pve_version pve_raw
# Capture both stdout and the rc so a failure is visible in the
# error message — silent `2>/dev/null` previously hid the real cause
# (binary missing / output malformed). Audit Tier 6 — `proxmox_update.sh`
# detección de versión silenciosa.
pve_raw=$(pveversion 2>&1)
local pve_rc=$?
pve_version=$(echo "$pve_raw" | grep -oP 'pve-manager/\K[0-9]+' | head -1)
if [[ -z "$pve_version" ]]; then
msg_error "Unable to detect Proxmox version."
if (( pve_rc != 0 )); then
msg_error "Unable to detect Proxmox version (pveversion exit $pve_rc): ${pve_raw:0:200}"
else
msg_error "Unable to parse Proxmox version from output: ${pve_raw:0:200}"
fi
return 1
fi
+43 -5
View File
@@ -1,12 +1,28 @@
#!/bin/bash
# ==========================================================
# ProxMenuX - Upgrade PVE 8 9 (Simplified, per official guide)
# ProxMenux - PVE 8 to 9 Pre-upgrade Check
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : (GPL-3.0) (https://github.com/MacRimi/ProxMenux/blob/main/LICENSE)
# License : GPL-3.0
# https://github.com/MacRimi/ProxMenux/blob/main/LICENSE
# Version : 1.0
# Last Updated: 14/08/2025
# ==========================================================
# Description:
# Runs Proxmox's official 'pve8to9 --full' pre-upgrade check and
# offers guided remediation for the common blocking issues. Stops
# before the actual upgrade -- invoke upgrade_pve8_to_pve9.sh to
# proceed once the check passes cleanly.
#
# Features:
# - Captures full pve8to9 output to /var/log/pve8-a-pve9-<timestamp>.log
# - Counts FAIL / WARN entries and surfaces a summary banner.
# - Detects common failure patterns (systemd-boot meta-package,
# Ceph version, repository conflicts, missing packages, low
# disk space, network restart needed) and proposes the matching
# repair command.
# - Three-way prompt: auto-repair, show manual commands, abort.
# - Re-runs the check after auto-repair to confirm resolution.
# ==========================================================
LOCAL_SCRIPTS="/usr/local/share/proxmenux/scripts"
@@ -21,6 +37,15 @@ fi
load_language
initialize_cache
# Load shared global functions: cleanup_duplicate_repos and ensure_repositories
# are referenced by the auto-repair flow below and live in these files.
if [[ -f "$LOCAL_SCRIPTS/global/common-functions.sh" ]]; then
source "$LOCAL_SCRIPTS/global/common-functions.sh"
fi
if [[ -f "$LOCAL_SCRIPTS/global/utils-install-functions.sh" ]]; then
source "$LOCAL_SCRIPTS/global/utils-install-functions.sh"
fi
# ==========================================================
@@ -39,6 +64,19 @@ fi
run_pve8to9_check2() {
# Bound the auto-repair → re-check recursion. If repairs keep producing
# FAILs (e.g. a missing repo can't be auto-fixed by `ensure_repositories`)
# the user could keep picking "auto-repair" indefinitely and we'd grow
# the bash call stack until it overflows. Cap at 3 attempts. Audit
# Tier 6 — `pve8to9_check.sh` recursión sin guard.
: "${_PVE8TO9_DEPTH:=0}"
_PVE8TO9_DEPTH=$((_PVE8TO9_DEPTH + 1))
if (( _PVE8TO9_DEPTH > 3 )); then
msg_error "$(translate "Maximum auto-repair attempts reached (3). Please review the log and run any remaining commands manually.")"
_PVE8TO9_DEPTH=0
return 1
fi
local tmp
tmp="$(mktemp)"
echo -e
@@ -76,9 +114,9 @@ run_pve8to9_check2() {
# Error 3: Repository configuration issues
if grep -q -E '(repository.*issue|repo.*problem|sources.*error)' "$tmp"; then
repair_commands+=("cleanup_duplicate_repos && configure_repositories")
repair_commands+=("cleanup_duplicate_repos && ensure_repositories")
repair_descriptions+=("$(translate "Fix repository configuration")")
echo -e "${YW}$(translate "Fix repositories:") ${CL}cleanup_duplicate_repos && configure_repositories"
echo -e "${YW}$(translate "Fix repositories:") ${CL}cleanup_duplicate_repos && ensure_repositories"
fi
# Error 4: Package conflicts
+20 -24
View File
@@ -1,36 +1,32 @@
#!/bin/bash
# ==========================================================
# ProxMenux - A menu-driven script for Proxmox VE management
# ProxMenux - System Utilities Installer
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : (GPL-3.0) (https://github.com/MacRimi/ProxMenux/blob/main/LICENSE)
# License : GPL-3.0
# https://github.com/MacRimi/ProxMenux/blob/main/LICENSE
# Version : 1.2
# Last Updated: 03/04/2026
# ==========================================================
# Description:
# This script provides an interactive system utilities installer with a
# comprehensive dialog-based interface for Proxmox VE and Linux systems.
# It simplifies the installation and management of essential command-line
# tools and utilities commonly used in server environments.
#
# The script offers both individual utility selection and predefined groups
# for different use cases, ensuring administrators can quickly set up their
# preferred toolset without manual package management.
#
# Supported utility categories:
# - Basic utilities: grc, htop, tree, curl, wget
# - Development tools: git, vim, nano, dos2unix
# - Compression tools: zip, unzip, rsync, cabextract
# - Network tools: iperf3, nmap, tcpdump, nethogs, iptraf-ng, sshpass
# - Analysis tools: jq, ncdu, iotop, btop, iftop
# - System tools: plocate, net-tools, ipset, msr-tools
# - Virtualization tools: libguestfs-tools, wimtools, genisoimage, chntpw
# - Download tools: axel, aria2
#
# The script automatically handles package name differences across distributions
# and provides detailed feedback on installation success, warnings, and failures.
# Interactive installer for 26 curated CLI utilities packaged in
# the canonical PROXMENUX_UTILS list (defined in
# global/utils-install-functions.sh). Uses the shared
# ensure_repositories() + install_single_package() pair to keep the
# repo configuration and feedback consistent with the rest of the
# project.
#
# Features:
# - Custom selection: dialog checklist of all 26 packages.
# - Install ALL utilities: one-click for all of PROXMENUX_UTILS.
# - Predefined groups (basic / dev / compression / multiplexers /
# analysis / network) for quick targeted installs.
# - Verify installations: checks every PROXMENUX_UTILS command for
# availability and shows an Available / Missing summary.
# - Per-package feedback (install_single_package returns 0 ok / 1
# failed / 2 installed-but-command-not-found-yet).
# - Hash refresh after each install to surface new commands.
# ==========================================================
# Configuration ============================================
LOCAL_SCRIPTS="/usr/local/share/proxmenux/scripts"
+60 -7
View File
@@ -1,12 +1,45 @@
#!/bin/bash
# ==========================================================
# ProxMenuX - Upgrade PVE 8 → 9 (Simplified, per official guide)
# ProxMenux - Upgrade PVE 8 to PVE 9
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : (GPL-3.0) (https://github.com/MacRimi/ProxMenux/blob/main/LICENSE)
# License : GPL-3.0
# https://github.com/MacRimi/ProxMenux/blob/main/LICENSE
# Version : 1.0
# Last Updated: 14/08/2025
# ==========================================================
# Description:
# Automated or interactive Proxmox VE 8 -> 9 major-version upgrade.
# Follows the official Proxmox upgrade procedure (Debian Bookworm ->
# Trixie + PVE 8 -> 9) with comprehensive safeguards, repository
# migration, Ceph version validation and post-upgrade verification.
#
# A major-version upgrade is destructive and not reversible -- the
# script enforces multiple safety gates and refuses to run from the
# Proxmox web terminal.
#
# Features:
# - Mode menu: Automatic (unattended), Interactive, Pre-check,
# Manual guide.
# - Blocks execution from the web terminal (termproxy / vncshell);
# requires SSH or physical / IPMI / iKVM console.
# - Pre-flight: pve8to9 --full, disk-space check
# (/var/cache/apt/archives >= 1024 MB), connectivity to
# download.proxmox.com, Ceph 19.x Squid validation when present.
# - Brings PVE 8 to the latest 8.4.x patch level first via the
# PVE 8 update worker.
# - Repository migration: sed bookworm -> trixie, deb822 .sources
# files for proxmox + debian + ceph, automatic fallback from
# Enterprise to no-subscription on 401 Unauthorized.
# - Validates 'proxmox-ve' candidate is 9.x and that the dry-run
# dist-upgrade does not propose removing it (would indicate
# broken repo config).
# - dist-upgrade with --force-confdef --force-confold in
# unattended mode; user-driven dpkg prompts in interactive mode.
# - Post-upgrade: installs grub-efi-amd64 on EFI hosts, restarts
# pve-manager, re-runs pve8to9 to surface residual issues.
# - Reboot prompt at the end.
# - Full log written to /var/log/pve8-a-pve9-<timestamp>.log.
# ==========================================================
LOCAL_SCRIPTS="/usr/local/share/proxmenux/scripts"
@@ -21,6 +54,15 @@ fi
load_language
initialize_cache
# Load shared global functions: cleanup_duplicate_repos and ensure_repositories
# are referenced by the auto-repair flow below and live in these files.
if [[ -f "$LOCAL_SCRIPTS/global/common-functions.sh" ]]; then
source "$LOCAL_SCRIPTS/global/common-functions.sh"
fi
if [[ -f "$LOCAL_SCRIPTS/global/utils-install-functions.sh" ]]; then
source "$LOCAL_SCRIPTS/global/utils-install-functions.sh"
fi
# ==========================================================
LOG="/var/log/pve8-a-pve9-$(date +%Y%m%d-%H%M%S).log"
@@ -594,6 +636,17 @@ regenerate_pve_cache
# ---------------------------
run_pve8to9_check() {
# Same recursion guard as in pve8to9_check.sh — auto-repair followed by
# re-check could otherwise loop indefinitely if repairs don't actually
# resolve the FAIL. Cap at 3 attempts. Audit Tier 6.
: "${_PVE8TO9_DEPTH:=0}"
_PVE8TO9_DEPTH=$((_PVE8TO9_DEPTH + 1))
if (( _PVE8TO9_DEPTH > 3 )); then
msg_error "$(translate "Maximum auto-repair attempts reached (3). Please review the log and run any remaining commands manually.")"
_PVE8TO9_DEPTH=0
return 1
fi
local tmp
tmp="$(mktemp)"
echo -e
@@ -637,9 +690,9 @@ run_pve8to9_check() {
# Error 4: Repository configuration issues
if grep -q -E '(repository.*issue|repo.*problem|sources.*error)' "$tmp"; then
repair_commands+=("cleanup_duplicate_repos && configure_repositories")
repair_commands+=("cleanup_duplicate_repos && ensure_repositories")
repair_descriptions+=("$(translate "Fix repository configuration")")
echo -e "${YW}$(translate "Fix repositories:") ${CL}cleanup_duplicate_repos && configure_repositories"
echo -e "${YW}$(translate "Fix repositories:") ${CL}cleanup_duplicate_repos && ensure_repositories"
fi
# Error 5: Package conflicts
@@ -1003,9 +1056,9 @@ run_pve8to9_check2() {
# Error 4: Repository configuration issues
if grep -q -E '(repository.*issue|repo.*problem|sources.*error)' "$tmp"; then
repair_commands+=("cleanup_duplicate_repos && configure_repositories")
repair_commands+=("cleanup_duplicate_repos && ensure_repositories")
repair_descriptions+=("$(translate "Fix repository configuration")")
echo -e "${YW}$(translate "Fix repositories:") ${CL}cleanup_duplicate_repos && configure_repositories"
echo -e "${YW}$(translate "Fix repositories:") ${CL}cleanup_duplicate_repos && ensure_repositories"
fi
# Error 5: Package conflicts
+17 -16
View File
@@ -1,28 +1,29 @@
#!/usr/bin/env bash
# ==========================================================
# ProxMenux - UUP Dump ISO Creator Custom
# ProxMenux - UUP Dump ISO Creator
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : (GPL-3.0) (https://github.com/MacRimi/ProxMenux/blob/main/LICENSE)
# License : GPL-3.0
# https://github.com/MacRimi/ProxMenux/blob/main/LICENSE
# Version : 1.0
# Last Updated: 30/06/2025
# ==========================================================
# Description:
# This script is part of the ProxMenux tools for Proxmox VE.
# It allows downloading and converting official Windows ISO images
# from UUP Dump using a shared link (with ID, pack, and edition).
# Downloads and converts official Windows ISO images from UUP Dump
# using a shared link (ID + pack + edition). Produces an up-to-date
# bootable ISO ready for VM creation in Proxmox VE.
#
# Key features:
# - Automatically installs and verifies required dependencies (aria2c, cabextract, wimlib-imagex…)
# - Downloads the selected Windows edition from UUP Dump using aria2
# - Converts the downloaded files into a bootable ISO
# - Stores the resulting ISO in the default template path (/var/lib/vz/template/iso)
# - Provides a graphical prompt via whiptail for user-friendly usage
#
# This tool simplifies the creation of official Windows ISOs
# for use in virtual machines within Proxmox VE.
# Features:
# - Automatically installs and verifies required dependencies
# (aria2c, cabextract, wimlib-imagex, ...).
# - Downloads the selected Windows edition from UUP Dump using
# aria2 (multi-connection accelerator).
# - Converts the downloaded files into a bootable ISO.
# - Stores the resulting ISO in the default template path
# (/var/lib/vz/template/iso) so it shows up in the Proxmox UI.
# - Whiptail-driven UX (URL prompt, edition / pack confirmation,
# progress reporting).
# ==========================================================
# ==========================================================
BASE_DIR="/usr/local/share/proxmenux"
+15 -14
View File
@@ -1,27 +1,28 @@
#!/usr/bin/env bash
# ==========================================================
# ProxMenuX - Virtual Machine Creator Script
# ProxMenux - Linux ISO Selector
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : (GPL-3.0) (https://github.com/MacRimi/ProxMenux/blob/main/LICENSE)
# License : GPL-3.0
# https://github.com/MacRimi/ProxMenux/blob/main/LICENSE
# Version : 1.0
# Last Updated: 07/05/2025
# ==========================================================
# Description:
# This script is part of the central ProxMenux VM creation module. It allows users
# to create virtual machines (VMs) in Proxmox VE using either default or advanced
# configurations, streamlining the deployment of Linux, Windows, and other systems.
# Linux installation source selector for the ProxMenux VM creator.
# Offers three paths to obtain the Linux installation media and
# also exposes the "Others" prebuilt VM menu used by the main
# dispatcher for community-maintained installers.
#
# Key features:
# - Supports both virtual disk creation and physical disk passthrough.
# - Automates CPU, RAM, BIOS, network and storage configuration.
# - Provides a user-friendly menu to select OS type, ISO image and disk interface.
# - Automatically generates a detailed and styled HTML description for each VM.
#
# All operations are designed to simplify and accelerate VM creation in a
# consistent and maintainable way, using ProxMenux standards.
# Features:
# - Curated list of official Linux ISOs (Ubuntu, Debian, Fedora,
# Arch, Rocky, Mint, openSUSE, Alpine, Kali, Manjaro) with
# direct download URLs.
# - Cloud-Init automated installers (community scripts).
# - Pick an existing ISO from /var/lib/vz/template/iso.
# - Separate "Others Prebuilt VMs" selector (HAOS, Docker, Nextcloud)
# used by the main menu's Community Scripts path.
# ==========================================================
+16 -14
View File
@@ -1,27 +1,27 @@
#!/usr/bin/env bash
# ==========================================================
# ProxMenuX - Virtual Machine Creator Script
# ProxMenux - NAS ISO Selector
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : (GPL-3.0) (https://github.com/MacRimi/ProxMenux/blob/main/LICENSE)
# License : GPL-3.0
# https://github.com/MacRimi/ProxMenux/blob/main/LICENSE
# Version : 1.0
# Last Updated: 04/04/2026
# ==========================================================
# Description:
# This script is part of the central ProxMenux VM creation module. It allows users
# to create virtual machines (VMs) in Proxmox VE using either default or advanced
# configurations, streamlining the deployment of Linux, Windows, and other systems.
# NAS appliance selector for the ProxMenux VM creator. Lists the
# supported NAS operating systems, auto-detects their latest stable
# release (where possible), and prepares the ISO / image metadata
# for the generic VM wizard. Synology DSM and ZimaOS have their own
# dedicated flows; Umbrel OS runs an external community script.
#
# Key features:
# - Supports both virtual disk creation and physical disk passthrough.
# - Automates CPU, RAM, BIOS, network and storage configuration.
# - Provides a user-friendly menu to select OS type, ISO image and disk interface.
# - Automatically generates a detailed and styled HTML description for each VM.
#
# All operations are designed to simplify and accelerate VM creation in a
# consistent and maintainable way, using ProxMenux standards.
# Features:
# - Auto-detects latest versions for TrueNAS SCALE/CORE, OMV,
# XigmaNAS and Rockstor, with safe fallbacks.
# - Dispatches Synology DSM to the dedicated loader-based flow.
# - Dispatches ZimaOS to its own installer script.
# - Runs the Umbrel OS community installer (external script).
# ==========================================================
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
@@ -188,6 +188,8 @@ function select_nas_iso() {
"5" "XigmaNAS VM (FreeBSD based)"
"6" "Rockstor VM (openSUSE based)"
"7" "ZimaOS VM (Proxmox-zimaos)"
"" ""
"" "\Z4───────────────── Community Scripts ─────────────────\Zn"
"8" "Umbrel OS VM (Helper Scripts)"
"9" "$(translate "Return to Main Menu")"
)
+12 -14
View File
@@ -1,27 +1,25 @@
#!/usr/bin/env bash
# ==========================================================
# ProxMenuX - Virtual Machine Creator Script
# ProxMenux - Windows ISO Selector
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : (GPL-3.0) (https://github.com/MacRimi/ProxMenux/blob/main/LICENSE)
# License : GPL-3.0
# https://github.com/MacRimi/ProxMenux/blob/main/LICENSE
# Version : 1.0
# Last Updated: 07/05/2025
# ==========================================================
# Description:
# This script is part of the central ProxMenux VM creation module. It allows users
# to create virtual machines (VMs) in Proxmox VE using either default or advanced
# configurations, streamlining the deployment of Linux, Windows, and other systems.
# Windows installation source selector for the ProxMenux VM
# creator. Offers two paths to obtain the Windows ISO and then
# hands over to the generic VM wizard for CPU, RAM, storage and
# optional GPU passthrough.
#
# Key features:
# - Supports both virtual disk creation and physical disk passthrough.
# - Automates CPU, RAM, BIOS, network and storage configuration.
# - Provides a user-friendly menu to select OS type, ISO image and disk interface.
# - Automatically generates a detailed and styled HTML description for each VM.
#
# All operations are designed to simplify and accelerate VM creation in a
# consistent and maintainable way, using ProxMenux standards.
# Features:
# - Build an up-to-date Windows ISO via the UUP Dump creator.
# - Pick a Windows ISO already present in /var/lib/vz/template/iso.
# - Auto-detects the latest ISO created by UUP Dump.
# - Exports ISO metadata (name, path, OS_TYPE) for the wizard.
# ==========================================================
LOCAL_SCRIPTS="/usr/local/share/proxmenux/scripts"
+19 -16
View File
@@ -1,30 +1,33 @@
#!/usr/bin/env bash
# ==========================================================
# ProxMenuX - Synology DSM VM Creator Script
# ProxMenux - Synology DSM VM Creator
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : (GPL-3.0) (https://github.com/MacRimi/ProxMenux/blob/main/LICENSE)
# License : GPL-3.0
# https://github.com/MacRimi/ProxMenux/blob/main/LICENSE
# Version : 1.0
# Last Updated: 13/03/2025
# ==========================================================
# Description:
# This script automates the creation and configuration of a Synology DSM
# (DiskStation Manager) virtual machine (VM) in Proxmox VE. It simplifies the
# setup process by allowing both default and advanced configuration options.
# Creates and configures a Synology DSM (DiskStation Manager)
# virtual machine on Proxmox VE. Downloads one of the supported
# loaders (Arc, RR, TinyCore M-shell, or a custom one), imports
# it as the VM boot disk, and prepares CPU/RAM/network/storage
# through the ProxMenux default or advanced wizard.
#
# The script automates the complete VM creation process, including loader
# download, disk configuration, and VM boot setup.
#
# **Credits**
# This script is an original idea but incorporates ideas and elements from
# a similar script by user **tim104979** from the ProxmoxVE branch:
# (https://raw.githubusercontent.com/tim104979/ProxmoxVE/refs/heads/main/vm/synology-vm.sh)
#
# Copyright (c) Proxmox VE Helper-Scripts Community
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Features:
# - Supports Arc, RR, TinyCore M-shell and Custom loaders.
# - Default and Advanced configuration modes.
# - Virtual disks (SATA, up to 6) or physical disk passthrough.
# - Imports the loader as IDE for maximum compatibility.
# - Generates a styled HTML description attached to the VM.
#
# Credits:
# Original work by MacRimi. Incorporates ideas and snippets from
# tim104979's synology-vm.sh in the ProxmoxVE Helper-Scripts
# Community project (MIT):
# https://raw.githubusercontent.com/tim104979/ProxmoxVE/refs/heads/main/vm/synology-vm.sh
# ==========================================================
+16 -14
View File
@@ -5,24 +5,26 @@
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : (GPL-3.0) (https://github.com/MacRimi/ProxMenux/blob/main/LICENSE)
# License : GPL-3.0
# https://github.com/MacRimi/ProxMenux/blob/main/LICENSE
# Version : 1.0
# Last Updated: 07/05/2025
# ==========================================================
# Description:
# This script is part of the ProxMenux tools for Proxmox VE.
# It allows downloading and converting official Windows ISO images
# from UUP Dump using a shared link (with ID, pack, and edition).
# Downloads and converts an official Windows ISO from UUP Dump
# using a shared link that carries the build parameters (id,
# pack, edition). The resulting ISO is placed in the Proxmox
# ISO storage and becomes immediately available to the VM
# creator.
#
# Key features:
# - Automatically installs and verifies required dependencies (aria2c, cabextract, wimlib-imagex…)
# - Downloads the selected Windows edition from UUP Dump using aria2
# - Converts the downloaded files into a bootable ISO
# - Stores the resulting ISO in the default template path (/var/lib/vz/template/iso)
# - Provides a graphical prompt via whiptail for user-friendly usage
#
# This tool simplifies the creation of official Windows ISOs
# for use in virtual machines within Proxmox VE.
# Features:
# - Auto-installs dependencies (aria2, cabextract, wimtools,
# genisoimage, chntpw, curl).
# - Downloads the UUP Dump converter and all UUP payload files
# in parallel with aria2.
# - Builds a bootable ISO via the upstream convert.sh.
# - Auto-detects the Proxmox ISO storage directory and falls
# back to /var/lib/vz/template/iso.
# - Interactive prompts via whiptail / dialog.
# ==========================================================
BASE_DIR="/usr/local/share/proxmenux"
+13 -14
View File
@@ -1,27 +1,26 @@
#!/usr/bin/env bash
# ==========================================================
# ProxMenuX - Virtual Machine Creator Script
# ProxMenux - VM Configurator (CPU / RAM / BIOS / Network)
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : (GPL-3.0) (https://github.com/MacRimi/ProxMenux/blob/main/LICENSE)
# License : GPL-3.0
# https://github.com/MacRimi/ProxMenux/blob/main/LICENSE
# Version : 1.0
# Last Updated: 07/05/2025
# ==========================================================
# Description:
# This script is part of the central ProxMenux VM creation module. It allows users
# to create virtual machines (VMs) in Proxmox VE using either default or advanced
# configurations, streamlining the deployment of Linux, Windows, and other systems.
# Shared VM configurator used by the ProxMenux VM creation
# flows (NAS, Windows, Linux, Synology, ZimaOS). Exposes two
# helpers: the default-profile applier (per OS family) and the
# advanced wizard that walks the user through every parameter.
#
# Key features:
# - Supports both virtual disk creation and physical disk passthrough.
# - Automates CPU, RAM, BIOS, network and storage configuration.
# - Provides a user-friendly menu to select OS type, ISO image and disk interface.
# - Automatically generates a detailed and styled HTML description for each VM.
#
# All operations are designed to simplify and accelerate VM creation in a
# consistent and maintainable way, using ProxMenux standards.
# Features:
# - VMID auto-assignment and collision check.
# - Hostname, machine type (q35 / i440fx), BIOS (OVMF / SeaBIOS).
# - CPU type (host / kvm64), core count, RAM.
# - Network: bridge, MAC, VLAN, MTU.
# - Per-OS defaults (NAS, Windows, Linux) and OMV BIOS override.
# ==========================================================
+13 -10
View File
@@ -1,23 +1,26 @@
#!/usr/bin/env bash
# ==========================================================
# ProxMenuX - ZimaOS VM Creator Script
# ProxMenux - ZimaOS VM Creator
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : (GPL-3.0) (https://github.com/MacRimi/ProxMenux/blob/main/LICENSE)
# License : GPL-3.0
# https://github.com/MacRimi/ProxMenux/blob/main/LICENSE
# Version : 1.0
# Last Updated: 21/08/2025
# ==========================================================
# Description:
# This script automates the creation and configuration of a ZimaOS
# Virtual machine (VM) in Proxmox VE. It simplifies the
# setup process by allowing both default and advanced configuration options.
#
# The script automates the complete VM creation process, including loader
# download, disk configuration, and VM boot setup.
#
# Creates and configures a ZimaOS virtual machine on Proxmox VE.
# Downloads the ZimaOS pre-built image, wires it into a new VM
# using either the ProxMenux default profile or the advanced
# wizard, and hands storage and optional GPU passthrough to the
# shared helpers.
#
# Features:
# - Default and Advanced configuration modes.
# - Unified storage plan (virtual / import / PCI passthrough).
# - Optional GPU passthrough via the shared VM wizard.
# - Auto-generates a styled HTML description attached to the VM.
# ==========================================================