Files
ProxMenux/scripts/post_install/uninstall-tools.sh
T
MacRimiandClaude Opus 5 da8a480eff Add audit and reports page, and a change journal
ProxMenux modifies the host: it rewrites configuration files, installs packages, enables services. Until now nobody could say afterwards what had changed, and showing the script does not answer that question — a four-hundred-line function may alter two values, and the reader has no way to know which two. This adds the two halves of an answer.

The change journal records what ProxMenux does as it does it. Eleven bash primitives capture the previous state, apply the change and record it in the same step, writing to a spool that the Monitor reads back. One hundred and thirteen functions across twenty-five scripts are instrumented, covering post-install, shared storage, security tooling, container conversions, disk operations and the PVE 8 to 9 upgrade path. The page shows the difference — rotate 7 becoming rotate 14 — and never the script. Restore and backup scripts are deliberately left out: a restore puts the host back to a state some other script already recorded.

The Audit and reports page answers the other half: what state is this host in, regardless of who put it there. Forty-three checks across seven areas read the host and classify each result as critical, warning, observation, conformant, unverified or not applicable, with the evidence they read attached to each one. A declared policy lets the reader say what this particular host is expected to do — which guests must have a backup, which storages are essential — so the report judges the host against its own intent rather than a generic template. An inventory records the hardware, network and guest topology behind those readings, a comparison shows what moved between two runs, and six report profiles produce a printable document scoped to what the reader needs. Everything is available in the eight supported languages.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 21:06:04 +02:00

1301 lines
48 KiB
Bash

