new script post-install automated

This commit is contained in:
MacRimi 2025-07-06 12:21:29 +02:00
parent 707b6a6f1b
commit 48b545d731
5 changed files with 6021 additions and 81 deletions

View File

@ -0,0 +1,854 @@
#!/bin/bash
# ==========================================================
# ProxMenux - Complete Post-Installation Script with Registration
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : MIT (https://raw.githubusercontent.com/MacRimi/ProxMenux/main/LICENSE)
# Version : 1.0
# Last Updated: 06/07/2025
# ==========================================================
# Description:
#
# 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
#
# 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
# ==========================================================
# Configuration
REPO_URL="https://raw.githubusercontent.com/MacRimi/ProxMenux/main"
BASE_DIR="/usr/local/share/proxmenux"
UTILS_FILE="$BASE_DIR/utils.sh"
VENV_PATH="/opt/googletrans-env"
TOOLS_JSON="/usr/local/share/proxmenux/installed_tools.json"
if [[ -f "$UTILS_FILE" ]]; then
source "$UTILS_FILE"
fi
load_language
initialize_cache
# Global variables
OS_CODENAME="$(grep "VERSION_CODENAME=" /etc/os-release | cut -d"=" -f 2 | xargs)"
RAM_SIZE_GB=$(( $(vmstat -s | grep -i "total memory" | xargs | cut -d" " -f 1) / 1024 / 1000))
NECESSARY_REBOOT=0
SCRIPT_TITLE="Customizable post-installation optimization script"
# ==========================================================
# 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"
}
# ==========================================================
lvm_repair_check() {
msg_info "$(translate "Checking and repairing old LVM PV headers (if needed)...")"
pvs_output=$(LC_ALL=C pvs -v 2>&1 | grep "old PV header")
if [ -z "$pvs_output" ]; then
msg_ok "$(translate "No PVs with old headers found.")"
register_tool "lvm_repair" true
return
fi
declare -A vg_map
while read -r line; do
pv=$(echo "$line" | grep -o '/dev/[^ ]*')
vg=$(pvs -o vg_name --noheadings "$pv" | awk '{print $1}')
if [ -n "$vg" ]; then
vg_map["$vg"]=1
fi
done <<< "$pvs_output"
for vg in "${!vg_map[@]}"; do
msg_warn "$(translate "Old PV header(s) found in VG $vg. Updating metadata...")"
vgck --updatemetadata "$vg"
vgchange -ay "$vg"
if [ $? -ne 0 ]; then
msg_warn "$(translate "Metadata update failed for VG $vg. Review manually.")"
else
msg_ok "$(translate "Metadata updated successfully for VG $vg")"
fi
done
msg_ok "$(translate "LVM PV headers check completed")"
}
# ==========================================================
cleanup_duplicate_repos() {
local sources_file="/etc/apt/sources.list"
local temp_file=$(mktemp)
local cleaned_count=0
declare -A seen_repos
while IFS= read -r line || [[ -n "$line" ]]; do
if [[ "$line" =~ ^[[:space:]]*# ]] || [[ -z "$line" ]]; then
echo "$line" >> "$temp_file"
continue
fi
if [[ "$line" =~ ^deb ]]; then
read -r _ url dist components <<< "$line"
local key="${url}_${dist}"
if [[ -v "seen_repos[$key]" ]]; then
echo "# $line" >> "$temp_file"
cleaned_count=$((cleaned_count + 1))
else
echo "$line" >> "$temp_file"
seen_repos[$key]="$components"
fi
else
echo "$line" >> "$temp_file"
fi
done < "$sources_file"
mv "$temp_file" "$sources_file"
chmod 644 "$sources_file"
local pve_files=(/etc/apt/sources.list.d/*proxmox*.list /etc/apt/sources.list.d/*pve*.list)
local pve_content="deb http://download.proxmox.com/debian/pve ${OS_CODENAME} pve-no-subscription"
local pve_public_repo="/etc/apt/sources.list.d/pve-public-repo.list"
local pve_public_repo_exists=false
if [ -f "$pve_public_repo" ] && grep -q "^deb.*pve-no-subscription" "$pve_public_repo"; then
pve_public_repo_exists=true
fi
for file in "${pve_files[@]}"; do
if [ -f "$file" ] && grep -q "^deb.*pve-no-subscription" "$file"; then
if ! $pve_public_repo_exists && [[ "$file" == "$pve_public_repo" ]]; then
sed -i 's/^# *deb/deb/' "$file"
pve_public_repo_exists=true
elif [[ "$file" != "$pve_public_repo" ]]; then
sed -i 's/^deb/# deb/' "$file"
cleaned_count=$((cleaned_count + 1))
fi
fi
done
apt update
}
apt_upgrade() {
NECESSARY_REBOOT=1
if [ -f /etc/apt/sources.list.d/pve-enterprise.list ] && grep -q "^deb" /etc/apt/sources.list.d/pve-enterprise.list; then
msg_info "$(translate "Disabling enterprise Proxmox repository...")"
sed -i "s/^deb/#deb/g" /etc/apt/sources.list.d/pve-enterprise.list
msg_ok "$(translate "Enterprise Proxmox repository disabled")"
fi
if [ -f /etc/apt/sources.list.d/ceph.list ] && grep -q "^deb" /etc/apt/sources.list.d/ceph.list; then
msg_info "$(translate "Disabling enterprise Proxmox Ceph repository...")"
sed -i "s/^deb/#deb/g" /etc/apt/sources.list.d/ceph.list
msg_ok "$(translate "Enterprise Proxmox Ceph repository disabled")"
fi
if [ ! -f /etc/apt/sources.list.d/pve-public-repo.list ] || ! grep -q "pve-no-subscription" /etc/apt/sources.list.d/pve-public-repo.list; then
msg_info "$(translate "Enabling free public Proxmox repository...")"
echo "deb http://download.proxmox.com/debian/pve ${OS_CODENAME} pve-no-subscription" > /etc/apt/sources.list.d/pve-public-repo.list
msg_ok "$(translate "Free public Proxmox repository enabled")"
fi
sources_file="/etc/apt/sources.list"
need_update=false
sed -i 's|ftp.es.debian.org|deb.debian.org|g' "$sources_file"
if grep -q "^deb http://security.debian.org ${OS_CODENAME}-security main contrib" "$sources_file"; then
sed -i "s|^deb http://security.debian.org ${OS_CODENAME}-security main contrib|deb http://security.debian.org/debian-security ${OS_CODENAME}-security main contrib non-free non-free-firmware|" "$sources_file"
msg_ok "$(translate "Replaced security repository with full version")"
need_update=true
fi
if ! grep -q "deb http://security.debian.org/debian-security ${OS_CODENAME}-security" "$sources_file"; then
echo "deb http://security.debian.org/debian-security ${OS_CODENAME}-security main contrib non-free non-free-firmware" >> "$sources_file"
need_update=true
fi
if ! grep -q "deb http://deb.debian.org/debian ${OS_CODENAME} " "$sources_file"; then
echo "deb http://deb.debian.org/debian ${OS_CODENAME} main contrib non-free non-free-firmware" >> "$sources_file"
need_update=true
fi
if ! grep -q "deb http://deb.debian.org/debian ${OS_CODENAME}-updates" "$sources_file"; then
echo "deb http://deb.debian.org/debian ${OS_CODENAME}-updates main contrib non-free non-free-firmware" >> "$sources_file"
need_update=true
fi
msg_ok "$(translate "Debian repositories configured correctly")"
# ===================================================
if [ ! -f /etc/apt/apt.conf.d/no-bookworm-firmware.conf ]; then
msg_info "$(translate "Disabling non-free firmware warnings...")"
echo 'APT::Get::Update::SourceListWarnings::NonFreeFirmware "false";' > /etc/apt/apt.conf.d/no-bookworm-firmware.conf
msg_ok "$(translate "Non-free firmware warnings disabled")"
fi
msg_info "$(translate "Updating package lists...")"
if apt-get update > /dev/null 2>&1; then
msg_ok "$(translate "Package lists updated")"
else
msg_error "$(translate "Failed to update package lists")"
return 1
fi
msg_info "$(translate "Removing conflicting utilities...")"
if /usr/bin/env DEBIAN_FRONTEND=noninteractive apt-get -y -o Dpkg::Options::='--force-confdef' purge ntp openntpd systemd-timesyncd > /dev/null 2>&1; then
msg_ok "$(translate "Conflicting utilities removed")"
else
msg_error "$(translate "Failed to remove conflicting utilities")"
fi
msg_info "$(translate "Performing packages upgrade...")"
apt-get install pv -y > /dev/null 2>&1
total_packages=$(apt-get -s dist-upgrade | grep "^Inst" | wc -l)
if [ "$total_packages" -eq 0 ]; then
total_packages=1
fi
msg_ok "$(translate "Packages upgrade successfull")"
tput civis
tput sc
(
/usr/bin/env DEBIAN_FRONTEND=noninteractive apt-get -y -o Dpkg::Options::='--force-confdef' dist-upgrade 2>&1 | \
while IFS= read -r line; do
if [[ "$line" =~ ^(Setting up|Unpacking|Preparing to unpack|Processing triggers for) ]]; then
package_name=$(echo "$line" | sed -E 's/.*(Setting up|Unpacking|Preparing to unpack|Processing triggers for) ([^ ]+).*/\2/')
[ -z "$package_name" ] && package_name="$(translate "Unknown")"
tput rc
tput ed
row=$(( $(tput lines) - 6 ))
tput cup $row 0; echo "$(translate "Installing packages...")"
tput cup $((row + 1)) 0; echo "──────────────────────────────────────────────"
tput cup $((row + 2)) 0; echo "Package: $package_name"
tput cup $((row + 3)) 0; echo "Progress: [ ] 0%"
tput cup $((row + 4)) 0; echo "──────────────────────────────────────────────"
for i in $(seq 1 10); do
progress=$((i * 10))
tput cup $((row + 3)) 9
printf "[%-50s] %3d%%" "$(printf "#%.0s" $(seq 1 $((progress/2))))" "$progress"
done
fi
done
)
if [ $? -eq 0 ]; then
tput rc
tput ed
msg_ok "$(translate "System upgrade completed")"
fi
msg_info "$(translate "Installing additional Proxmox packages...")"
if /usr/bin/env DEBIAN_FRONTEND=noninteractive apt-get -y -o Dpkg::Options::='--force-confdef' install zfsutils-linux proxmox-backup-restore-image chrony > /dev/null 2>&1; then
msg_ok "$(translate "Additional Proxmox packages installed")"
else
msg_error "$(translate "Failed to install additional Proxmox packages")"
fi
lvm_repair_check
cleanup_duplicate_repos
msg_ok "$(translate "Proxmox update completed")"
}
# ==========================================================
remove_subscription_banner() {
msg_info "$(translate "Removing Proxmox subscription nag banner...")"
local JS_FILE="/usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js"
local GZ_FILE="/usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js.gz"
local APT_HOOK="/etc/apt/apt.conf.d/no-nag-script"
if [[ ! -f "$APT_HOOK" ]]; then
cat <<'EOF' > "$APT_HOOK"
DPkg::Post-Invoke { "dpkg -V proxmox-widget-toolkit | grep -q '/proxmoxlib\.js$'; if [ $? -eq 1 ]; then { echo 'Removing subscription nag from UI...'; sed -i '/.*data\.status.*{/{s/\!//;s/active/NoMoreNagging/;s/Active/NoMoreNagging/}' /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js; rm -f /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js.gz; }; fi"; };
EOF
fi
if [[ -f "$JS_FILE" ]]; then
sed -i '/.*data\.status.*{/{s/\!//;s/active/NoMoreNagging/;s/Active/NoMoreNagging/}' "$JS_FILE"
[[ -f "$GZ_FILE" ]] && rm -f "$GZ_FILE"
touch "$JS_FILE"
fi
apt --reinstall install proxmox-widget-toolkit -y > /dev/null 2>&1
msg_ok "$(translate "Subscription nag banner removed successfully")"
register_tool "subscription_banner" true
}
# ==========================================================
configure_time_sync() {
msg_info "$(translate "Configuring system time settings...")"
this_ip=$(dig +short myip.opendns.com @resolver1.opendns.com)
if [ -z "$this_ip" ]; then
msg_warn "$(translate "Failed to obtain public IP address")"
timezone="UTC"
else
timezone=$(curl -s "https://ipapi.co/${this_ip}/timezone")
if [ -z "$timezone" ]; then
msg_warn "$(translate "Failed to determine timezone from IP address")"
timezone="UTC"
else
msg_ok "$(translate "Found timezone $timezone for IP $this_ip")"
fi
fi
msg_info "$(translate "Enabling automatic time synchronization...")"
if timedatectl set-ntp true; then
msg_ok "$(translate "Time settings configured - Timezone:") $timezone"
register_tool "time_sync" true
else
msg_error "$(translate "Failed to enable automatic time synchronization")"
fi
}
# ==========================================================
skip_apt_languages() {
msg_info "$(translate "Configuring APT to skip downloading additional languages...")"
local default_locale=""
if [ -f /etc/default/locale ]; then
default_locale=$(grep '^LANG=' /etc/default/locale | cut -d= -f2 | tr -d '"')
elif [ -f /etc/environment ]; then
default_locale=$(grep '^LANG=' /etc/environment | cut -d= -f2 | tr -d '"')
fi
default_locale="${default_locale:-en_US.UTF-8}"
local normalized_locale=$(echo "$default_locale" | tr 'A-Z' 'a-z' | sed 's/utf-8/utf8/;s/-/_/')
if ! locale -a | grep -qi "^$normalized_locale$"; then
if ! grep -qE "^${default_locale}[[:space:]]+UTF-8" /etc/locale.gen; then
echo "$default_locale UTF-8" >> /etc/locale.gen
fi
locale-gen "$default_locale" > /dev/null 2>&1
fi
echo 'Acquire::Languages "none";' > /etc/apt/apt.conf.d/99-disable-translations
msg_ok "$(translate "APT configured to skip additional languages")"
register_tool "apt_languages" true
}
# ==========================================================
optimize_journald() {
msg_info "$(translate "Limiting size and optimizing journald...")"
NECESSARY_REBOOT=1
cat <<EOF > /etc/systemd/journald.conf
[Journal]
Storage=persistent
SplitMode=none
RateLimitInterval=0
RateLimitIntervalSec=0
RateLimitBurst=0
ForwardToSyslog=no
ForwardToWall=yes
Seal=no
Compress=yes
SystemMaxUse=64M
RuntimeMaxUse=60M
MaxLevelStore=warning
MaxLevelSyslog=warning
MaxLevelKMsg=warning
MaxLevelConsole=notice
MaxLevelWall=crit
EOF
systemctl restart systemd-journald.service > /dev/null 2>&1
journalctl --vacuum-size=64M --vacuum-time=1d > /dev/null 2>&1
journalctl --rotate > /dev/null 2>&1
msg_ok "$(translate "Journald optimized - Max size: 64M")"
register_tool "journald" true
}
# ==========================================================
optimize_logrotate() {
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"
# ProxMenux optimized configuration
daily
su root adm
rotate 7
create
compress
size=10M
delaycompress
copytruncate
include /etc/logrotate.d
EOF
systemctl restart logrotate > /dev/null 2>&1
fi
msg_ok "$(translate "Logrotate optimization completed")"
register_tool "logrotate" true
}
# ==========================================================
increase_system_limits() {
msg_info "$(translate "Increasing various system limits...")"
NECESSARY_REBOOT=1
cat > /etc/sysctl.d/99-maxwatches.conf << EOF
# ProxMenux configuration
fs.inotify.max_user_watches = 1048576
fs.inotify.max_user_instances = 1048576
fs.inotify.max_queued_events = 1048576
EOF
cat > /etc/security/limits.d/99-limits.conf << EOF
# ProxMenux configuration
* soft nproc 1048576
* hard nproc 1048576
* soft nofile 1048576
* hard nofile 1048576
root soft nproc unlimited
root hard nproc unlimited
root soft nofile unlimited
root hard nofile unlimited
EOF
cat > /etc/sysctl.d/99-maxkeys.conf << EOF
# ProxMenux configuration
kernel.keys.root_maxkeys=1000000
kernel.keys.maxkeys=1000000
EOF
for file in /etc/systemd/system.conf /etc/systemd/user.conf; do
if ! grep -q "^DefaultLimitNOFILE=" "$file"; then
echo "DefaultLimitNOFILE=256000" >> "$file"
fi
done
for file in /etc/pam.d/common-session /etc/pam.d/runuser-l; do
if ! grep -q "^session required pam_limits.so" "$file"; then
echo 'session required pam_limits.so' >> "$file"
fi
done
if ! grep -q "ulimit -n 256000" /root/.profile; then
echo "ulimit -n 256000" >> /root/.profile
fi
cat > /etc/sysctl.d/99-swap.conf << EOF
# ProxMenux configuration
vm.swappiness = 10
vm.vfs_cache_pressure = 100
EOF
cat > /etc/sysctl.d/99-fs.conf << EOF
# ProxMenux configuration
fs.nr_open = 12000000
fs.file-max = 9223372036854775807
fs.aio-max-nr = 1048576
EOF
msg_ok "$(translate "System limits increase completed.")"
register_tool "system_limits" true
}
# ==========================================================
configure_entropy() {
msg_info "$(translate "Configuring entropy generation to prevent slowdowns...")"
/usr/bin/env DEBIAN_FRONTEND=noninteractive apt-get -y -o Dpkg::Options::='--force-confdef' install haveged > /dev/null 2>&1
cat <<EOF > /etc/default/haveged
# -w sets low entropy watermark (in bits)
DAEMON_ARGS="-w 1024"
EOF
systemctl daemon-reload > /dev/null 2>&1
systemctl enable haveged > /dev/null 2>&1
msg_ok "$(translate "Entropy generation configuration completed")"
register_tool "entropy" true
}
# ==========================================================
optimize_memory_settings() {
msg_info "$(translate "Optimizing memory settings...")"
NECESSARY_REBOOT=1
cat <<EOF > /etc/sysctl.d/99-memory.conf
# Balanced Memory Optimization
vm.swappiness = 10
vm.dirty_ratio = 15
vm.dirty_background_ratio = 5
vm.overcommit_memory = 1
vm.max_map_count = 65530
EOF
if [ -f /proc/sys/vm/compaction_proactiveness ]; then
echo "vm.compaction_proactiveness = 20" >> /etc/sysctl.d/99-memory.conf
fi
msg_ok "$(translate "Memory optimization completed.")"
register_tool "memory_settings" true
}
# ==========================================================
configure_kernel_panic() {
msg_info "$(translate "Configuring kernel panic behavior")"
NECESSARY_REBOOT=1
cat <<EOF > /etc/sysctl.d/99-kernelpanic.conf
# Enable restart on kernel panic, kernel oops and hardlockup
kernel.core_pattern = /var/crash/core.%t.%p
kernel.panic = 10
kernel.panic_on_oops = 1
kernel.hardlockup_panic = 1
EOF
msg_ok "$(translate "Kernel panic behavior configuration completed")"
register_tool "kernel_panic" true
}
# ==========================================================
force_apt_ipv4() {
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
}
# ==========================================================
apply_network_optimizations() {
msg_info "$(translate "Optimizing network settings...")"
NECESSARY_REBOOT=1
cat <<EOF > /etc/sysctl.d/99-network.conf
net.core.netdev_max_backlog=8192
net.core.optmem_max=8192
net.core.rmem_max=16777216
net.core.somaxconn=8151
net.core.wmem_max=16777216
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.all.log_martians = 0
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv4.conf.default.log_martians = 0
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.default.secure_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.icmp_ignore_bogus_error_responses = 1
net.ipv4.ip_local_port_range=1024 65535
net.ipv4.tcp_base_mss = 1024
net.ipv4.tcp_challenge_ack_limit = 999999999
net.ipv4.tcp_fin_timeout=10
net.ipv4.tcp_keepalive_intvl=30
net.ipv4.tcp_keepalive_probes=3
net.ipv4.tcp_keepalive_time=240
net.ipv4.tcp_limit_output_bytes=65536
net.ipv4.tcp_max_syn_backlog=8192
net.ipv4.tcp_max_tw_buckets = 1440000
net.ipv4.tcp_mtu_probing = 1
net.ipv4.tcp_rfc1337=1
net.ipv4.tcp_rmem=8192 87380 16777216
net.ipv4.tcp_sack=1
net.ipv4.tcp_slow_start_after_idle=0
net.ipv4.tcp_syn_retries=3
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_tw_recycle = 0
net.ipv4.tcp_tw_reuse = 0
net.ipv4.tcp_wmem=8192 65536 16777216
net.netfilter.nf_conntrack_generic_timeout = 60
net.netfilter.nf_conntrack_helper=0
net.netfilter.nf_conntrack_max = 524288
net.netfilter.nf_conntrack_tcp_timeout_established = 28800
net.unix.max_dgram_qlen = 4096
EOF
sysctl --system > /dev/null 2>&1
local interfaces_file="/etc/network/interfaces"
if ! grep -q 'source /etc/network/interfaces.d/*' "$interfaces_file"; then
echo "source /etc/network/interfaces.d/*" >> "$interfaces_file"
fi
msg_ok "$(translate "Network optimization completed")"
register_tool "network_optimization" true
}
# ==========================================================
disable_rpc() {
msg_info "$(translate "Disabling portmapper/rpcbind for security...")"
systemctl disable rpcbind > /dev/null 2>&1
systemctl stop rpcbind > /dev/null 2>&1
msg_ok "$(translate "portmapper/rpcbind has been disabled and removed")"
register_tool "disable_rpc" true
}
# ==========================================================
customize_bashrc() {
msg_info "$(translate "Customizing bashrc for root user...")"
local bashrc="/root/.bashrc"
local bash_profile="/root/.bash_profile"
if [ ! -f "${bashrc}.bak" ]; then
cp "$bashrc" "${bashrc}.bak"
fi
cat >> "$bashrc" << 'EOF'
# ProxMenux customizations
export HISTTIMEFORMAT="%d/%m/%y %T "
export PS1="\[\e[31m\][\[\e[m\]\[\e[38;5;172m\]\u\[\e[m\]@\[\e[38;5;153m\]\h\[\e[m\] \[\e[38;5;214m\]\W\[\e[m\]\[\e[31m\]]\[\e[m\]\\$ "
alias l='ls -CF'
alias la='ls -A'
alias ll='ls -alF'
alias ls='ls --color=auto'
alias grep='grep --color=auto'
alias fgrep='fgrep --color=auto'
alias egrep='egrep --color=auto'
source /etc/profile.d/bash_completion.sh
EOF
if ! grep -q "source /root/.bashrc" "$bash_profile"; then
echo "source /root/.bashrc" >> "$bash_profile"
fi
msg_ok "$(translate "Bashrc customization completed")"
register_tool "bashrc_custom" true
}
# ==========================================================
install_log2ram_auto() {
msg_info2 "$(translate "Checking if system disk is SSD or M.2...")"
ROOT_PART=$(lsblk -no NAME,MOUNTPOINT | grep ' /$' | awk '{print $1}')
SYSTEM_DISK=$(lsblk -no PKNAME /dev/$ROOT_PART 2>/dev/null)
SYSTEM_DISK=${SYSTEM_DISK:-sda}
if [[ "$SYSTEM_DISK" == nvme* || "$(cat /sys/block/$SYSTEM_DISK/queue/rotational 2>/dev/null)" == "0" ]]; then
msg_ok "$(translate "System disk ($SYSTEM_DISK) is SSD or M.2. Proceeding with log2ram setup.")"
else
msg_warn "$(translate "System disk ($SYSTEM_DISK) is not SSD/M.2. Skipping log2ram installation.")"
return 0
fi
# Clean up previous state
rm -rf /tmp/log2ram
rm -f /etc/systemd/system/log2ram*
rm -f /etc/systemd/system/log2ram-daily.*
rm -f /etc/cron.d/log2ram*
rm -f /usr/sbin/log2ram
rm -f /etc/log2ram.conf
rm -f /usr/local/bin/log2ram-check.sh
rm -rf /var/log.hdd
systemctl daemon-reexec >/dev/null 2>&1
systemctl daemon-reload >/dev/null 2>&1
msg_info "$(translate "Installing log2ram from GitHub...")"
git clone https://github.com/azlux/log2ram.git /tmp/log2ram >/dev/null 2>>/tmp/log2ram_install.log
cd /tmp/log2ram || return 1
bash install.sh >>/tmp/log2ram_install.log 2>&1
if [[ -f /etc/log2ram.conf ]] && systemctl list-units --all | grep -q log2ram; then
msg_ok "$(translate "log2ram installed successfully")"
else
msg_error "$(translate "Failed to install log2ram. See /tmp/log2ram_install.log")"
return 1
fi
# Detect RAM
RAM_SIZE_GB=$(free -g | awk '/^Mem:/{print $2}')
[[ -z "$RAM_SIZE_GB" || "$RAM_SIZE_GB" -eq 0 ]] && RAM_SIZE_GB=4
if (( RAM_SIZE_GB <= 8 )); then
LOG2RAM_SIZE="128M"
CRON_HOURS=1
elif (( RAM_SIZE_GB <= 16 )); then
LOG2RAM_SIZE="256M"
CRON_HOURS=3
else
LOG2RAM_SIZE="512M"
CRON_HOURS=6
fi
msg_ok "$(translate "Detected RAM:") $RAM_SIZE_GB GB — $(translate "log2ram size set to:") $LOG2RAM_SIZE"
sed -i "s/^SIZE=.*/SIZE=$LOG2RAM_SIZE/" /etc/log2ram.conf
rm -f /etc/cron.hourly/log2ram
echo "0 */$CRON_HOURS * * * root /usr/sbin/log2ram write" > /etc/cron.d/log2ram
msg_ok "$(translate "log2ram write scheduled every") $CRON_HOURS $(translate "hour(s)")"
cat << 'EOF' > /usr/local/bin/log2ram-check.sh
#!/bin/bash
CONF_FILE="/etc/log2ram.conf"
LIMIT_KB=$(grep '^SIZE=' "$CONF_FILE" | cut -d'=' -f2 | tr -d 'M')000
USED_KB=$(df /var/log --output=used | tail -1)
THRESHOLD=$(( LIMIT_KB * 90 / 100 ))
if (( USED_KB > THRESHOLD )); then
/usr/sbin/log2ram write
fi
EOF
chmod +x /usr/local/bin/log2ram-check.sh
echo "*/5 * * * * root /usr/local/bin/log2ram-check.sh" > /etc/cron.d/log2ram-auto-sync
msg_ok "$(translate "Auto-sync enabled when /var/log exceeds 90% of") $LOG2RAM_SIZE"
register_tool "log2ram" true
}
# ==========================================================
run_complete_optimization() {
clear
show_proxmenux_logo
msg_title "$(translate "ProxMenux Optimization Post-Installation")"
ensure_tools_json
apt_upgrade
remove_subscription_banner
configure_time_sync
skip_apt_languages
optimize_journald
optimize_logrotate
increase_system_limits
configure_entropy
optimize_memory_settings
configure_kernel_panic
force_apt_ipv4
apply_network_optimizations
disable_rpc
customize_bashrc
install_log2ram_auto
echo -e
msg_success "$(translate "Complete post-installation optimization finished!")"
if [[ "$NECESSARY_REBOOT" -eq 1 ]]; then
whiptail --title "Reboot Required" \
--yesno "$(translate "Some changes require a reboot to take effect. Do you want to restart now?")" 10 60
if [[ $? -eq 0 ]]; then
msg_info "$(translate "Removing no longer required packages and purging old cached updates...")"
apt-get -y autoremove >/dev/null 2>&1
apt-get -y autoclean >/dev/null 2>&1
msg_ok "$(translate "Cleanup finished")"
msg_success "$(translate "Press Enter to continue...")"
read -r
msg_warn "$(translate "Rebooting the system...")"
reboot
else
msg_info "$(translate "Removing no longer required packages and purging old cached updates...")"
apt-get -y autoremove >/dev/null 2>&1
apt-get -y autoclean >/dev/null 2>&1
msg_ok "$(translate "Cleanup finished")"
msg_info2 "$(translate "You can reboot later manually.")"
msg_success "$(translate "Press Enter to continue...")"
read -r
exit 0
fi
fi
msg_success "$(translate "All changes applied. No reboot required.")"
msg_success "$(translate "Press Enter to return to menu...")"
read -r
clear
}
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
run_complete_optimization
fi

View File

@ -0,0 +1,854 @@
#!/bin/bash
# ==========================================================
# ProxMenux - Complete Post-Installation Script with Registration
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : MIT (https://raw.githubusercontent.com/MacRimi/ProxMenux/main/LICENSE)
# Version : 1.0
# Last Updated: 06/07/2025
# ==========================================================
# Description:
#
# 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
#
# 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
# ==========================================================
# Configuration
REPO_URL="https://raw.githubusercontent.com/MacRimi/ProxMenux/main"
BASE_DIR="/usr/local/share/proxmenux"
UTILS_FILE="$BASE_DIR/utils.sh"
VENV_PATH="/opt/googletrans-env"
TOOLS_JSON="/usr/local/share/proxmenux/installed_tools.json"
if [[ -f "$UTILS_FILE" ]]; then
source "$UTILS_FILE"
fi
load_language
initialize_cache
# Global variables
OS_CODENAME="$(grep "VERSION_CODENAME=" /etc/os-release | cut -d"=" -f 2 | xargs)"
RAM_SIZE_GB=$(( $(vmstat -s | grep -i "total memory" | xargs | cut -d" " -f 1) / 1024 / 1000))
NECESSARY_REBOOT=0
SCRIPT_TITLE="Customizable post-installation optimization script"
# ==========================================================
# 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"
}
# ==========================================================
lvm_repair_check() {
msg_info "$(translate "Checking and repairing old LVM PV headers (if needed)...")"
pvs_output=$(LC_ALL=C pvs -v 2>&1 | grep "old PV header")
if [ -z "$pvs_output" ]; then
msg_ok "$(translate "No PVs with old headers found.")"
register_tool "lvm_repair" true
return
fi
declare -A vg_map
while read -r line; do
pv=$(echo "$line" | grep -o '/dev/[^ ]*')
vg=$(pvs -o vg_name --noheadings "$pv" | awk '{print $1}')
if [ -n "$vg" ]; then
vg_map["$vg"]=1
fi
done <<< "$pvs_output"
for vg in "${!vg_map[@]}"; do
msg_warn "$(translate "Old PV header(s) found in VG $vg. Updating metadata...")"
vgck --updatemetadata "$vg"
vgchange -ay "$vg"
if [ $? -ne 0 ]; then
msg_warn "$(translate "Metadata update failed for VG $vg. Review manually.")"
else
msg_ok "$(translate "Metadata updated successfully for VG $vg")"
fi
done
msg_ok "$(translate "LVM PV headers check completed")"
}
# ==========================================================
cleanup_duplicate_repos() {
local sources_file="/etc/apt/sources.list"
local temp_file=$(mktemp)
local cleaned_count=0
declare -A seen_repos
while IFS= read -r line || [[ -n "$line" ]]; do
if [[ "$line" =~ ^[[:space:]]*# ]] || [[ -z "$line" ]]; then
echo "$line" >> "$temp_file"
continue
fi
if [[ "$line" =~ ^deb ]]; then
read -r _ url dist components <<< "$line"
local key="${url}_${dist}"
if [[ -v "seen_repos[$key]" ]]; then
echo "# $line" >> "$temp_file"
cleaned_count=$((cleaned_count + 1))
else
echo "$line" >> "$temp_file"
seen_repos[$key]="$components"
fi
else
echo "$line" >> "$temp_file"
fi
done < "$sources_file"
mv "$temp_file" "$sources_file"
chmod 644 "$sources_file"
local pve_files=(/etc/apt/sources.list.d/*proxmox*.list /etc/apt/sources.list.d/*pve*.list)
local pve_content="deb http://download.proxmox.com/debian/pve ${OS_CODENAME} pve-no-subscription"
local pve_public_repo="/etc/apt/sources.list.d/pve-public-repo.list"
local pve_public_repo_exists=false
if [ -f "$pve_public_repo" ] && grep -q "^deb.*pve-no-subscription" "$pve_public_repo"; then
pve_public_repo_exists=true
fi
for file in "${pve_files[@]}"; do
if [ -f "$file" ] && grep -q "^deb.*pve-no-subscription" "$file"; then
if ! $pve_public_repo_exists && [[ "$file" == "$pve_public_repo" ]]; then
sed -i 's/^# *deb/deb/' "$file"
pve_public_repo_exists=true
elif [[ "$file" != "$pve_public_repo" ]]; then
sed -i 's/^deb/# deb/' "$file"
cleaned_count=$((cleaned_count + 1))
fi
fi
done
apt update
}
apt_upgrade() {
NECESSARY_REBOOT=1
if [ -f /etc/apt/sources.list.d/pve-enterprise.list ] && grep -q "^deb" /etc/apt/sources.list.d/pve-enterprise.list; then
msg_info "$(translate "Disabling enterprise Proxmox repository...")"
sed -i "s/^deb/#deb/g" /etc/apt/sources.list.d/pve-enterprise.list
msg_ok "$(translate "Enterprise Proxmox repository disabled")"
fi
if [ -f /etc/apt/sources.list.d/ceph.list ] && grep -q "^deb" /etc/apt/sources.list.d/ceph.list; then
msg_info "$(translate "Disabling enterprise Proxmox Ceph repository...")"
sed -i "s/^deb/#deb/g" /etc/apt/sources.list.d/ceph.list
msg_ok "$(translate "Enterprise Proxmox Ceph repository disabled")"
fi
if [ ! -f /etc/apt/sources.list.d/pve-public-repo.list ] || ! grep -q "pve-no-subscription" /etc/apt/sources.list.d/pve-public-repo.list; then
msg_info "$(translate "Enabling free public Proxmox repository...")"
echo "deb http://download.proxmox.com/debian/pve ${OS_CODENAME} pve-no-subscription" > /etc/apt/sources.list.d/pve-public-repo.list
msg_ok "$(translate "Free public Proxmox repository enabled")"
fi
sources_file="/etc/apt/sources.list"
need_update=false
sed -i 's|ftp.es.debian.org|deb.debian.org|g' "$sources_file"
if grep -q "^deb http://security.debian.org ${OS_CODENAME}-security main contrib" "$sources_file"; then
sed -i "s|^deb http://security.debian.org ${OS_CODENAME}-security main contrib|deb http://security.debian.org/debian-security ${OS_CODENAME}-security main contrib non-free non-free-firmware|" "$sources_file"
msg_ok "$(translate "Replaced security repository with full version")"
need_update=true
fi
if ! grep -q "deb http://security.debian.org/debian-security ${OS_CODENAME}-security" "$sources_file"; then
echo "deb http://security.debian.org/debian-security ${OS_CODENAME}-security main contrib non-free non-free-firmware" >> "$sources_file"
need_update=true
fi
if ! grep -q "deb http://deb.debian.org/debian ${OS_CODENAME} " "$sources_file"; then
echo "deb http://deb.debian.org/debian ${OS_CODENAME} main contrib non-free non-free-firmware" >> "$sources_file"
need_update=true
fi
if ! grep -q "deb http://deb.debian.org/debian ${OS_CODENAME}-updates" "$sources_file"; then
echo "deb http://deb.debian.org/debian ${OS_CODENAME}-updates main contrib non-free non-free-firmware" >> "$sources_file"
need_update=true
fi
msg_ok "$(translate "Debian repositories configured correctly")"
# ===================================================
if [ ! -f /etc/apt/apt.conf.d/no-bookworm-firmware.conf ]; then
msg_info "$(translate "Disabling non-free firmware warnings...")"
echo 'APT::Get::Update::SourceListWarnings::NonFreeFirmware "false";' > /etc/apt/apt.conf.d/no-bookworm-firmware.conf
msg_ok "$(translate "Non-free firmware warnings disabled")"
fi
msg_info "$(translate "Updating package lists...")"
if apt-get update > /dev/null 2>&1; then
msg_ok "$(translate "Package lists updated")"
else
msg_error "$(translate "Failed to update package lists")"
return 1
fi
msg_info "$(translate "Removing conflicting utilities...")"
if /usr/bin/env DEBIAN_FRONTEND=noninteractive apt-get -y -o Dpkg::Options::='--force-confdef' purge ntp openntpd systemd-timesyncd > /dev/null 2>&1; then
msg_ok "$(translate "Conflicting utilities removed")"
else
msg_error "$(translate "Failed to remove conflicting utilities")"
fi
msg_info "$(translate "Performing packages upgrade...")"
apt-get install pv -y > /dev/null 2>&1
total_packages=$(apt-get -s dist-upgrade | grep "^Inst" | wc -l)
if [ "$total_packages" -eq 0 ]; then
total_packages=1
fi
msg_ok "$(translate "Packages upgrade successfull")"
tput civis
tput sc
(
/usr/bin/env DEBIAN_FRONTEND=noninteractive apt-get -y -o Dpkg::Options::='--force-confdef' dist-upgrade 2>&1 | \
while IFS= read -r line; do
if [[ "$line" =~ ^(Setting up|Unpacking|Preparing to unpack|Processing triggers for) ]]; then
package_name=$(echo "$line" | sed -E 's/.*(Setting up|Unpacking|Preparing to unpack|Processing triggers for) ([^ ]+).*/\2/')
[ -z "$package_name" ] && package_name="$(translate "Unknown")"
tput rc
tput ed
row=$(( $(tput lines) - 6 ))
tput cup $row 0; echo "$(translate "Installing packages...")"
tput cup $((row + 1)) 0; echo "──────────────────────────────────────────────"
tput cup $((row + 2)) 0; echo "Package: $package_name"
tput cup $((row + 3)) 0; echo "Progress: [ ] 0%"
tput cup $((row + 4)) 0; echo "──────────────────────────────────────────────"
for i in $(seq 1 10); do
progress=$((i * 10))
tput cup $((row + 3)) 9
printf "[%-50s] %3d%%" "$(printf "#%.0s" $(seq 1 $((progress/2))))" "$progress"
done
fi
done
)
if [ $? -eq 0 ]; then
tput rc
tput ed
msg_ok "$(translate "System upgrade completed")"
fi
msg_info "$(translate "Installing additional Proxmox packages...")"
if /usr/bin/env DEBIAN_FRONTEND=noninteractive apt-get -y -o Dpkg::Options::='--force-confdef' install zfsutils-linux proxmox-backup-restore-image chrony > /dev/null 2>&1; then
msg_ok "$(translate "Additional Proxmox packages installed")"
else
msg_error "$(translate "Failed to install additional Proxmox packages")"
fi
lvm_repair_check
cleanup_duplicate_repos
msg_ok "$(translate "Proxmox update completed")"
}
# ==========================================================
remove_subscription_banner() {
msg_info "$(translate "Removing Proxmox subscription nag banner...")"
local JS_FILE="/usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js"
local GZ_FILE="/usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js.gz"
local APT_HOOK="/etc/apt/apt.conf.d/no-nag-script"
if [[ ! -f "$APT_HOOK" ]]; then
cat <<'EOF' > "$APT_HOOK"
DPkg::Post-Invoke { "dpkg -V proxmox-widget-toolkit | grep -q '/proxmoxlib\.js$'; if [ $? -eq 1 ]; then { echo 'Removing subscription nag from UI...'; sed -i '/.*data\.status.*{/{s/\!//;s/active/NoMoreNagging/;s/Active/NoMoreNagging/}' /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js; rm -f /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js.gz; }; fi"; };
EOF
fi
if [[ -f "$JS_FILE" ]]; then
sed -i '/.*data\.status.*{/{s/\!//;s/active/NoMoreNagging/;s/Active/NoMoreNagging/}' "$JS_FILE"
[[ -f "$GZ_FILE" ]] && rm -f "$GZ_FILE"
touch "$JS_FILE"
fi
apt --reinstall install proxmox-widget-toolkit -y > /dev/null 2>&1
msg_ok "$(translate "Subscription nag banner removed successfully")"
register_tool "subscription_banner" true
}
# ==========================================================
configure_time_sync() {
msg_info "$(translate "Configuring system time settings...")"
this_ip=$(dig +short myip.opendns.com @resolver1.opendns.com)
if [ -z "$this_ip" ]; then
msg_warn "$(translate "Failed to obtain public IP address")"
timezone="UTC"
else
timezone=$(curl -s "https://ipapi.co/${this_ip}/timezone")
if [ -z "$timezone" ]; then
msg_warn "$(translate "Failed to determine timezone from IP address")"
timezone="UTC"
else
msg_ok "$(translate "Found timezone $timezone for IP $this_ip")"
fi
fi
msg_info "$(translate "Enabling automatic time synchronization...")"
if timedatectl set-ntp true; then
msg_ok "$(translate "Time settings configured - Timezone:") $timezone"
register_tool "time_sync" true
else
msg_error "$(translate "Failed to enable automatic time synchronization")"
fi
}
# ==========================================================
skip_apt_languages() {
msg_info "$(translate "Configuring APT to skip downloading additional languages...")"
local default_locale=""
if [ -f /etc/default/locale ]; then
default_locale=$(grep '^LANG=' /etc/default/locale | cut -d= -f2 | tr -d '"')
elif [ -f /etc/environment ]; then
default_locale=$(grep '^LANG=' /etc/environment | cut -d= -f2 | tr -d '"')
fi
default_locale="${default_locale:-en_US.UTF-8}"
local normalized_locale=$(echo "$default_locale" | tr 'A-Z' 'a-z' | sed 's/utf-8/utf8/;s/-/_/')
if ! locale -a | grep -qi "^$normalized_locale$"; then
if ! grep -qE "^${default_locale}[[:space:]]+UTF-8" /etc/locale.gen; then
echo "$default_locale UTF-8" >> /etc/locale.gen
fi
locale-gen "$default_locale" > /dev/null 2>&1
fi
echo 'Acquire::Languages "none";' > /etc/apt/apt.conf.d/99-disable-translations
msg_ok "$(translate "APT configured to skip additional languages")"
register_tool "apt_languages" true
}
# ==========================================================
optimize_journald() {
msg_info "$(translate "Limiting size and optimizing journald...")"
NECESSARY_REBOOT=1
cat <<EOF > /etc/systemd/journald.conf
[Journal]
Storage=persistent
SplitMode=none
RateLimitInterval=0
RateLimitIntervalSec=0
RateLimitBurst=0
ForwardToSyslog=no
ForwardToWall=yes
Seal=no
Compress=yes
SystemMaxUse=64M
RuntimeMaxUse=60M
MaxLevelStore=warning
MaxLevelSyslog=warning
MaxLevelKMsg=warning
MaxLevelConsole=notice
MaxLevelWall=crit
EOF
systemctl restart systemd-journald.service > /dev/null 2>&1
journalctl --vacuum-size=64M --vacuum-time=1d > /dev/null 2>&1
journalctl --rotate > /dev/null 2>&1
msg_ok "$(translate "Journald optimized - Max size: 64M")"
register_tool "journald" true
}
# ==========================================================
optimize_logrotate() {
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"
# ProxMenux optimized configuration
daily
su root adm
rotate 7
create
compress
size=10M
delaycompress
copytruncate
include /etc/logrotate.d
EOF
systemctl restart logrotate > /dev/null 2>&1
fi
msg_ok "$(translate "Logrotate optimization completed")"
register_tool "logrotate" true
}
# ==========================================================
increase_system_limits() {
msg_info "$(translate "Increasing various system limits...")"
NECESSARY_REBOOT=1
cat > /etc/sysctl.d/99-maxwatches.conf << EOF
# ProxMenux configuration
fs.inotify.max_user_watches = 1048576
fs.inotify.max_user_instances = 1048576
fs.inotify.max_queued_events = 1048576
EOF
cat > /etc/security/limits.d/99-limits.conf << EOF
# ProxMenux configuration
* soft nproc 1048576
* hard nproc 1048576
* soft nofile 1048576
* hard nofile 1048576
root soft nproc unlimited
root hard nproc unlimited
root soft nofile unlimited
root hard nofile unlimited
EOF
cat > /etc/sysctl.d/99-maxkeys.conf << EOF
# ProxMenux configuration
kernel.keys.root_maxkeys=1000000
kernel.keys.maxkeys=1000000
EOF
for file in /etc/systemd/system.conf /etc/systemd/user.conf; do
if ! grep -q "^DefaultLimitNOFILE=" "$file"; then
echo "DefaultLimitNOFILE=256000" >> "$file"
fi
done
for file in /etc/pam.d/common-session /etc/pam.d/runuser-l; do
if ! grep -q "^session required pam_limits.so" "$file"; then
echo 'session required pam_limits.so' >> "$file"
fi
done
if ! grep -q "ulimit -n 256000" /root/.profile; then
echo "ulimit -n 256000" >> /root/.profile
fi
cat > /etc/sysctl.d/99-swap.conf << EOF
# ProxMenux configuration
vm.swappiness = 10
vm.vfs_cache_pressure = 100
EOF
cat > /etc/sysctl.d/99-fs.conf << EOF
# ProxMenux configuration
fs.nr_open = 12000000
fs.file-max = 9223372036854775807
fs.aio-max-nr = 1048576
EOF
msg_ok "$(translate "System limits increase completed.")"
register_tool "system_limits" true
}
# ==========================================================
configure_entropy() {
msg_info "$(translate "Configuring entropy generation to prevent slowdowns...")"
/usr/bin/env DEBIAN_FRONTEND=noninteractive apt-get -y -o Dpkg::Options::='--force-confdef' install haveged > /dev/null 2>&1
cat <<EOF > /etc/default/haveged
# -w sets low entropy watermark (in bits)
DAEMON_ARGS="-w 1024"
EOF
systemctl daemon-reload > /dev/null 2>&1
systemctl enable haveged > /dev/null 2>&1
msg_ok "$(translate "Entropy generation configuration completed")"
register_tool "entropy" true
}
# ==========================================================
optimize_memory_settings() {
msg_info "$(translate "Optimizing memory settings...")"
NECESSARY_REBOOT=1
cat <<EOF > /etc/sysctl.d/99-memory.conf
# Balanced Memory Optimization
vm.swappiness = 10
vm.dirty_ratio = 15
vm.dirty_background_ratio = 5
vm.overcommit_memory = 1
vm.max_map_count = 65530
EOF
if [ -f /proc/sys/vm/compaction_proactiveness ]; then
echo "vm.compaction_proactiveness = 20" >> /etc/sysctl.d/99-memory.conf
fi
msg_ok "$(translate "Memory optimization completed.")"
register_tool "memory_settings" true
}
# ==========================================================
configure_kernel_panic() {
msg_info "$(translate "Configuring kernel panic behavior")"
NECESSARY_REBOOT=1
cat <<EOF > /etc/sysctl.d/99-kernelpanic.conf
# Enable restart on kernel panic, kernel oops and hardlockup
kernel.core_pattern = /var/crash/core.%t.%p
kernel.panic = 10
kernel.panic_on_oops = 1
kernel.hardlockup_panic = 1
EOF
msg_ok "$(translate "Kernel panic behavior configuration completed")"
register_tool "kernel_panic" true
}
# ==========================================================
force_apt_ipv4() {
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
}
# ==========================================================
apply_network_optimizations() {
msg_info "$(translate "Optimizing network settings...")"
NECESSARY_REBOOT=1
cat <<EOF > /etc/sysctl.d/99-network.conf
net.core.netdev_max_backlog=8192
net.core.optmem_max=8192
net.core.rmem_max=16777216
net.core.somaxconn=8151
net.core.wmem_max=16777216
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.all.log_martians = 0
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv4.conf.default.log_martians = 0
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.default.secure_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.icmp_ignore_bogus_error_responses = 1
net.ipv4.ip_local_port_range=1024 65535
net.ipv4.tcp_base_mss = 1024
net.ipv4.tcp_challenge_ack_limit = 999999999
net.ipv4.tcp_fin_timeout=10
net.ipv4.tcp_keepalive_intvl=30
net.ipv4.tcp_keepalive_probes=3
net.ipv4.tcp_keepalive_time=240
net.ipv4.tcp_limit_output_bytes=65536
net.ipv4.tcp_max_syn_backlog=8192
net.ipv4.tcp_max_tw_buckets = 1440000
net.ipv4.tcp_mtu_probing = 1
net.ipv4.tcp_rfc1337=1
net.ipv4.tcp_rmem=8192 87380 16777216
net.ipv4.tcp_sack=1
net.ipv4.tcp_slow_start_after_idle=0
net.ipv4.tcp_syn_retries=3
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_tw_recycle = 0
net.ipv4.tcp_tw_reuse = 0
net.ipv4.tcp_wmem=8192 65536 16777216
net.netfilter.nf_conntrack_generic_timeout = 60
net.netfilter.nf_conntrack_helper=0
net.netfilter.nf_conntrack_max = 524288
net.netfilter.nf_conntrack_tcp_timeout_established = 28800
net.unix.max_dgram_qlen = 4096
EOF
sysctl --system > /dev/null 2>&1
local interfaces_file="/etc/network/interfaces"
if ! grep -q 'source /etc/network/interfaces.d/*' "$interfaces_file"; then
echo "source /etc/network/interfaces.d/*" >> "$interfaces_file"
fi
msg_ok "$(translate "Network optimization completed")"
register_tool "network_optimization" true
}
# ==========================================================
disable_rpc() {
msg_info "$(translate "Disabling portmapper/rpcbind for security...")"
systemctl disable rpcbind > /dev/null 2>&1
systemctl stop rpcbind > /dev/null 2>&1
msg_ok "$(translate "portmapper/rpcbind has been disabled and removed")"
register_tool "disable_rpc" true
}
# ==========================================================
customize_bashrc() {
msg_info "$(translate "Customizing bashrc for root user...")"
local bashrc="/root/.bashrc"
local bash_profile="/root/.bash_profile"
if [ ! -f "${bashrc}.bak" ]; then
cp "$bashrc" "${bashrc}.bak"
fi
cat >> "$bashrc" << 'EOF'
# ProxMenux customizations
export HISTTIMEFORMAT="%d/%m/%y %T "
export PS1="\[\e[31m\][\[\e[m\]\[\e[38;5;172m\]\u\[\e[m\]@\[\e[38;5;153m\]\h\[\e[m\] \[\e[38;5;214m\]\W\[\e[m\]\[\e[31m\]]\[\e[m\]\\$ "
alias l='ls -CF'
alias la='ls -A'
alias ll='ls -alF'
alias ls='ls --color=auto'
alias grep='grep --color=auto'
alias fgrep='fgrep --color=auto'
alias egrep='egrep --color=auto'
source /etc/profile.d/bash_completion.sh
EOF
if ! grep -q "source /root/.bashrc" "$bash_profile"; then
echo "source /root/.bashrc" >> "$bash_profile"
fi
msg_ok "$(translate "Bashrc customization completed")"
register_tool "bashrc_custom" true
}
# ==========================================================
install_log2ram_auto() {
msg_info2 "$(translate "Checking if system disk is SSD or M.2...")"
ROOT_PART=$(lsblk -no NAME,MOUNTPOINT | grep ' /$' | awk '{print $1}')
SYSTEM_DISK=$(lsblk -no PKNAME /dev/$ROOT_PART 2>/dev/null)
SYSTEM_DISK=${SYSTEM_DISK:-sda}
if [[ "$SYSTEM_DISK" == nvme* || "$(cat /sys/block/$SYSTEM_DISK/queue/rotational 2>/dev/null)" == "0" ]]; then
msg_ok "$(translate "System disk ($SYSTEM_DISK) is SSD or M.2. Proceeding with log2ram setup.")"
else
msg_warn "$(translate "System disk ($SYSTEM_DISK) is not SSD/M.2. Skipping log2ram installation.")"
return 0
fi
# Clean up previous state
rm -rf /tmp/log2ram
rm -f /etc/systemd/system/log2ram*
rm -f /etc/systemd/system/log2ram-daily.*
rm -f /etc/cron.d/log2ram*
rm -f /usr/sbin/log2ram
rm -f /etc/log2ram.conf
rm -f /usr/local/bin/log2ram-check.sh
rm -rf /var/log.hdd
systemctl daemon-reexec >/dev/null 2>&1
systemctl daemon-reload >/dev/null 2>&1
msg_info "$(translate "Installing log2ram from GitHub...")"
git clone https://github.com/azlux/log2ram.git /tmp/log2ram >/dev/null 2>>/tmp/log2ram_install.log
cd /tmp/log2ram || return 1
bash install.sh >>/tmp/log2ram_install.log 2>&1
if [[ -f /etc/log2ram.conf ]] && systemctl list-units --all | grep -q log2ram; then
msg_ok "$(translate "log2ram installed successfully")"
else
msg_error "$(translate "Failed to install log2ram. See /tmp/log2ram_install.log")"
return 1
fi
# Detect RAM
RAM_SIZE_GB=$(free -g | awk '/^Mem:/{print $2}')
[[ -z "$RAM_SIZE_GB" || "$RAM_SIZE_GB" -eq 0 ]] && RAM_SIZE_GB=4
if (( RAM_SIZE_GB <= 8 )); then
LOG2RAM_SIZE="128M"
CRON_HOURS=1
elif (( RAM_SIZE_GB <= 16 )); then
LOG2RAM_SIZE="256M"
CRON_HOURS=3
else
LOG2RAM_SIZE="512M"
CRON_HOURS=6
fi
msg_ok "$(translate "Detected RAM:") $RAM_SIZE_GB GB — $(translate "log2ram size set to:") $LOG2RAM_SIZE"
sed -i "s/^SIZE=.*/SIZE=$LOG2RAM_SIZE/" /etc/log2ram.conf
rm -f /etc/cron.hourly/log2ram
echo "0 */$CRON_HOURS * * * root /usr/sbin/log2ram write" > /etc/cron.d/log2ram
msg_ok "$(translate "log2ram write scheduled every") $CRON_HOURS $(translate "hour(s)")"
cat << 'EOF' > /usr/local/bin/log2ram-check.sh
#!/bin/bash
CONF_FILE="/etc/log2ram.conf"
LIMIT_KB=$(grep '^SIZE=' "$CONF_FILE" | cut -d'=' -f2 | tr -d 'M')000
USED_KB=$(df /var/log --output=used | tail -1)
THRESHOLD=$(( LIMIT_KB * 90 / 100 ))
if (( USED_KB > THRESHOLD )); then
/usr/sbin/log2ram write
fi
EOF
chmod +x /usr/local/bin/log2ram-check.sh
echo "*/5 * * * * root /usr/local/bin/log2ram-check.sh" > /etc/cron.d/log2ram-auto-sync
msg_ok "$(translate "Auto-sync enabled when /var/log exceeds 90% of") $LOG2RAM_SIZE"
register_tool "log2ram" true
}
# ==========================================================
run_complete_optimization() {
clear
show_proxmenux_logo
msg_title "$(translate "ProxMenux Optimization Post-Installation")"
ensure_tools_json
apt_upgrade
remove_subscription_banner
configure_time_sync
skip_apt_languages
optimize_journald
optimize_logrotate
increase_system_limits
configure_entropy
optimize_memory_settings
configure_kernel_panic
force_apt_ipv4
apply_network_optimizations
disable_rpc
customize_bashrc
install_log2ram_auto
echo -e
msg_success "$(translate "Complete post-installation optimization finished!")"
if [[ "$NECESSARY_REBOOT" -eq 1 ]]; then
whiptail --title "Reboot Required" \
--yesno "$(translate "Some changes require a reboot to take effect. Do you want to restart now?")" 10 60
if [[ $? -eq 0 ]]; then
msg_info "$(translate "Removing no longer required packages and purging old cached updates...")"
apt-get -y autoremove >/dev/null 2>&1
apt-get -y autoclean >/dev/null 2>&1
msg_ok "$(translate "Cleanup finished")"
msg_success "$(translate "Press Enter to continue...")"
read -r
msg_warn "$(translate "Rebooting the system...")"
reboot
else
msg_info "$(translate "Removing no longer required packages and purging old cached updates...")"
apt-get -y autoremove >/dev/null 2>&1
apt-get -y autoclean >/dev/null 2>&1
msg_ok "$(translate "Cleanup finished")"
msg_info2 "$(translate "You can reboot later manually.")"
msg_success "$(translate "Press Enter to continue...")"
read -r
exit 0
fi
fi
msg_success "$(translate "All changes applied. No reboot required.")"
msg_success "$(translate "Press Enter to return to menu...")"
read -r
clear
}
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
run_complete_optimization
fi

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,606 @@
#!/bin/bash
# ==========================================================
# ProxMenux - Complete Uninstall Optimizations Script
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : MIT (https://raw.githubusercontent.com/MacRimi/ProxMenux/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.
#
# 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.
# ==========================================================
REPO_URL="https://raw.githubusercontent.com/MacRimi/ProxMenux/main"
RETURN_SCRIPT="$REPO_URL/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"
VENV_PATH="/opt/googletrans-env"
if [[ -f "$UTILS_FILE" ]]; then
source "$UTILS_FILE"
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() {
if ! command -v fastfetch &>/dev/null; then
msg_warn "$(translate "Fastfetch is not installed.")"
return 0
fi
msg_info2 "$(translate "Uninstalling Fastfetch...")"
rm -f /usr/local/bin/fastfetch /usr/bin/fastfetch
rm -rf "$HOME/.config/fastfetch"
rm -rf /usr/local/share/fastfetch
sed -i '/fastfetch/d' "$HOME/.bashrc" "$HOME/.profile" 2>/dev/null
rm -f /etc/profile.d/fastfetch.sh /etc/update-motd.d/99-fastfetch
dpkg -r fastfetch &>/dev/null
msg_ok "$(translate "Fastfetch removed from system")"
register_tool "fastfetch" false
}
################################################################
uninstall_figurine() {
if ! command -v figurine &>/dev/null; then
msg_warn "$(translate "Figurine is not installed.")"
return 0
fi
msg_info2 "$(translate "Uninstalling Figurine...")"
rm -f /usr/local/bin/figurine
rm -f /etc/profile.d/figurine.sh
sed -i '/figurine/d' "$HOME/.bashrc" "$HOME/.profile" 2>/dev/null
msg_ok "$(translate "Figurine removed from system")"
register_tool "figurine" false
}
################################################################
uninstall_kexec() {
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...")"
systemctl disable --now kexec-pve.service &>/dev/null
rm -f /etc/systemd/system/kexec-pve.service
sed -i "/alias reboot-quick='systemctl kexec'/d" /root/.bash_profile
apt-get purge -y kexec-tools >/dev/null 2>&1
msg_ok "$(translate "kexec-tools and related settings removed")"
register_tool "kexec" false
}
################################################################
uninstall_apt_upgrade() {
msg_info "$(translate "Restoring enterprise repositories...")"
# Re-enable enterprise repos
if [ -f /etc/apt/sources.list.d/pve-enterprise.list ]; then
sed -i "s/^#deb/deb/g" /etc/apt/sources.list.d/pve-enterprise.list
fi
if [ -f /etc/apt/sources.list.d/ceph.list ]; then
sed -i "s/^#deb/deb/g" /etc/apt/sources.list.d/ceph.list
fi
# Remove public repo
rm -f /etc/apt/sources.list.d/pve-public-repo.list
# Remove firmware warning config
rm -f /etc/apt/apt.conf.d/no-bookworm-firmware.conf
apt-get update > /dev/null 2>&1
msg_ok "$(translate "Enterprise repositories restored")"
register_tool "apt_upgrade" false
}
################################################################
uninstall_subscription_banner() {
msg_info "$(translate "Restoring subscription banner...")"
# Remove APT hook
rm -f /etc/apt/apt.conf.d/no-nag-script
# Reinstall proxmox-widget-toolkit to restore original
apt --reinstall install proxmox-widget-toolkit -y >/dev/null 2>&1
msg_ok "$(translate "Subscription banner restored")"
register_tool "subscription_banner" false
}
################################################################
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() {
msg_info "$(translate "Restoring default journald configuration...")"
# Restore default journald configuration
cat > /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
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...")"
# Restore from backup if it exists
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() {
msg_info "$(translate "Removing system limits optimizations...")"
# Remove ProxMenux sysctl configurations
rm -f /etc/sysctl.d/99-maxwatches.conf
rm -f /etc/sysctl.d/99-maxkeys.conf
rm -f /etc/sysctl.d/99-swap.conf
rm -f /etc/sysctl.d/99-fs.conf
# Remove ProxMenux limits configuration
rm -f /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
sed -i '/^DefaultLimitNOFILE=256000/d' "$file"
fi
done
# Remove PAM limits
for file in /etc/pam.d/common-session /etc/pam.d/runuser-l; do
if [ -f "$file" ]; then
sed -i '/^session required pam_limits.so/d' "$file"
fi
done
# Remove ulimit from profile
if [ -f /root/.profile ]; then
sed -i '/ulimit -n 256000/d' /root/.profile
fi
# Reload sysctl
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() {
msg_info "$(translate "Removing network optimizations...")"
# Remove ProxMenux network configuration
rm -f /etc/sysctl.d/99-network.conf
# Remove interfaces.d source line if we added it
local interfaces_file="/etc/network/interfaces"
if [ -f "$interfaces_file" ]; then
# Only remove if it's the last line and looks like our addition
if tail -1 "$interfaces_file" | grep -q "^source /etc/network/interfaces.d/\*$"; then
sed -i '$d' "$interfaces_file"
fi
fi
# Reload sysctl
sysctl --system >/dev/null 2>&1
msg_ok "$(translate "Network optimizations removed")"
register_tool "network_optimization" false
}
################################################################
uninstall_disable_rpc() {
msg_info "$(translate "Re-enabling RPC services...")"
# Re-enable and start rpcbind
systemctl enable rpcbind >/dev/null 2>&1
systemctl start rpcbind >/dev/null 2>&1
msg_ok "$(translate "RPC services re-enabled")"
register_tool "disable_rpc" false
}
################################################################
uninstall_bashrc_custom() {
msg_info "$(translate "Restoring original bashrc...")"
# Restore original bashrc from backup
if [ -f /root/.bashrc.bak ]; then
mv /root/.bashrc.bak /root/.bashrc
msg_ok "$(translate "Original bashrc restored")"
else
# Remove ProxMenux customizations manually
if [ -f /root/.bashrc ]; then
# Remove our customization block
sed -i '/# ProxMenux customizations/,/source \/etc\/profile\.d\/bash_completion\.sh/d' /root/.bashrc
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
sed -i '/source \/root\/\.bashrc/d' /root/.bash_profile
fi
register_tool "bashrc_custom" false
}
################################################################
uninstall_log2ram() {
if [[ ! -f /etc/log2ram.conf ]] && ! systemctl list-units --all | grep -q log2ram; then
msg_warn "$(translate "log2ram is not installed.")"
return 0
fi
msg_info "$(translate "Uninstalling log2ram...")"
# Stop and disable services and timers
systemctl stop log2ram >/dev/null 2>&1
systemctl disable log2ram >/dev/null 2>&1
systemctl stop log2ram-daily.timer >/dev/null 2>&1
systemctl disable log2ram-daily.timer >/dev/null 2>&1
# Remove cron jobs
rm -f /etc/cron.d/log2ram
rm -f /etc/cron.d/log2ram-auto-sync
# Remove config and binaries
rm -f /usr/local/bin/log2ram-check.sh
rm -f /usr/sbin/log2ram
rm -f /etc/log2ram.conf*
rm -f /etc/systemd/system/log2ram.service
rm -f /etc/systemd/system/log2ram-daily.timer
rm -f /etc/systemd/system/log2ram-daily.service
# Clean up log2ram mount if active
if [ -d /var/log.hdd ]; then
if [ -d /var/log ] && mountpoint -q /var/log; then
rsync -a /var/log/ /var/log.hdd/ >/dev/null 2>&1
umount /var/log >/dev/null 2>&1
fi
rm -rf /var/log.hdd
fi
systemctl daemon-reexec >/dev/null 2>&1
systemctl daemon-reload >/dev/null 2>&1
msg_ok "$(translate "log2ram completely removed")"
register_tool "log2ram" false
}
################################################################
migrate_installed_tools() {
if [[ -f "$TOOLS_JSON" ]]; then
return
fi
clear
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
}
################################################################
show_uninstall_menu() {
ensure_tools_json
migrate_installed_tools
mapfile -t tools_installed < <(jq -r 'to_entries | map(select(.value==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
lvm_repair) desc="LVM PV Headers Repair";;
repo_cleanup) desc="Repository Cleanup";;
apt_upgrade) desc="APT Upgrade & Repository Config";;
subscription_banner) desc="Subscription Banner Removal";;
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";;
network_optimization) desc="Network Optimizations";;
disable_rpc) desc="RPC/rpcbind Disable";;
bashrc_custom) desc="Bashrc Customization";;
log2ram) desc="Log2ram (SSD Protection)";;
*) 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.")"
if dialog --backtitle "ProxMenux" \
--title "$(translate "Reboot Recommended")" \
--yesno "$(translate "Do you want to reboot now?")" 8 50; then
reboot
fi
}
################################################################
show_uninstall_menu

