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
+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