#!/bin/bash
# ==========================================================
# ProxMenux - Uninstall Optimizations
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : GPL-3.0
# https://github.com/MacRimi/ProxMenux/blob/main/LICENSE
# Version : 1.1
# ==========================================================
# Description:
# 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.
#
# Features:
# - Registry-driven: only shows tools currently applied.
# - Per-tool reverse functions for each registered reversible 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, …).
# ==========================================================
LOCAL_SCRIPTS="/usr/local/share/proxmenux/scripts"
RETURN_SCRIPT="$LOCAL_SCRIPTS/menus/menu_post_install.sh"
BASE_DIR="/usr/local/share/proxmenux"
UTILS_FILE="$BASE_DIR/utils.sh"
TOOLS_JSON="$BASE_DIR/installed_tools.json"
if [[ -f "$UTILS_FILE" ]]; then
source "$UTILS_FILE"
fi
if [[ -f "$LOCAL_SCRIPTS/global/pmx_journal.sh" ]]; then
source "$LOCAL_SCRIPTS/global/pmx_journal.sh"
fi
load_language
initialize_cache
# Tool registration system
ensure_tools_json() {
[ -f "$TOOLS_JSON" ] || echo "{}" > "$TOOLS_JSON"
}
register_tool() {
local tool="$1"
local state="$2"
ensure_tools_json
jq --arg t "$tool" --argjson v "$state" '.[$t]=$v' "$TOOLS_JSON" > "$TOOLS_JSON.tmp" && mv "$TOOLS_JSON.tmp" "$TOOLS_JSON"
}
################################################################
uninstall_fastfetch() {
local FUNC_VERSION="1.0"
pmx_journal_context "uninstall_fastfetch" "$FUNC_VERSION"
if ! command -v fastfetch &>/dev/null && [[ ! -f /usr/local/bin/fastfetch ]]; then
msg_warn "$(translate "Fastfetch is not installed.")"
return 0
fi
msg_info2 "$(translate "Uninstalling Fastfetch...")"
pmx_remove_file /usr/local/bin/fastfetch
pmx_remove_file /usr/bin/fastfetch
pmx_record_execution "Remove Fastfetch configuration directory" "rm -rf $HOME/.config/fastfetch"
rm -rf "$HOME/.config/fastfetch"
pmx_record_execution "Remove shared Fastfetch files" "rm -rf /usr/local/share/fastfetch"
rm -rf /usr/local/share/fastfetch
local profile_file
for profile_file in "$HOME/.bashrc" "$HOME/.profile" /etc/profile; do
pmx_edit_file "$profile_file" '/fastfetch/d' 2>/dev/null || true
done
pmx_edit_file "$HOME/.bashrc" '/# BEGIN FASTFETCH/,/# END FASTFETCH/d'
pmx_remove_file /etc/profile.d/fastfetch.sh
pmx_remove_file /etc/update-motd.d/99-fastfetch
pmx_record_execution "Remove Fastfetch package" "dpkg -r fastfetch"
dpkg -r fastfetch &>/dev/null
msg_ok "$(translate "Fastfetch removed from system")"
register_tool "fastfetch" false
}
################################################################
uninstall_figurine() {
local FUNC_VERSION="1.0"
pmx_journal_context "uninstall_figurine" "$FUNC_VERSION"
if ! command -v figurine &>/dev/null; then
msg_warn "$(translate "Figurine is not installed.")"
return 0
fi
msg_info2 "$(translate "Uninstalling Figurine...")"
pmx_remove_file /usr/local/bin/figurine
pmx_remove_file /etc/profile.d/figurine.sh
local profile_file
for profile_file in "$HOME/.bashrc" "$HOME/.profile"; do
pmx_edit_file "$profile_file" '/lxcclean/d;/lxcupdate/d;/kernelclean/d;/cpugov/d;/updatecerts/d;/seqwrite/d;/seqread/d;/ranwrite/d;/ranread/d' 2>/dev/null || true
pmx_edit_file "$profile_file" '/# ProxMenux Figurine aliases and tools/,+20d' 2>/dev/null || true
pmx_edit_file "$profile_file" '/# BEGIN PROXMENUX ALIASES/,/# END PROXMENUX ALIASES/d' 2>/dev/null || true
done
msg_ok "$(translate "Figurine removed from system")"
register_tool "figurine" false
}
################################################################
uninstall_kexec() {
local FUNC_VERSION="1.0"
pmx_journal_context "uninstall_kexec" "$FUNC_VERSION"
if ! dpkg -s kexec-tools >/dev/null 2>&1 && [ ! -f /etc/systemd/system/kexec-pve.service ]; then
msg_warn "$(translate "kexec-tools is not installed or already removed.")"
return 0
fi
msg_info2 "$(translate "Uninstalling kexec-tools and removing custom service...")"
pmx_disable_service kexec-pve.service
pmx_remove_file /etc/systemd/system/kexec-pve.service
pmx_edit_file /root/.bash_profile "/alias reboot-quick='systemctl kexec'/d"
pmx_record_execution "Purge kexec-tools package" "apt-get purge -y kexec-tools"
apt-get purge -y kexec-tools >/dev/null 2>&1
msg_ok "$(translate "kexec-tools and related settings removed")"
register_tool "kexec" false
}
################################################################
uninstall_subscription_banner() {
msg_info "$(translate "Restoring subscription banner...")"
local JS_FILE="/usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js"
local MOBILE_UI_FILE="/usr/share/pve-yew-mobile-gui/index.html.tpl"
local PATCH_BIN="/usr/local/bin/pve-remove-nag-v3.sh"
local BASE_DIR="/usr/local/share/proxmenux"
local MIN_JS_FILE="/usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.min.js"
local GZ_FILE="/usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js.gz"
local restored=false
for hook in /etc/apt/apt.conf.d/*nag*; do
if [[ -e "$hook" ]]; then
rm -f "$hook"
msg_ok "$(translate "Removed APT hook: $hook")"
fi
done
if [[ -f "$PATCH_BIN" ]]; then
rm -f "$PATCH_BIN"
msg_ok "$(translate "Removed patch script: $PATCH_BIN")"
fi
if [[ -d "$BASE_DIR/backups" ]]; then
local backup_file
backup_file=$(ls -t "$BASE_DIR/backups"/proxmoxlib.js.backup.* 2>/dev/null | head -1)
if [[ -n "$backup_file" && -f "$backup_file" ]]; then
# Verify backup integrity before restoring
if [[ -s "$backup_file" ]] && grep -q "Ext\|function" "$backup_file" && ! grep -q $'\0' "$backup_file"; then
cp -a "$backup_file" "$JS_FILE"
msg_ok "$(translate "Restored desktop UI from backup: $backup_file")"
restored=true
else
msg_warn "$(translate "Backup file appears corrupted, will reinstall packages")"
fi
else
msg_warn "$(translate "No desktop UI backup found, will reinstall packages")"
fi
local mobile_backup
mobile_backup=$(ls -t "$BASE_DIR/backups"/index.html.tpl.backup.* 2>/dev/null | head -1)
if [[ -n "$mobile_backup" && -f "$mobile_backup" && -f "$MOBILE_UI_FILE" ]]; then
if [[ -s "$mobile_backup" ]]; then
cp -a "$mobile_backup" "$MOBILE_UI_FILE"
msg_ok "$(translate "Restored mobile UI from backup: $mobile_backup")"
fi
fi
fi
if [[ "$restored" == false ]]; then
msg_info "$(translate "Performing complete package reinstallation...")"
# Update package lists
apt-get update >/dev/null 2>&1
# Reinstall packages with force-confnew to restore original configs
if apt-get --reinstall -o Dpkg::Options::="--force-confnew" install \
pve-manager proxmox-widget-toolkit libjs-extjs libpve-http-server-perl -y >/dev/null 2>&1; then
msg_ok "$(translate "Reinstalled Proxmox packages successfully")"
restored=true
else
msg_error "$(translate "Failed to reinstall packages")"
fi
# Clean package update cache
rm -rf /var/lib/pve-manager/pkgupdates /var/cache/pve-manager 2>/dev/null || true
# Second pass reinstallation to ensure everything is clean
apt-get update >/dev/null 2>&1
apt-get --reinstall install proxmox-widget-toolkit pve-manager libjs-extjs libpve-http-server-perl -y >/dev/null 2>&1 || true
fi
msg_info "$(translate "Cleaning cached files...")"
rm -f "$MIN_JS_FILE" "$GZ_FILE" 2>/dev/null || true
rm -rf /var/lib/pve-manager/pkgupdates /var/cache/pve-manager 2>/dev/null || true
find /var/cache/pve-manager/ -name "*.js*" -delete 2>/dev/null || true
find /var/lib/pve-manager/ -name "*.js*" -delete 2>/dev/null || true
find /var/cache/nginx/ -type f -delete 2>/dev/null || true
#systemctl restart pveproxy pvedaemon pvestatd 2>/dev/null || true
if [[ "$restored" == true ]]; then
register_tool "subscription_banner" false
msg_ok "$(translate "Subscription banner restored successfully (desktop and mobile)")"
msg_ok "$(translate "Refresh your browser to see changes (server restart may be required)")"
else
msg_error "$(translate "Failed to restore subscription banner completely")"
return 1
fi
}
################################################################
uninstall_rpc() {
local state_file="$BASE_DIR/rpcbind.state"
local unit enabled_state active_state
local failed=0
if [[ ! -s "$state_file" ]]; then
msg_error "$(translate "The original rpcbind state is unavailable; no service state was changed")"
return 1
fi
msg_info2 "$(translate "Restoring the original rpcbind service state...")"
while IFS='|' read -r unit enabled_state active_state; do
[[ "$unit" != "rpcbind.service" && "$unit" != "rpcbind.socket" ]] && continue
case "$enabled_state" in
enabled)
systemctl enable "$unit" >/dev/null 2>&1 || failed=1
;;
enabled-runtime)
systemctl enable --runtime "$unit" >/dev/null 2>&1 || failed=1
;;
masked)
systemctl mask "$unit" >/dev/null 2>&1 || failed=1
;;
masked-runtime)
systemctl mask --runtime "$unit" >/dev/null 2>&1 || failed=1
;;
*)
systemctl disable "$unit" >/dev/null 2>&1 || true
;;
esac
case "$active_state" in
active|activating|reloading)
systemctl start "$unit" >/dev/null 2>&1 || failed=1
;;
*)
systemctl stop "$unit" >/dev/null 2>&1 || true
;;
esac
done < "$state_file"
if [[ "$failed" -ne 0 ]]; then
msg_error "$(translate "The original rpcbind state could not be restored completely")"
return 1
fi
rm -f "$state_file"
register_tool "rpc" false
msg_ok "$(translate "The original rpcbind service state has been restored")"
}
################################################################
uninstall_motd() {
local FUNC_VERSION="1.0"
pmx_journal_context "uninstall_motd" "$FUNC_VERSION"
local state_file="$BASE_DIR/motd.state"
local original_file="$BASE_DIR/motd.original"
local motd_file="${PROXMENUX_MOTD_FILE:-/etc/motd}"
local custom_message=" This system is optimised by: ProxMenux"
local original_state
if [[ ! -f "$state_file" ]]; then
msg_error "$(translate "The original MOTD state is unavailable; no changes were made")"
return 1
fi
original_state="$(head -n 1 "$state_file" 2>/dev/null)"
case "$original_state" in
present)
if [[ ! -f "$original_file" ]]; then
msg_error "$(translate "The original MOTD backup is unavailable; no changes were made")"
return 1
fi
pmx_write_file "$motd_file" < "$original_file"
;;
absent)
pmx_remove_file "$motd_file"
;;
legacy-marker)
if [[ -f "$motd_file" ]]; then
pmx_edit_file "$motd_file" "\|^${custom_message}$|d"
pmx_edit_file "$motd_file" '/./,$!d'
fi
;;
*)
msg_error "$(translate "The saved MOTD state is invalid; no changes were made")"
return 1
;;
esac
pmx_remove_file "$state_file"
pmx_remove_file "$original_file"
register_tool "motd" false
msg_ok "$(translate "The original MOTD configuration has been restored")"
}
################################################################
uninstall_system_utils() {
local state_file="$BASE_DIR/system_utils.packages"
local remaining_file="${state_file}.remaining.$$"
local package
local packages=()
if [[ ! -s "$state_file" ]]; then
msg_error "$(translate "No ProxMenux-installed utility package list is available")"
return 1
fi
while IFS= read -r package; do
[[ "$package" =~ ^[a-z0-9][a-z0-9+.-]*(:[a-z0-9]+)?$ ]] || continue
packages+=("$package")
done < "$state_file"
if [[ ${#packages[@]} -eq 0 ]]; then
msg_error "$(translate "The saved utility package list is invalid; no packages were removed")"
return 1
fi
msg_info2 "$(translate "Removing utilities installed by ProxMenux...")"
/usr/bin/env DEBIAN_FRONTEND=noninteractive apt-get purge -y "${packages[@]}" >/dev/null 2>&1 || true
: > "$remaining_file"
for package in "${packages[@]}"; do
if dpkg-query -W -f='${Status}' "$package" 2>/dev/null | grep -q '^install ok installed$'; then
printf '%s\n' "$package" >> "$remaining_file"
fi
done
if [[ -s "$remaining_file" ]]; then
mv "$remaining_file" "$state_file"
msg_error "$(translate "Some utility packages could not be removed; the remaining list has been preserved")"
return 1
fi
rm -f "$remaining_file" "$state_file"
register_tool "system_utils" false
msg_ok "$(translate "Utilities installed by ProxMenux have been removed")"
}
################################################################
uninstall_time_sync() {
msg_info "$(translate "Resetting time synchronization...")"
# Reset to UTC (safe default)
timedatectl set-timezone UTC >/dev/null 2>&1
msg_ok "$(translate "Time synchronization reset to UTC")"
register_tool "time_sync" false
}
################################################################
uninstall_apt_languages() {
msg_info "$(translate "Restoring APT language downloads...")"
# Remove the configuration that disables translations
rm -f /etc/apt/apt.conf.d/99-disable-translations
msg_ok "$(translate "APT language downloads restored")"
register_tool "apt_languages" false
}
################################################################
uninstall_journald() {
local FUNC_VERSION="1.0"
pmx_journal_context "uninstall_journald" "$FUNC_VERSION"
msg_info "$(translate "Restoring default journald configuration...")"
# Restore default journald configuration
pmx_write_file /etc/systemd/journald.conf << 'EOF'
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
#
# Entries in this file show the compile time defaults.
# You can change settings by editing this file.
# Defaults can be restored by simply deleting this file.
#
# See journald.conf(5) for details.
[Journal]
#Storage=auto
#Compress=yes
#Seal=yes
#SplitMode=uid
#SyncIntervalSec=5m
#RateLimitInterval=30s
#RateLimitBurst=1000
#SystemMaxUse=
#SystemKeepFree=
#SystemMaxFileSize=
#RuntimeMaxUse=
#RuntimeKeepFree=
#RuntimeMaxFileSize=
#MaxRetentionSec=
#MaxFileSec=1month
#ForwardToSyslog=yes
#ForwardToKMsg=no
#ForwardToConsole=no
#ForwardToWall=yes
#TTYPath=/dev/console
#MaxLevelStore=debug
#MaxLevelSyslog=debug
#MaxLevelKMsg=notice
#MaxLevelConsole=info
#MaxLevelWall=emerg
EOF
pmx_record_execution "Restart systemd-journald" "systemctl restart systemd-journald.service"
systemctl restart systemd-journald.service >/dev/null 2>&1
msg_ok "$(translate "Default journald configuration restored")"
register_tool "journald" false
}
################################################################
uninstall_logrotate() {
msg_info "$(translate "Restoring original logrotate configuration...")"
[ -f /etc/logrotate.d/pveproxy ] && rm -f /etc/logrotate.d/pveproxy
if [ -f /etc/logrotate.conf.bak ]; then
mv /etc/logrotate.conf.bak /etc/logrotate.conf
systemctl restart logrotate >/dev/null 2>&1
msg_ok "$(translate "Original logrotate configuration restored")"
else
msg_warn "$(translate "No backup found, logrotate configuration not changed")"
fi
register_tool "logrotate" false
}
################################################################
uninstall_system_limits() {
local FUNC_VERSION="1.0"
pmx_journal_context "uninstall_system_limits" "$FUNC_VERSION"
msg_info "$(translate "Removing system limits optimizations...")"
# Remove ProxMenux sysctl configurations
pmx_remove_file /etc/sysctl.d/99-maxwatches.conf
pmx_remove_file /etc/sysctl.d/99-maxkeys.conf
pmx_remove_file /etc/sysctl.d/99-swap.conf
pmx_remove_file /etc/sysctl.d/99-fs.conf
# Remove ProxMenux limits configuration
pmx_remove_file /etc/security/limits.d/99-limits.conf
# Remove systemd limits (restore defaults)
for file in /etc/systemd/system.conf /etc/systemd/user.conf; do
if [ -f "$file" ]; then
pmx_edit_file "$file" '/^DefaultLimitNOFILE=256000/d'
fi
done
# Remove PAM limits
for file in /etc/pam.d/common-session /etc/pam.d/runuser-l; do
if [ -f "$file" ]; then
pmx_edit_file "$file" '/^session required pam_limits.so/d'
fi
done
# Remove ulimit from profile
if [ -f /root/.profile ]; then
pmx_edit_file /root/.profile '/ulimit -n 256000/d'
fi
# Reload sysctl
pmx_record_execution "Apply sysctl configuration" "sysctl --system"
sysctl --system >/dev/null 2>&1
msg_ok "$(translate "System limits optimizations removed")"
register_tool "system_limits" false
}
################################################################
uninstall_entropy() {
msg_info "$(translate "Removing entropy generation optimization...")"
# Stop and disable haveged
systemctl stop haveged >/dev/null 2>&1
systemctl disable haveged >/dev/null 2>&1
# Remove haveged package
apt-get purge -y haveged >/dev/null 2>&1
# Remove configuration
rm -f /etc/default/haveged
msg_ok "$(translate "Entropy generation optimization removed")"
register_tool "entropy" false
}
################################################################
uninstall_memory_settings() {
msg_info "$(translate "Removing memory optimizations...")"
# Remove ProxMenux memory configuration
rm -f /etc/sysctl.d/99-memory.conf
# Reload sysctl
sysctl --system >/dev/null 2>&1
msg_ok "$(translate "Memory optimizations removed")"
register_tool "memory_settings" false
}
################################################################
uninstall_kernel_panic() {
msg_info "$(translate "Removing kernel panic configuration...")"
# Remove ProxMenux kernel panic configuration
rm -f /etc/sysctl.d/99-kernelpanic.conf
# Reload sysctl
sysctl --system >/dev/null 2>&1
msg_ok "$(translate "Kernel panic configuration removed")"
register_tool "kernel_panic" false
}
################################################################
uninstall_apt_ipv4() {
msg_info "$(translate "Removing APT IPv4 configuration...")"
# Remove IPv4 force configuration
rm -f /etc/apt/apt.conf.d/99-force-ipv4
msg_ok "$(translate "APT IPv4 configuration removed")"
register_tool "apt_ipv4" false
}
################################################################
uninstall_network_optimization() {
local FUNC_VERSION="1.0"
pmx_journal_context "uninstall_network_optimization" "$FUNC_VERSION"
msg_info "$(translate "Removing network optimizations...")"
pmx_remove_file /etc/sysctl.d/99-network.conf
local interfaces_file="/etc/network/interfaces"
if [ -f "$interfaces_file" ]; then
pmx_edit_file "$interfaces_file" '/^source \/etc\/network\/interfaces\.d\/\*/d'
fi
pmx_remove_file /etc/sysctl.d/97-proxmenux-fwbr.conf
pmx_remove_file /etc/sysctl.d/98-proxmenux-rpf.conf
pmx_disable_service proxmenux-fwbr-tune.service || true
pmx_remove_file /etc/systemd/system/proxmenux-fwbr-tune.service
pmx_remove_file /usr/local/sbin/proxmenux-fwbr-tune
pmx_remove_file /etc/udev/rules.d/99-proxmenux-fwbr-tune.rules
pmx_remove_file /etc/udev/rules.d/99-zz-proxmenux-fwbr-tune.rules
pmx_record_execution "Reload udev rules" "udevadm control --reload-rules"
udevadm control --reload-rules >/dev/null 2>&1 || true
pmx_record_execution "Reload systemd configuration" "systemctl daemon-reload"
systemctl daemon-reload >/dev/null 2>&1 || true
pmx_record_execution "Apply sysctl configuration" "sysctl --system"
sysctl --system >/dev/null 2>&1 || true
msg_ok "$(translate "Network optimizations removed")"
register_tool "network_optimization" false
}
################################################################
uninstall_bashrc_custom() {
local FUNC_VERSION="1.0"
pmx_journal_context "uninstall_bashrc_custom" "$FUNC_VERSION"
msg_info "$(translate "Restoring original bashrc...")"
# Restore original bashrc from backup
if [ -f /root/.bashrc.bak ]; then
pmx_write_file /root/.bashrc < /root/.bashrc.bak
pmx_remove_file /root/.bashrc.bak
msg_ok "$(translate "Original bashrc restored")"
else
# Remove ProxMenux customizations manually
if [ -f /root/.bashrc ]; then
# Remove the customization block using the markers written by customize_bashrc
pmx_edit_file /root/.bashrc '/# BEGIN PMX_CORE_BASHRC/,/# END PMX_CORE_BASHRC/d'
fi
msg_ok "$(translate "ProxMenux customizations removed from bashrc")"
fi
# Remove bash_profile source line if we added it
if [ -f /root/.bash_profile ]; then
pmx_edit_file /root/.bash_profile '/source \/root\/\.bashrc/d'
fi
register_tool "bashrc_custom" false
}
################################################################
uninstall_log2ram() {
msg_info "$(translate "Uninstalling log2ram (all versions)...")"
systemctl stop log2ram log2ram-daily.timer log2ram-daily.service >/dev/null 2>&1 || true
systemctl disable log2ram log2ram-daily.timer log2ram-daily.service >/dev/null 2>&1 || true
rm -f /etc/cron.d/log2ram \
/etc/cron.d/log2ram-auto-sync \
/etc/cron.d/log2ram-sync \
/etc/cron.hourly/log2ram \
/etc/cron.daily/log2ram \
/etc/cron.weekly/log2ram \
/etc/cron.monthly/log2ram 2>/dev/null || true
rm -f /usr/local/bin/log2ram-check.sh \
/usr/local/bin/log2ram \
/usr/local/bin/log2ram-sync \
/usr/sbin/log2ram \
/usr/bin/log2ram 2>/dev/null || true
rm -f /etc/systemd/system/log2ram.service \
/etc/systemd/system/log2ram-daily.timer \
/etc/systemd/system/log2ram-daily.service \
/etc/systemd/system/sysinit.target.wants/log2ram.service \
/etc/systemd/system/timers.target.wants/log2ram-daily.timer \
/lib/systemd/system/log2ram.service \
/lib/systemd/system/log2ram-daily.timer \
/lib/systemd/system/log2ram-daily.service 2>/dev/null || true
rm -rf /etc/systemd/system/log2ram.service.d 2>/dev/null || true
rm -f /etc/log2ram.conf \
/etc/log2ram.conf.dpkg-old \
/etc/log2ram.conf.bak \
/etc/log2ram.conf.save 2>/dev/null || true
rm -rf /etc/logrotate.d/log2ram 2>/dev/null || true
if mountpoint -q /var/log 2>/dev/null; then
if [[ -d /var/log.hdd ]]; then
msg_info "$(translate "Preserving logs to /var/log.hdd before unmounting...")"
rsync -a /var/log/ /var/log.hdd/ >/dev/null 2>&1 || true
fi
umount /var/log >/dev/null 2>&1 || true
fi
[[ -d /var/log.hdd ]] && rm -rf /var/log.hdd
[[ -d /tmp/log2ram ]] && rm -rf /tmp/log2ram
[[ -d /var/hdd.log ]] && rm -rf /var/hdd.log
[[ -f /tmp/log2ram_install.log ]] && rm -f /tmp/log2ram_install.log
systemctl daemon-reload >/dev/null 2>&1 || true
systemctl reset-failed >/dev/null 2>&1 || true
systemctl restart cron >/dev/null 2>&1 || true
if dpkg -l 2>/dev/null | grep -q '^ii log2ram'; then
msg_info "$(translate "Purging log2ram apt package...")"
apt-get purge -y log2ram >/dev/null 2>&1 || true
apt-get autoremove -y >/dev/null 2>&1 || true
fi
if [[ -f /etc/log2ram.conf ]] || \
command -v log2ram >/dev/null 2>&1 || \
systemctl list-units --all 2>/dev/null | grep -q log2ram || \
[[ -f /etc/cron.d/log2ram-auto-sync ]]; then
msg_warn "$(translate "Some log2ram files may still exist. Manual cleanup may be required.")"
else
msg_ok "$(translate "log2ram completely removed from system")"
fi
register_tool "log2ram" false
NECESSARY_REBOOT=1
}
################################################################
uninstall_persistent_network() {
msg_info "$(translate "Removing ProxMenux persistent NIC .link files...")"
sleep 1
if ! type pmx_uninstall_persistent_network &>/dev/null; then
if [[ -f "$LOCAL_SCRIPTS/global/utils-install-functions.sh" ]]; then
source "$LOCAL_SCRIPTS/global/utils-install-functions.sh"
fi
fi
local removed=0
while IFS='=' read -r key value; do
[[ "$key" == "REMOVED" ]] && removed="$value"
done < <(pmx_uninstall_persistent_network)
if (( removed > 0 )); then
msg_ok "$(translate "Removed") $removed $(translate "ProxMenux-managed .link file(s). User-authored .link files were left in place.")"
msg_info "$(translate "Interface names will return to default systemd behavior.")"
NECESSARY_REBOOT=1
else
msg_warn "$(translate "No ProxMenux-managed .link files found — nothing to remove.")"
fi
register_tool "persistent_network" false
}
uninstall_vfio_iommu() {
local FUNC_VERSION="1.0"
pmx_journal_context "uninstall_vfio_iommu" "$FUNC_VERSION"
msg_info2 "$(translate "Reverting IOMMU/VFIO configuration...")"
NECESSARY_REBOOT=1
# Remove VFIO modules from /etc/modules
local modules_file="/etc/modules"
if [ -f "$modules_file" ]; then
pmx_edit_file "$modules_file" '/^vfio$/d;/^vfio_iommu_type1$/d;/^vfio_pci$/d;/^vfio_virqfd$/d'
msg_ok "$(translate "VFIO modules removed from /etc/modules")"
fi
# Remove driver blacklists added by ProxMenux
local blacklist_file="/etc/modprobe.d/blacklist.conf"
if [ -f "$blacklist_file" ]; then
pmx_edit_file "$blacklist_file" '/^blacklist nouveau$/d;/^blacklist lbm-nouveau$/d;/^blacklist radeon$/d;/^blacklist nvidia$/d;/^blacklist nvidiafb$/d;/^options nouveau modeset=0$/d'
[ ! -s "$blacklist_file" ] && pmx_remove_file "$blacklist_file"
msg_ok "$(translate "Driver blacklist entries removed")"
fi
# Remove IOMMU kernel parameters
local cmdline_file="/etc/kernel/cmdline"
if [[ -f "$cmdline_file" ]] && grep -qE 'root=ZFS=|root=ZFS/' "$cmdline_file"; then
# systemd-boot / ZFS
if grep -qE 'intel_iommu=on|amd_iommu=on|iommu=pt|pcie_acs_override=' "$cmdline_file"; then
cp "$cmdline_file" "${cmdline_file}.bak.$(date +%Y%m%d_%H%M%S)"
pmx_edit_file "$cmdline_file" -E 's/\b(intel_iommu=on|amd_iommu=on|iommu=pt|pcie_acs_override=[^ ]*)\b//g'
pmx_edit_file "$cmdline_file" -E 's/[[:space:]]+/ /g; s/^ //; s/ $//'
if command -v proxmox-boot-tool >/dev/null 2>&1; then
pmx_record_execution "Refresh Proxmox boot configuration" "proxmox-boot-tool refresh"
proxmox-boot-tool refresh >/dev/null 2>&1 || true
fi
msg_ok "$(translate "IOMMU parameters removed from /etc/kernel/cmdline")"
fi
else
# GRUB
local grub_file="/etc/default/grub"
if [[ -f "$grub_file" ]] && grep -qE 'intel_iommu=on|amd_iommu=on|iommu=pt|pcie_acs_override=' "$grub_file"; then
cp "$grub_file" "${grub_file}.bak.$(date +%Y%m%d_%H%M%S)"
pmx_edit_file "$grub_file" -E 's/\b(intel_iommu=on|amd_iommu=on|iommu=pt|pcie_acs_override=[^ "]*)\b//g'
awk -F\" 'BEGIN{OFS="\""} /GRUB_CMDLINE_LINUX_DEFAULT=/{gsub(/[[:space:]]+/," ",$2);sub(/^ /,"",$2);sub(/ $/,"",$2)}1' \
"$grub_file" | pmx_write_file "$grub_file"
pmx_record_execution "Regenerate GRUB configuration" "update-grub"
update-grub >/dev/null 2>&1 || true
msg_ok "$(translate "IOMMU parameters removed from GRUB")"
fi
fi
msg_info "$(translate 'Updating initramfs (this may take a minute)...')"
pmx_record_execution "Regenerate initramfs" "update-initramfs -u -k all"
update-initramfs -u -k all >/dev/null 2>&1 || true
pmx_record_execution "Refresh Proxmox boot configuration" "proxmox-boot-tool refresh"
proxmox-boot-tool refresh >/dev/null 2>&1 || true
msg_ok "$(translate "IOMMU/VFIO configuration reverted")"
register_tool "vfio_iommu" false
}
################################################################
uninstall_amd_fixes() {
local FUNC_VERSION="1.0"
pmx_journal_context "uninstall_amd_fixes" "$FUNC_VERSION"
msg_info2 "$(translate "Reverting AMD (Ryzen/EPYC) fixes...")"
NECESSARY_REBOOT=1
if grep -q "root=ZFS=" /proc/cmdline 2>/dev/null; then
cmdline_file="/etc/kernel/cmdline"
if [[ -f "$cmdline_file" ]] && grep -q "idle=nomwait" "$cmdline_file"; then
cp "$cmdline_file" "${cmdline_file}.bak.$(date +%Y%m%d_%H%M%S)" || {
msg_error "$(translate "Failed to backup $cmdline_file")"
return 1
}
pmx_edit_file "$cmdline_file" 's/\bidle=nomwait\b//g; s/[[:space:]]\+/ /g; s/^ //; s/ $//'
if command -v proxmox-boot-tool >/dev/null 2>&1; then
pmx_record_execution "Refresh Proxmox boot configuration" "proxmox-boot-tool refresh"
proxmox-boot-tool refresh >/dev/null 2>&1 || {
msg_error "$(translate "Failed to refresh boot configuration")"
return 1
}
fi
msg_ok "$(translate "Removed idle=nomwait from /etc/kernel/cmdline (ZFS)")"
fi
else
grub_file="/etc/default/grub"
if [[ -f "$grub_file" ]] && grep -q 'GRUB_CMDLINE_LINUX_DEFAULT=' "$grub_file"; then
if grep -q "idle=nomwait" "$grub_file"; then
cp "$grub_file" "${grub_file}.bak.$(date +%Y%m%d_%H%M%S)" || {
msg_error "$(translate "Failed to backup $grub_file")"
return 1
}
pmx_edit_file "$grub_file" -E 's/(GRUB_CMDLINE_LINUX_DEFAULT=")/\1/; s/\bidle=nomwait\b//g'
awk -F\" '
$1=="GRUB_CMDLINE_LINUX_DEFAULT=" {
gsub(/[[:space:]]+/," ",$2); sub(/^ /,"",$2); sub(/ $/,"",$2)
}1
' OFS="\"" "$grub_file" | pmx_write_file "$grub_file"
pmx_record_execution "Regenerate GRUB configuration" "update-grub"
update-grub >/dev/null 2>&1 || {
msg_error "$(translate "Failed to update GRUB configuration")"
return 1
}
msg_ok "$(translate "Removed idle=nomwait from GRUB configuration")"
fi
fi
fi
kvm_conf="/etc/modprobe.d/kvm.conf"
if [[ -f "$kvm_conf" ]]; then
if grep -Eq '(ignore_msrs|report_ignored_msrs)' "$kvm_conf"; then
cp "$kvm_conf" "${kvm_conf}.bak.$(date +%Y%m%d_%H%M%S)" || {
msg_error "$(translate "Failed to backup $kvm_conf")"
return 1
}
pmx_edit_file "$kvm_conf" -E '/ignore_msrs|report_ignored_msrs/d'
if [[ ! -s "$kvm_conf" ]]; then
pmx_remove_file "$kvm_conf"
msg_ok "$(translate "Removed empty KVM configuration file")"
else
msg_ok "$(translate "Removed KVM MSR options from configuration")"
fi
pmx_record_execution "Regenerate initramfs" "update-initramfs -u -k all"
update-initramfs -u -k all >/dev/null 2>&1 || true
pmx_record_execution "Refresh Proxmox boot configuration" "proxmox-boot-tool refresh"
proxmox-boot-tool refresh >/dev/null 2>&1 || true
else
msg_ok "$(translate "KVM MSR options not present, nothing to revert")"
fi
fi
msg_success "$(translate "AMD fixes have been successfully reverted")"
register_tool "amd_fixes" false
}
################################################################
migrate_installed_tools() {
if [[ -f "$TOOLS_JSON" ]]; then
return
fi
show_proxmenux_logo
msg_info "$(translate 'Detecting previous optimizations...')"
echo "{}" > "$TOOLS_JSON"
local updated=false
# APT configurations
if [[ -f /etc/apt/apt.conf.d/99-force-ipv4 ]]; then
jq '. + {"apt_ipv4": true}' "$TOOLS_JSON" > "$TOOLS_JSON.tmp" && mv "$TOOLS_JSON.tmp" "$TOOLS_JSON"
updated=true
fi
if [[ -f /etc/apt/apt.conf.d/99-disable-translations ]]; then
jq '. + {"apt_languages": true}' "$TOOLS_JSON" > "$TOOLS_JSON.tmp" && mv "$TOOLS_JSON.tmp" "$TOOLS_JSON"
updated=true
fi
# System configurations
if [[ -f /etc/sysctl.d/99-memory.conf ]]; then
jq '. + {"memory_settings": true}' "$TOOLS_JSON" > "$TOOLS_JSON.tmp" && mv "$TOOLS_JSON.tmp" "$TOOLS_JSON"
updated=true
fi
if [[ -f /etc/sysctl.d/99-network.conf ]]; then
jq '. + {"network_optimization": true}' "$TOOLS_JSON" > "$TOOLS_JSON.tmp" && mv "$TOOLS_JSON.tmp" "$TOOLS_JSON"
updated=true
fi
if [[ -f /etc/sysctl.d/99-kernelpanic.conf ]]; then
jq '. + {"kernel_panic": true}' "$TOOLS_JSON" > "$TOOLS_JSON.tmp" && mv "$TOOLS_JSON.tmp" "$TOOLS_JSON"
updated=true
fi
if [[ -f /etc/security/limits.d/99-limits.conf ]]; then
jq '. + {"system_limits": true}' "$TOOLS_JSON" > "$TOOLS_JSON.tmp" && mv "$TOOLS_JSON.tmp" "$TOOLS_JSON"
updated=true
fi
# Services
if systemctl is-active --quiet log2ram 2>/dev/null; then
jq '. + {"log2ram": true}' "$TOOLS_JSON" > "$TOOLS_JSON.tmp" && mv "$TOOLS_JSON.tmp" "$TOOLS_JSON"
updated=true
fi
if dpkg -l | grep -q haveged; then
jq '. + {"entropy": true}' "$TOOLS_JSON" > "$TOOLS_JSON.tmp" && mv "$TOOLS_JSON.tmp" "$TOOLS_JSON"
updated=true
fi
# Bashrc customization
if grep -q "# ProxMenux customizations" /root/.bashrc 2>/dev/null; then
jq '. + {"bashrc_custom": true}' "$TOOLS_JSON" > "$TOOLS_JSON.tmp" && mv "$TOOLS_JSON.tmp" "$TOOLS_JSON"
updated=true
fi
# Subscription banner
if [[ -f /etc/apt/apt.conf.d/no-nag-script ]]; then
jq '. + {"subscription_banner": true}' "$TOOLS_JSON" > "$TOOLS_JSON.tmp" && mv "$TOOLS_JSON.tmp" "$TOOLS_JSON"
updated=true
fi
if [[ "$updated" == true ]]; then
sleep 2
msg_ok "$(translate 'Optimizations detected and ready to revert.')"
sleep 1
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-squid.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() {
local FUNC_VERSION="1.0"
pmx_journal_context "uninstall_ha" "$FUNC_VERSION"
msg_info2 "$(translate 'Disabling High Availability services...')"
pmx_disable_service pve-ha-lrm || true
pmx_disable_service pve-ha-crm || true
pmx_disable_service corosync || 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() {
local FUNC_VERSION="1.0"
pmx_journal_context "uninstall_pigz" "$FUNC_VERSION"
msg_info2 "$(translate 'Reverting pigz wrapper...')"
if [[ -f /bin/gzip.original ]]; then
pmx_write_file /bin/gzip < /bin/gzip.original
pmx_remove_file /bin/gzip.original
msg_ok "$(translate 'Restored original /bin/gzip')"
fi
pmx_remove_file /bin/pigzwrapper
pmx_edit_file /etc/vzdump.conf 's/^pigz: 1/#pigz: 1/' 2>/dev/null || true
pmx_record_execution "Purge pigz package" "apt-get purge -y pigz"
apt-get purge -y pigz >/dev/null 2>&1 || true
msg_ok "$(translate 'pigz removed')"
register_tool "pigz" false
}
uninstall_zfs_arc() {
local backup_dir="$BASE_DIR/backups/zfs_arc"
local manifest="$backup_dir/manifest.tsv"
local remaining_manifest=""
local original backup post_hash current_hash
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
if [[ -s "$manifest" ]]; then
remaining_manifest=$(mktemp "${manifest}.XXXXXX") || remaining_manifest=""
while IFS=$'\t' read -r original backup post_hash; do
[[ -n "$original" && -n "$backup" ]] || continue
current_hash=""
if [[ -f "$original" ]]; then
current_hash=$(sha256sum "$original" 2>/dev/null | awk '{print $1}')
fi
if [[ ! -e "$original" || "$current_hash" == "$post_hash" ]]; then
if [[ -f "$backup" ]] && cp -p "$backup" "$original"; then
rm -f "$backup"
msg_ok "$(translate 'External ZFS ARC settings restored:') $original"
elif [[ -n "$remaining_manifest" ]]; then
printf '%s\t%s\t%s\n' "$original" "$backup" "$post_hash" >> "$remaining_manifest"
fi
else
msg_warn "$(translate 'External ZFS configuration changed after the ProxMenux migration; current file and backup preserved:') $original"
if [[ -n "$remaining_manifest" ]]; then
printf '%s\t%s\t%s\n' "$original" "$backup" "$post_hash" >> "$remaining_manifest"
fi
fi
done < "$manifest"
if [[ -n "$remaining_manifest" ]]; then
if [[ -s "$remaining_manifest" ]]; then
mv -f "$remaining_manifest" "$manifest"
else
rm -f "$remaining_manifest" "$manifest"
fi
fi
rmdir "$backup_dir" 2>/dev/null || true
rmdir "$BASE_DIR/backups" 2>/dev/null || true
fi
update-initramfs -u -k all >/dev/null 2>&1 || true
if command -v proxmox-boot-tool >/dev/null 2>&1; then
proxmox-boot-tool refresh >/dev/null 2>&1 || true
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_zfs_autotrim() {
local state_file="$BASE_DIR/zfs_autotrim_pools"
local pools=()
local pool
msg_info2 "$(translate 'Disabling ZFS autotrim applied by ProxMenux...')"
if ! command -v zpool >/dev/null 2>&1; then
msg_warn "$(translate 'ZFS not detected. Nothing to disable.')"
rm -f "$state_file"
register_tool "zfs_autotrim" false
return 0
fi
if [[ ! -s "$state_file" ]]; then
msg_warn "$(translate 'No ProxMenux ZFS autotrim state file found.')"
register_tool "zfs_autotrim" false
return 0
fi
mapfile -t pools < <(sort -u "$state_file")
for pool in "${pools[@]}"; do
if zpool list -H "$pool" >/dev/null 2>&1; then
if zpool set autotrim=off "$pool" >/dev/null 2>&1; then
msg_ok "$(translate 'ZFS autotrim disabled for pool:') $pool"
else
msg_warn "$(translate 'Failed to disable ZFS autotrim for pool:') $pool"
fi
else
msg_warn "$(translate 'ZFS pool not found:') $pool"
fi
done
rm -f "$state_file"
register_tool "zfs_autotrim" false
}
uninstall_vzdump_speed() {
local FUNC_VERSION="1.0"
pmx_journal_context "uninstall_vzdump_speed" "$FUNC_VERSION"
msg_info2 "$(translate 'Reverting vzdump speed tuning...')"
if [[ -f /etc/vzdump.conf.bak ]]; then
pmx_write_file /etc/vzdump.conf < /etc/vzdump.conf.bak
pmx_remove_file /etc/vzdump.conf.bak
msg_ok "$(translate 'Restored original /etc/vzdump.conf from .bak')"
else
pmx_edit_file /etc/vzdump.conf '/^bwlimit: 0$/d;/^ionice: 5$/d' 2>/dev/null
msg_ok "$(translate 'Removed bwlimit/ionice tuning (no .bak found)')"
fi
register_tool "vzdump_speed" false
}
################################################################
show_uninstall_menu() {
ensure_tools_json
migrate_installed_tools
mapfile -t tools_installed < <(jq -r 'to_entries | map(select(.value==true or .value.installed?==true)) | .[].key' "$TOOLS_JSON")
if [[ ${#tools_installed[@]} -eq 0 ]]; then
dialog --backtitle "ProxMenux" --title "ProxMenux" \
--msgbox "\n\n$(translate "No optimizations detected to uninstall.")" 10 60
return 0
fi
local menu_options=()
for tool in "${tools_installed[@]}"; do
case "$tool" in
subscription_banner) desc="Subscription Banner Removal";;
rpc) desc="RPC / rpcbind Disable";;
motd) desc="Custom MOTD Banner";;
system_utils) desc="System Utilities installed by ProxMenux";;
time_sync) desc="Time Synchronization";;
apt_languages) desc="APT Language Skip";;
journald) desc="Journald Optimization";;
logrotate) desc="Logrotate Optimization";;
system_limits) desc="System Limits Increase";;
entropy) desc="Entropy Generation (haveged)";;
memory_settings) desc="Memory Settings Optimization";;
kernel_panic) desc="Kernel Panic Configuration";;
apt_ipv4) desc="APT IPv4 Force";;
kexec) desc="kexec for quick reboots";;
network_optimization) desc="Network Optimizations";;
bashrc_custom) desc="Bashrc Customization";;
figurine) desc="Figurine";;
fastfetch) desc="Fastfetch";;
log2ram) desc="Log2ram (SSD Protection)";;
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";;
zfs_autotrim) desc="ZFS autotrim";;
vzdump_speed) desc="vzdump bwlimit/ionice tuning";;
*) desc="$tool";;
esac
menu_options+=("$tool" "$desc" "off")
done
selected_tools=$(dialog --backtitle "ProxMenux" \
--title "$(translate "Uninstall Optimizations")" \
--checklist "$(translate "Select optimizations to uninstall:")" 20 70 12 \
"${menu_options[@]}" 3>&1 1>&2 2>&3)
local dialog_result=$?
if [[ $dialog_result -ne 0 || -z "$selected_tools" ]]; then
return 0
fi
# Show confirmation
if ! dialog --backtitle "ProxMenux" \
--title "$(translate "Confirm Uninstallation")" \
--yesno "\n\n$(translate "Are you sure you want to uninstall the selected optimizations.")" 10 60; then
return 0
fi
# Execute uninstallations
for tool in $selected_tools; do
tool=$(echo "$tool" | tr -d '"')
if declare -f "uninstall_$tool" > /dev/null 2>&1; then
clear
show_proxmenux_logo
"uninstall_$tool"
else
msg_warn "$(translate "No uninstaller found for:") $tool"
fi
done
msg_success "$(translate "Selected optimizations have been uninstalled.")"
msg_warn "$(translate "A system reboot is recommended to ensure all changes take effect.")"
echo -e
msg_success "$(translate "Press Enter to continue...")"
read -r
if dialog --backtitle "ProxMenux" \
--title "$(translate "Reboot Recommended")" \
--yesno "$(translate "Do you want to reboot now?")" 8 50; then
reboot
fi
}
################################################################
show_uninstall_menu