View File

@ -1,19 +1,25 @@
#!/bin/bash
# ==========================================================
# ProxMenux - Uninstall Tools Menu for Proxmox
# ProxMenux - Complete Uninstall Optimizations Script
# ==========================================================
# Author : MacRimi
# Copyright : (c) 2024 MacRimi
# License : MIT (https://raw.githubusercontent.com/MacRimi/ProxMenux/main/LICENSE)
# Version : 1.1
# Last Updated: 19/06/2025
# Version : 1.0
# Last Updated: 06/07/2025
# ==========================================================
# Description:
# This script provides a dynamic menu for uninstalling optional tools
# installed through ProxMenux on Proxmox Virtual Environment (VE).
# This script provides a complete uninstallation and rollback system
# for all post-installation optimizations applied by ProxMenux.
#
# 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.
# ==========================================================
REPO_URL="https://raw.githubusercontent.com/MacRimi/ProxMenux/main"
RETURN_SCRIPT="$REPO_URL/scripts/menus/menu_post_install.sh"
BASE_DIR="/usr/local/share/proxmenux"
@ -24,10 +30,11 @@ VENV_PATH="/opt/googletrans-env"
if [[ -f "$UTILS_FILE" ]]; then
source "$UTILS_FILE"
fi
load_language
initialize_cache
# Tool registration system
ensure_tools_json() {
[ -f "$TOOLS_JSON" ] || echo "{}" > "$TOOLS_JSON"
}
@ -39,49 +46,6 @@ register_tool() {
jq --arg t "$tool" --argjson v "$state" '.[$t]=$v' "$TOOLS_JSON" > "$TOOLS_JSON.tmp" && mv "$TOOLS_JSON.tmp" "$TOOLS_JSON"
}
migrate_installed_tools() {
local TOOLS_JSON="/usr/local/share/proxmenux/installed_tools.json"
if [[ -f "$TOOLS_JSON" ]]; then
return
fi
clear
show_proxmenux_logo
msg_info "$(translate 'Detecting previous adjustments...')"
echo "{}" > "$TOOLS_JSON"
local updated=false
# --- Fastfetch ---
if command -v fastfetch >/dev/null 2>&1 || [[ -x /usr/local/bin/fastfetch ]] || [[ -x /usr/bin/fastfetch ]]; then
jq '. + {"fastfetch": true}' "$TOOLS_JSON" > "$TOOLS_JSON.tmp" && mv "$TOOLS_JSON.tmp" "$TOOLS_JSON"
updated=true
fi
# --- Figurine ---
if command -v figurine >/dev/null 2>&1 || [[ -x /usr/local/bin/figurine ]]; then
jq '. + {"figurine": true}' "$TOOLS_JSON" > "$TOOLS_JSON.tmp" && mv "$TOOLS_JSON.tmp" "$TOOLS_JSON"
updated=true
fi
# --- Kexec ---
if dpkg -s kexec-tools >/dev/null 2>&1 && systemctl list-unit-files | grep -q kexec-pve.service; then
jq '. + {"kexec": true}' "$TOOLS_JSON" > "$TOOLS_JSON.tmp" && mv "$TOOLS_JSON.tmp" "$TOOLS_JSON"
updated=true
fi
if [[ "$updated" == true ]]; then
sleep 2
msg_ok "$(translate 'Adjustments detected and ready to revert.')"
sleep 1
fi
}
################################################################
uninstall_fastfetch() {
@ -139,36 +103,483 @@ uninstall_kexec() {
################################################################
uninstall_apt_upgrade() {
msg_info "$(translate "Restoring enterprise repositories...")"
# Re-enable enterprise repos
if [ -f /etc/apt/sources.list.d/pve-enterprise.list ]; then
sed -i "s/^#deb/deb/g" /etc/apt/sources.list.d/pve-enterprise.list
fi
if [ -f /etc/apt/sources.list.d/ceph.list ]; then
sed -i "s/^#deb/deb/g" /etc/apt/sources.list.d/ceph.list
fi
# Remove public repo
rm -f /etc/apt/sources.list.d/pve-public-repo.list
# Remove firmware warning config
rm -f /etc/apt/apt.conf.d/no-bookworm-firmware.conf
apt-get update > /dev/null 2>&1
msg_ok "$(translate "Enterprise repositories restored")"
register_tool "apt_upgrade" false
}
################################################################
uninstall_subscription_banner() {
msg_info "$(translate "Restoring subscription banner...")"
# Remove APT hook
rm -f /etc/apt/apt.conf.d/no-nag-script
# Reinstall proxmox-widget-toolkit to restore original
apt --reinstall install proxmox-widget-toolkit -y >/dev/null 2>&1
msg_ok "$(translate "Subscription banner restored")"
register_tool "subscription_banner" false
}
################################################################
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() {
msg_info "$(translate "Restoring default journald configuration...")"
# Restore default journald configuration
cat > /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
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...")"
# Restore from backup if it exists
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() {
msg_info "$(translate "Removing system limits optimizations...")"
# Remove ProxMenux sysctl configurations
rm -f /etc/sysctl.d/99-maxwatches.conf
rm -f /etc/sysctl.d/99-maxkeys.conf
rm -f /etc/sysctl.d/99-swap.conf
rm -f /etc/sysctl.d/99-fs.conf
# Remove ProxMenux limits configuration
rm -f /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
sed -i '/^DefaultLimitNOFILE=256000/d' "$file"
fi
done
# Remove PAM limits
for file in /etc/pam.d/common-session /etc/pam.d/runuser-l; do
if [ -f "$file" ]; then
sed -i '/^session required pam_limits.so/d' "$file"
fi
done
# Remove ulimit from profile
if [ -f /root/.profile ]; then
sed -i '/ulimit -n 256000/d' /root/.profile
fi
# Reload sysctl
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() {
msg_info "$(translate "Removing network optimizations...")"
# Remove ProxMenux network configuration
rm -f /etc/sysctl.d/99-network.conf
# Remove interfaces.d source line if we added it
local interfaces_file="/etc/network/interfaces"
if [ -f "$interfaces_file" ]; then
# Only remove if it's the last line and looks like our addition
if tail -1 "$interfaces_file" | grep -q "^source /etc/network/interfaces.d/\*$"; then
sed -i '$d' "$interfaces_file"
fi
fi
# Reload sysctl
sysctl --system >/dev/null 2>&1
msg_ok "$(translate "Network optimizations removed")"
register_tool "network_optimization" false
}
################################################################
uninstall_disable_rpc() {
msg_info "$(translate "Re-enabling RPC services...")"
# Re-enable and start rpcbind
systemctl enable rpcbind >/dev/null 2>&1
systemctl start rpcbind >/dev/null 2>&1
msg_ok "$(translate "RPC services re-enabled")"
register_tool "disable_rpc" false
}
################################################################
uninstall_bashrc_custom() {
msg_info "$(translate "Restoring original bashrc...")"
# Restore original bashrc from backup
if [ -f /root/.bashrc.bak ]; then
mv /root/.bashrc.bak /root/.bashrc
msg_ok "$(translate "Original bashrc restored")"
else
# Remove ProxMenux customizations manually
if [ -f /root/.bashrc ]; then
# Remove our customization block
sed -i '/# ProxMenux customizations/,/source \/etc\/profile\.d\/bash_completion\.sh/d' /root/.bashrc
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
sed -i '/source \/root\/\.bashrc/d' /root/.bash_profile
fi
register_tool "bashrc_custom" false
}
################################################################
uninstall_log2ram() {
if [[ ! -f /etc/log2ram.conf ]] && ! systemctl list-units --all | grep -q log2ram; then
msg_warn "$(translate "log2ram is not installed.")"
return 0
fi
msg_info "$(translate "Uninstalling log2ram...")"
# Stop and disable services and timers
systemctl stop log2ram >/dev/null 2>&1
systemctl disable log2ram >/dev/null 2>&1
systemctl stop log2ram-daily.timer >/dev/null 2>&1
systemctl disable log2ram-daily.timer >/dev/null 2>&1
# Remove cron jobs
rm -f /etc/cron.d/log2ram
rm -f /etc/cron.d/log2ram-auto-sync
# Remove config and binaries
rm -f /usr/local/bin/log2ram-check.sh
rm -f /usr/sbin/log2ram
rm -f /etc/log2ram.conf*
rm -f /etc/systemd/system/log2ram.service
rm -f /etc/systemd/system/log2ram-daily.timer
rm -f /etc/systemd/system/log2ram-daily.service
# Clean up log2ram mount if active
if [ -d /var/log.hdd ]; then
if [ -d /var/log ] && mountpoint -q /var/log; then
rsync -a /var/log/ /var/log.hdd/ >/dev/null 2>&1
umount /var/log >/dev/null 2>&1
fi
rm -rf /var/log.hdd
fi
systemctl daemon-reexec >/dev/null 2>&1
systemctl daemon-reload >/dev/null 2>&1
msg_ok "$(translate "log2ram completely removed")"
register_tool "log2ram" false
}
################################################################
migrate_installed_tools() {
if [[ -f "$TOOLS_JSON" ]]; then
return
fi
clear
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
}
################################################################
show_uninstall_menu() {
ensure_tools_json
migrate_installed_tools
mapfile -t tools_installed < <(jq -r 'to_entries | map(select(.value==true)) | .[].key' "$TOOLS_JSON")
if [[ ${#tools_installed[@]} -eq 0 ]]; then
dialog --backtitle "ProxMenux" --title "ProxMenux" --msgbox "\n\n$(translate "No uninstallable tools detected.")" 10 60
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
fastfetch) desc="Fastfetch";;
figurine) desc="Figurine";;
kexec) desc="Kexec fast reboot";;
lvm_repair) desc="LVM PV Headers Repair";;
repo_cleanup) desc="Repository Cleanup";;
apt_upgrade) desc="APT Upgrade & Repository Config";;
subscription_banner) desc="Subscription Banner Removal";;
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";;
network_optimization) desc="Network Optimizations";;
disable_rpc) desc="RPC/rpcbind Disable";;
bashrc_custom) desc="Bashrc Customization";;
log2ram) desc="Log2ram (SSD Protection)";;
*) desc="$tool";;
esac
menu_options+=("$tool" "$desc" "off")
done
selected_tools=$(dialog --backtitle "ProxMenux" \
--title "$(translate "Uninstall Tools")" \
--checklist "$(translate "Select settings") post-install $(translate "to uninstall:")" 20 60 12 \
--title "$(translate "Uninstall Optimizations")" \
--checklist "$(translate "Select optimizations to uninstall:")" 20 70 12 \
"${menu_options[@]}" 3>&1 1>&2 2>&3)
local dialog_result=$?
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
@ -180,12 +591,16 @@ show_uninstall_menu() {
fi
done
msg_success "$(translate "All related files and settings have been removed. Reboot required.")"
msg_success "$(translate "Press Enter to return to menu...")"
read -r
msg_success "$(translate "Selected optimizations have been uninstalled.")"
msg_warn "$(translate "A system reboot is recommended to ensure all changes take effect.")"
if dialog --backtitle "ProxMenux" \
--title "$(translate "Reboot Recommended")" \
--yesno "$(translate "Do you want to reboot now?")" 8 50; then
reboot
fi
}
################################################################
migrate_installed_tools
show_uninstall_menu