From 26968b02a1c763f03edaa8b4f9beb9526e4469ae Mon Sep 17 00:00:00 2001 From: MacRimi Date: Thu, 2 Apr 2026 19:23:55 +0200 Subject: [PATCH] update post_install.sh --- scripts/post_install/auto_post_install.sh | 62 +- .../post_install/customizable_post_install.sh | 1650 +---------------- scripts/post_install/uninstall-tools.sh | 194 +- 3 files changed, 124 insertions(+), 1782 deletions(-) diff --git a/scripts/post_install/auto_post_install.sh b/scripts/post_install/auto_post_install.sh index 09b33025..b8f217e8 100644 --- a/scripts/post_install/auto_post_install.sh +++ b/scripts/post_install/auto_post_install.sh @@ -511,42 +511,7 @@ EOF # ========================================================== -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 -} - - - -customize_bashrc() { +customize_bashrc() { msg_info "$(translate "Customizing bashrc for root user...")" local bashrc="/root/.bashrc" local bash_profile="/root/.bash_profile" @@ -562,7 +527,7 @@ customize_bashrc() { fi - cat >> "$bashrc" << 'EOF' + cat >> "$bashrc" << EOF ${marker_begin} # ProxMenux core customizations export HISTTIMEFORMAT="%d/%m/%y %T " @@ -837,27 +802,27 @@ EOF setup_persistent_network() { local LINK_DIR="/etc/systemd/network" local BACKUP_DIR="/etc/systemd/network/backup-$(date +%Y%m%d-%H%M%S)" - + local pve_version + pve_version=$(pveversion 2>/dev/null | grep -oP 'pve-manager/\K[0-9]+' | head -1) - msg_info "$(translate "Setting up persistent network interfaces")" sleep 2 mkdir -p "$LINK_DIR" - + if ls "$LINK_DIR"/*.link >/dev/null 2>&1; then mkdir -p "$BACKUP_DIR" cp "$LINK_DIR"/*.link "$BACKUP_DIR"/ 2>/dev/null || true fi - + local count=0 for iface in $(ls /sys/class/net/ | grep -vE "lo|docker|veth|br-|vmbr|tap|fwpr|fwln|virbr|bond|cilium|zt|wg"); do if [[ -e "/sys/class/net/$iface/device" ]] || [[ -e "/sys/class/net/$iface/phy80211" ]]; then local MAC=$(cat /sys/class/net/$iface/address 2>/dev/null) - + if [[ "$MAC" =~ ^([a-fA-F0-9]{2}:){5}[a-fA-F0-9]{2}$ ]]; then local LINK_FILE="$LINK_DIR/10-$iface.link" - + cat > "$LINK_FILE" </dev/null || true + msg_ok "$(translate "PVE9: udev rules reloaded — new interfaces will get correct names without reboot")" + fi msg_ok "$(translate "Changes will apply after reboot.")" else msg_warn "$(translate "No physical interfaces found")" fi register_tool "persistent_network" true - } diff --git a/scripts/post_install/customizable_post_install.sh b/scripts/post_install/customizable_post_install.sh index df889ee4..99e14503 100644 --- a/scripts/post_install/customizable_post_install.sh +++ b/scripts/post_install/customizable_post_install.sh @@ -60,6 +60,11 @@ fi load_language initialize_cache + +# Load shared global functions +if [[ -f "$LOCAL_SCRIPTS/global/common-functions.sh" ]]; then + source "$LOCAL_SCRIPTS/global/common-functions.sh" +fi # ========================================================== @@ -112,8 +117,7 @@ $(translate "Do you want to continue anyway?")" 13 70 enable_kexec() { msg_info2 "$(translate "Configuring kexec for quick reboots...")" - NECESSARY_REBOOT=1 - register_tool "kexec" true + NECESSARY_REBOOT=1 # Set default answers for debconf echo "kexec-tools kexec-tools/load_kexec boolean false" | debconf-set-selections > /dev/null 2>&1 @@ -242,8 +246,12 @@ Compress=yes SystemMaxUse=64M RuntimeMaxUse=60M # Optimize the logging and speed up tasks -MaxLevelStore=warning -MaxLevelSyslog=warning +# MaxLevelStore=info allows ProxMenux Monitor to display system logs correctly. +# Using "warning" causes the log viewer to show nearly identical entries across +# all date ranges (1d/3d/7d) because most activity is info-level. +# It also prevents Fail2Ban from detecting SSH/Proxmox auth failures via journal. +MaxLevelStore=info +MaxLevelSyslog=info MaxLevelKMsg=warning MaxLevelConsole=notice MaxLevelWall=crit @@ -269,6 +277,7 @@ EOF journalctl --rotate > /dev/null 2>&1 msg_success "$(translate "Journald optimization completed")" + register_tool "journald" true } @@ -281,31 +290,6 @@ EOF -install_kernel_headers() { - msg_info2 "$(translate "Installing kernel headers")" - NECESSARY_REBOOT=1 - - # Get the current kernel version - local kernel_version=$(uname -r) - local headers_package="linux-headers-${kernel_version}" - - # Check if headers are already installed - if dpkg -s "$headers_package" >/dev/null 2>&1; then - msg_ok "$(translate "Kernel headers are already installed")" - else - msg_info "$(translate "Installing kernel headers...")" - if /usr/bin/env DEBIAN_FRONTEND=noninteractive apt-get -y -o Dpkg::Options::='--force-confdef' install "$headers_package" > /dev/null 2>&1; then - msg_ok "$(translate "Kernel headers installed successfully")" - else - msg_error "$(translate "Failed to install kernel headers")" - return 1 - fi - fi - - msg_success "$(translate "Kernel headers installation process completed")" -} - - # ========================================================== @@ -333,6 +317,7 @@ EOF msg_ok "$(translate "Kernel panic configuration updated and applied")" + register_tool "kernel_panic" true msg_success "$(translate "Kernel panic behavior configuration completed")" } @@ -429,6 +414,7 @@ fs.file-max = 9223372036854775807 fs.aio-max-nr = 1048576" msg_ok "$(translate "Max FS open files configuration created successfully")" + register_tool "system_limits" true msg_success "$(translate "System limits increase completed.")" } @@ -439,26 +425,6 @@ fs.aio-max-nr = 1048576" -skip_apt_languages_() { - msg_info2 "$(translate "Configuring APT to skip downloading additional languages")" - - local config_file="/etc/apt/apt.conf.d/99-disable-translations" - local config_content="Acquire::Languages \"none\";" - - msg_info "$(translate "Setting APT language configuration...")" - - if [ -f "$config_file" ] && grep -q "$config_content" "$config_file"; then - msg_ok "$(translate "APT language configuration updated")" - else - echo -e "$config_content\n" > "$config_file" - msg_ok "$(translate "APT language configuration updated")" - fi - - msg_success "$(translate "APT configured to skip downloading additional languages")" -} - - - skip_apt_languages() { msg_info2 "$(translate "Configuring APT to skip downloading additional languages")" @@ -501,6 +467,7 @@ skip_apt_languages() { msg_ok "$(translate "APT language configuration updated")" fi + register_tool "apt_languages" true msg_success "$(translate "APT configured to skip downloading additional languages")" } @@ -514,47 +481,6 @@ skip_apt_languages() { -configure_time_sync_() { - msg_info2 "$(translate "Configuring system time settings...")" - - - # Get public IP address - 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 - # Get timezone based on IP - 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 - - # Set the timezone - if timedatectl set-timezone "$timezone"; then - msg_ok "$(translate "Timezone set to $timezone")" - else - msg_error "$(translate "Failed to set timezone to $timezone")" - fi - - # Configure time synchronization - msg_info "$(translate "Enabling automatic time synchronization...")" - if timedatectl set-ntp true; then - systemctl restart postfix 2>/dev/null || true - msg_ok "$(translate "Automatic time synchronization enabled")" - register_tool "time_sync" true - msg_success "$(translate "Time settings configuration completed")" - else - msg_error "$(translate "Failed to enable automatic time synchronization")" - fi - - -} - @@ -600,467 +526,26 @@ configure_time_sync() { -install_system_utils_() { - command_exists() { - command -v "$1" >/dev/null 2>&1 - } -ensure_repositories_() { - local sources_file="/etc/apt/sources.list" - local need_update=false - if [[ ! -f "$sources_file" ]]; then - msg_warn "$(translate "sources.list not found, creating default Debian repository...")" - cat > "$sources_file" << EOF -# Default Debian ${OS_CODENAME} repository -deb http://deb.debian.org/debian ${OS_CODENAME} main contrib non-free non-free-firmware -EOF - need_update=true - else - if ! grep -q "deb.*${OS_CODENAME}.*main" "$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 - fi - if [[ "$need_update" == true ]] || ! apt list --installed >/dev/null 2>&1; then - msg_info "$(translate "Updating APT package lists...")" - apt-get update -o Acquire::AllowInsecureRepositories=true >/dev/null 2>&1 - fi - return 0 -} -ensure_repositories() { - local pve_version need_update=false - pve_version=$(pveversion 2>/dev/null | grep -oP 'pve-manager/\K[0-9]+' | head -1) - if [[ -z "$pve_version" ]]; then - msg_error "Unable to detect Proxmox version." - return 1 - fi - if (( pve_version >= 9 )); then - # ===== PVE 9 (Debian 13 - trixie) ===== - # proxmox.sources (no-subscription) ─ create if missing - if [[ ! -f /etc/apt/sources.list.d/proxmox.sources ]]; then - cat > /etc/apt/sources.list.d/proxmox.sources <<'EOF' -Enabled: true -Types: deb -URIs: http://download.proxmox.com/debian/pve -Suites: trixie -Components: pve-no-subscription -Signed-By: /usr/share/keyrings/proxmox-archive-keyring.gpg -EOF - need_update=true - fi - # debian.sources ─ create if missing - if [[ ! -f /etc/apt/sources.list.d/debian.sources ]]; then - cat > /etc/apt/sources.list.d/debian.sources <<'EOF' -Types: deb -URIs: http://deb.debian.org/debian/ -Suites: trixie trixie-updates -Components: main contrib non-free-firmware -Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg -Types: deb -URIs: http://security.debian.org/debian-security/ -Suites: trixie-security -Components: main contrib non-free-firmware -Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg -EOF - need_update=true - fi - # apt-get update only if needed or lists are empty - if [[ "$need_update" == true ]] || [[ ! -d /var/lib/apt/lists || -z "$(ls -A /var/lib/apt/lists 2>/dev/null)" ]]; then - msg_info "$(translate "Updating APT package lists...")" - apt-get update >/dev/null 2>&1 || apt-get update - fi - else - # ===== PVE 8 (Debian 12 - bookworm) ===== - local sources_file="/etc/apt/sources.list" - - # Debian base (create or append minimal lines if missing) - if ! grep -qE 'deb .* bookworm .* main' "$sources_file" 2>/dev/null; then - { - echo "deb http://deb.debian.org/debian bookworm main contrib non-free non-free-firmware" - echo "deb http://deb.debian.org/debian bookworm-updates main contrib non-free non-free-firmware" - echo "deb http://security.debian.org/debian-security bookworm-security main contrib non-free non-free-firmware" - } >> "$sources_file" - need_update=true - fi - - # Proxmox no-subscription list (classic) if missing - if [[ ! -f /etc/apt/sources.list.d/pve-no-subscription.list ]]; then - echo "deb http://download.proxmox.com/debian/pve bookworm pve-no-subscription" \ - > /etc/apt/sources.list.d/pve-no-subscription.list - need_update=true - fi - fi - - # apt-get update only if needed or lists are empty - if [[ "$need_update" == true ]] || [[ ! -d /var/lib/apt/lists || -z "$(ls -A /var/lib/apt/lists 2>/dev/null)" ]]; then - msg_info "$(translate "Updating APT package lists...")" - apt-get update >/dev/null 2>&1 || apt-get update - fi - - return 0 -} - - - - - - - - - - - - - - - - - - install_single_package() { - local package="$1" - local command_name="${2:-$package}" - local description="$3" - - msg_info "$(translate "Installing") $package ($description)..." - local install_success=false - - if apt install -y "$package" >/dev/null 2>&1; then - install_success=true - fi - - cleanup - - if [ "$install_success" = true ]; then - hash -r 2>/dev/null - sleep 1 - if command_exists "$command_name"; then - msg_ok "$package $(translate "installed correctly and available")" - return 0 - else - msg_warn "$package $(translate "installed but command not immediately available")" - msg_info2 "$(translate "May need to restart terminal")" - return 2 - fi - else - msg_error "$(translate "Error installing") $package" - return 1 - fi - } - - show_utilities_selection() { - local utilities=( - "axel" "$(translate "Download accelerator")" "OFF" - "dos2unix" "$(translate "Convert DOS/Unix text files")" "OFF" - "grc" "$(translate "Generic log/command colorizer")" "OFF" - "htop" "$(translate "Interactive process viewer")" "OFF" - "btop" "$(translate "Modern resource monitor")" "OFF" - "iftop" "$(translate "Real-time network usage")" "OFF" - "iotop" "$(translate "Monitor disk I/O usage")" "OFF" - #"iperf3" "$(translate "Network performance testing")" "OFF" - "ipset" "$(translate "Manage IP sets")" "OFF" - "iptraf-ng" "$(translate "Network monitoring tool")" "OFF" - "mlocate" "$(translate "Locate files quickly")" "OFF" - "msr-tools" "$(translate "Access CPU MSRs")" "OFF" - "net-tools" "$(translate "Legacy networking tools")" "OFF" - "sshpass" "$(translate "Non-interactive SSH login")" "OFF" - "tmux" "$(translate "Terminal multiplexer")" "OFF" - "unzip" "$(translate "Extract ZIP files")" "OFF" - "zip" "$(translate "Create ZIP files")" "OFF" - "s-tui" "$(translate "Stress-Terminal UI")" "OFF" - "libguestfs-tools" "$(translate "VM disk utilities")" "OFF" - "aria2" "$(translate "Multi-source downloader")" "OFF" - "cabextract" "$(translate "Extract CAB files")" "OFF" - "wimtools" "$(translate "Manage WIM images")" "OFF" - "genisoimage" "$(translate "Create ISO images")" "OFF" - "chntpw" "$(translate "Edit Windows registry/passwords")" "OFF" - ) - - local selected - selected=$(dialog --clear --backtitle "ProxMenux - $(translate "System Utilities")" \ - --title "$(translate "Select utilities to install")" \ - --checklist "$(translate "Use SPACE to select/deselect, ENTER to confirm")" \ - 20 70 12 "${utilities[@]}" 2>&1 >/dev/tty) - - echo "$selected" - } - - install_selected_utilities() { - local selected="$1" - - if [ -z "$selected" ]; then - dialog --clear --backtitle "ProxMenux" \ - --title "$(translate "No Selection")" \ - --msgbox "$(translate "No utilities were selected")" 8 40 - return - fi - - clear - show_proxmenux_logo - msg_title "$SCRIPT_TITLE" - msg_info2 "$(translate "Installing selected utilities")" - - - if ! ensure_repositories; then - msg_error "$(translate "Failed to configure repositories. Installation aborted.")" - return 1 - fi - - local failed=0 - local success=0 - local warning=0 - local selected_array - IFS=' ' read -ra selected_array <<< "$selected" - - declare -A package_to_command=( - ["mlocate"]="locate" - ["msr-tools"]="rdmsr" - ["net-tools"]="netstat" - ["libguestfs-tools"]="virt-filesystems" - ["aria2"]="aria2c" - ["wimtools"]="wimlib-imagex" - ) - - for util in "${selected_array[@]}"; do - util=$(echo "$util" | tr -d '"') - local verify_command="${package_to_command[$util]:-$util}" - install_single_package "$util" "$verify_command" "$util" - local install_result=$? - - case $install_result in - 0) success=$((success + 1)) ;; - 1) failed=$((failed + 1)) ;; - 2) warning=$((warning + 1)) ;; - esac - sleep 2 - done - - if [ -f ~/.bashrc ]; then - source ~/.bashrc >/dev/null 2>&1 - fi - - hash -r 2>/dev/null - echo - msg_info2 "$(translate "Installation summary"):" - msg_ok "$(translate "Successful"): $success" - if [ $warning -gt 0 ]; then - msg_warn "$(translate "Warnings"): $warning" - fi - if [ $failed -gt 0 ]; then - msg_error "$(translate "Failed"): $failed" - fi - msg_success "$(translate "Common system utilities installation completed")" - } - - - local selected_utilities - selected_utilities=$(show_utilities_selection) - if [ -n "$selected_utilities" ]; then - install_selected_utilities "$selected_utilities" - fi -} - - - - - - - - - - - -install_system_utils() { - command_exists() { command -v "$1" >/dev/null 2>&1; } - - ensure_repositories() { - local sources_file="/etc/apt/sources.list" - local need_update=false - - if [[ ! -f "$sources_file" ]]; then - msg_warn "$(translate "sources.list not found, creating default Debian repository...")" - cat > "$sources_file" << EOF -# Default Debian ${OS_CODENAME} repository -deb http://deb.debian.org/debian ${OS_CODENAME} main contrib non-free non-free-firmware -EOF - need_update=true - else - if ! grep -q "deb.*${OS_CODENAME}.*main" "$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 - fi - - if [[ "$need_update" == true ]] || ! apt list --installed >/dev/null 2>&1; then - msg_info "$(translate "Updating APT package lists...")" - apt-get update -o Acquire::AllowInsecureRepositories=true >/dev/null 2>&1 - fi - return 0 - } - - install_single_package() { - local package="$1" - local command_name="${2:-$package}" - local description="$3" - - msg_info "$(translate "Installing") $package ($description)..." - local install_success=false - - DEBIAN_FRONTEND=noninteractive apt-get install -y "$package" >/dev/null 2>&1 && install_success=true - cleanup - - if [[ "$install_success" == true ]]; then - hash -r 2>/dev/null - sleep 1 - if command_exists "$command_name"; then - msg_ok "$package $(translate "installed correctly and available")" - return 0 - else - msg_warn "$package $(translate "installed but command not immediately available")" - msg_info2 "$(translate "May need to restart terminal")" - return 2 - fi - else - msg_error "$(translate "Error installing") $package" - return 1 - fi - } - - show_utilities_selection() { - local utilities=( - "axel" "$(translate "Download accelerator")" "OFF" - "dos2unix" "$(translate "Convert DOS/Unix text files")" "OFF" - "grc" "$(translate "Generic log/command colorizer")" "OFF" - "htop" "$(translate "Interactive process viewer")" "OFF" - "btop" "$(translate "Modern resource monitor")" "OFF" - "iftop" "$(translate "Real-time network usage")" "OFF" - "iotop" "$(translate "Monitor disk I/O usage")" "OFF" - # "iperf3" "$(translate "Network performance testing")" "OFF" - "intel-gpu-tools" "$(translate "tools for the Intel graphics driver")" "OFF" - "ipset" "$(translate "Manage IP sets")" "OFF" - "iptraf-ng" "$(translate "Network monitoring tool")" "OFF" - "s-tui" "$(translate "Stress-Terminal UI")" "OFF" - "plocate" "$(translate "Locate files quickly")" "OFF" - "msr-tools" "$(translate "Access CPU MSRs")" "OFF" - "net-tools" "$(translate "Legacy networking tools")" "OFF" - "sshpass" "$(translate "Non-interactive SSH login")" "OFF" - "tmux" "$(translate "Terminal multiplexer")" "OFF" - "unzip" "$(translate "Extract ZIP files")" "OFF" - "zip" "$(translate "Create ZIP files")" "OFF" - "libguestfs-tools" "$(translate "VM disk utilities")" "OFF" - "aria2" "$(translate "Multi-source downloader")" "OFF" - "cabextract" "$(translate "Extract CAB files")" "OFF" - "wimtools" "$(translate "Manage WIM images")" "OFF" - "genisoimage" "$(translate "Create ISO images")" "OFF" - "chntpw" "$(translate "Edit Windows registry/passwords")" "OFF" - ) - - local selected - selected=$( - dialog --clear --backtitle "ProxMenux - $(translate "System Utilities")" \ - --title "$(translate "Select utilities to install")" \ - --checklist "$(translate "Use SPACE to select/deselect, ENTER to confirm")" \ - 20 70 12 "${utilities[@]}" 3>&1 1>&2 2>&3 - ) - local status=$? - - - echo "$selected" - return "$status" - } - - install_selected_utilities() { - local selected="$1" - - - if [[ -z "$selected" ]]; then - dialog --clear --backtitle "ProxMenux" \ - --title "$(translate "No Selection")" \ - --msgbox "$(translate "No utilities were selected")" 8 40 - return 0 - fi - - - show_proxmenux_logo - msg_title "$SCRIPT_TITLE" - msg_info2 "$(translate "Installing selected utilities")" - - if ! ensure_repositories; then - msg_error "$(translate "Failed to configure repositories. Installation aborted.")" - return 1 - fi - - local failed=0 success=0 warning=0 - local selected_array - IFS=' ' read -ra selected_array <<< "$selected" - - declare -A package_to_command=( - ["plocate"]="locate" - ["msr-tools"]="rdmsr" - ["net-tools"]="netstat" - ["libguestfs-tools"]="virt-filesystems" - ["aria2"]="aria2c" - ["wimtools"]="wimlib-imagex" - ) - - for util in "${selected_array[@]}"; do - util="${util%\"}"; util="${util#\"}" - local verify_command="${package_to_command[$util]:-$util}" - install_single_package "$util" "$verify_command" "$util" - case $? in - 0) success=$((success+1)) ;; - 1) failed=$((failed+1)) ;; - 2) warning=$((warning+1)) ;; - esac - sleep 1 - done - - [[ -f ~/.bashrc ]] && source ~/.bashrc >/dev/null 2>&1 - hash -r 2>/dev/null - - echo - msg_info2 "$(translate "Installation summary"):" - msg_ok "$(translate "Successful"): $success" - (( warning > 0 )) && msg_warn "$(translate "Warnings"): $warning" - (( failed > 0 )) && msg_error "$(translate "Failed"): $failed" - msg_success "$(translate "Common system utilities installation completed")" - return 0 - } - - - local selected_utilities - selected_utilities=$(show_utilities_selection) - local dlg_status=$? - - if [[ $dlg_status -ne 0 ]]; then - dialog --clear --backtitle "ProxMenux" \ - --title "$(translate "Canceled")" \ - --msgbox "$(translate "Action canceled by user")" 8 40 - - show_proxmenux_logo - return 0 - fi - - install_selected_utilities "$selected_utilities" -} @@ -1095,6 +580,7 @@ EOF systemctl enable haveged > /dev/null 2>&1 msg_ok "$(translate "haveged service enabled successfully")" + register_tool "entropy" true msg_success "$(translate "Entropy generation configuration completed")" } @@ -1107,74 +593,6 @@ EOF -apply_amd_fixes_() { - msg_info2 "$(translate "Detecting AMD CPU and applying fixes if necessary...")" - NECESSARY_REBOOT=1 - - local cpu_model=$(grep -i -m 1 "model name" /proc/cpuinfo) - if echo "$cpu_model" | grep -qi "EPYC"; then - msg_info "$(translate "AMD EPYC CPU detected")" - elif echo "$cpu_model" | grep -qi "Ryzen"; then - msg_info "$(translate "AMD Ryzen CPU detected")" - else - msg_ok "$(translate "No AMD CPU detected. Skipping AMD fixes.")" - return - fi - - msg_info "$(translate "Applying AMD-specific fixes...")" - - # Apply kernel fix for random crashing and instability - local grub_file="/etc/default/grub" - if ! grep -q "idle=nomwait" "$grub_file"; then - msg_info "$(translate "Setting kernel parameter: idle=nomwait")" - if sed -i 's/GRUB_CMDLINE_LINUX_DEFAULT="/GRUB_CMDLINE_LINUX_DEFAULT="idle=nomwait /g' "$grub_file"; then - msg_ok "$(translate "Kernel parameter set successfully")" - if update-grub > /dev/null 2>&1; then - msg_ok "$(translate "GRUB configuration updated")" - else - msg_warn "$(translate "Failed to update GRUB configuration")" - fi - else - msg_warn "$(translate "Failed to set kernel parameter")" - fi - else - msg_info "$(translate "Kernel parameter 'idle=nomwait' already set")" - fi - - # Add MSR ignore to fix Windows guest on EPYC/Ryzen host - local kvm_conf="/etc/modprobe.d/kvm.conf" - msg_info "$(translate "Configuring KVM to ignore MSRs...")" - if ! grep -q "options kvm ignore_msrs=Y" "$kvm_conf"; then - echo "options kvm ignore_msrs=Y" >> "$kvm_conf" - msg_ok "$(translate "KVM ignore_msrs option added")" - else - msg_info "$(translate "KVM ignore_msrs option already set")" - fi - if ! grep -q "options kvm report_ignored_msrs=N" "$kvm_conf"; then - echo "options kvm report_ignored_msrs=N" >> "$kvm_conf" - msg_ok "$(translate "KVM report_ignored_msrs option added")" - else - msg_info "$(translate "KVM report_ignored_msrs option already set")" - fi - - # Install the latest Proxmox VE kernel - msg_info "$(translate "Checking for Proxmox VE kernel updates...")" - local current_kernel=$(uname -r | cut -d'-' -f1-2) - local latest_kernel=$(apt-cache search pve-kernel | grep "^pve-kernel-${current_kernel}" | sort -V | tail -n1 | cut -d' ' -f1) - - if [ "$latest_kernel" != "pve-kernel-$current_kernel" ]; then - msg_info "$(translate "Installing the latest Proxmox VE kernel...")" - if /usr/bin/env DEBIAN_FRONTEND=noninteractive apt-get -y -o Dpkg::Options::='--force-confdef' install "$latest_kernel" > /dev/null 2>&1; then - msg_ok "$(translate "Latest Proxmox VE kernel installed successfully")" - else - msg_warn "$(translate "Failed to install the latest Proxmox VE kernel")" - fi - else - msg_ok "$(translate "The latest Proxmox VE kernel is already installed")" - fi - - msg_success "$(translate "AMD CPU fixes applied successfully")" -} @@ -1273,6 +691,7 @@ apply_amd_fixes() { fi msg_success "$(translate "AMD CPU fixes applied successfully")" + register_tool "amd_fixes" true } @@ -1301,6 +720,7 @@ force_apt_ipv4() { fi fi + register_tool "apt_ipv4" true msg_success "$(translate "APT IPv4 configuration completed")" } @@ -1333,13 +753,13 @@ net.ipv4.conf.all.accept_redirects = 0 net.ipv4.conf.all.accept_source_route = 0 net.ipv4.conf.all.secure_redirects = 0 net.ipv4.conf.all.send_redirects = 0 -net.ipv4.conf.all.log_martians = 1 +net.ipv4.conf.all.log_martians = 0 net.ipv4.conf.default.accept_redirects = 0 net.ipv4.conf.default.accept_source_route = 0 net.ipv4.conf.default.secure_redirects = 0 net.ipv4.conf.default.send_redirects = 0 -net.ipv4.conf.default.log_martians = 1 +net.ipv4.conf.default.log_martians = 0 net.ipv4.conf.all.rp_filter = 2 net.ipv4.conf.default.rp_filter = 2 @@ -1906,268 +1326,12 @@ EOF -install_fail2ban_() { - msg_info2 "$(translate "Installing and configuring Fail2Ban to protect the web interface...")" - - -# if dpkg -l | grep -qw fail2ban; then -# msg_info "$(translate "Removing existing Fail2Ban installation...")" -# apt-get remove --purge -y fail2ban >/dev/null 2>&1 -# rm -rf /etc/fail2ban /var/lib/fail2ban /var/run/fail2ban -# msg_ok "$(translate "Fail2Ban removed successfully")" -# else -# msg_ok "$(translate "Fail2Ban was not installed")" -# fi - - - msg_info "$(translate "Installing Fail2Ban...")" - apt-get update >/dev/null 2>&1 && apt-get install -y fail2ban >/dev/null 2>&1 - if [[ $? -eq 0 ]]; then - msg_ok "$(translate "Fail2Ban installed successfully")" - else - msg_error "$(translate "Failed to install Fail2Ban")" - return 1 - fi - - - mkdir -p /etc/fail2ban/jail.d /etc/fail2ban/filter.d - - - msg_info "$(translate "Configuring Proxmox filter...")" - cat > /etc/fail2ban/filter.d/proxmox.conf << EOF -[Definition] -failregex = pvedaemon\[.*authentication failure; rhost= user=.* msg=.* -ignoreregex = -EOF - msg_ok "$(translate "Proxmox filter configured")" - - - msg_info "$(translate "Configuring Proxmox jail...")" - cat > /etc/fail2ban/jail.d/proxmox.conf << EOF -[proxmox] -enabled = true -port = https,http,8006,8007 -filter = proxmox -logpath = /var/log/daemon.log -maxretry = 3 -bantime = 3600 -findtime = 600 -EOF - msg_ok "$(translate "Proxmox jail configured")" - - - msg_info "$(translate "Configuring general Fail2Ban settings...")" - cat > /etc/fail2ban/jail.local << EOF -[DEFAULT] -ignoreip = 127.0.0.1 -bantime = 86400 -maxretry = 2 -findtime = 1800 - -[ssh-iptables] -enabled = true -filter = sshd -action = iptables[name=SSH, port=ssh, protocol=tcp] -logpath = /var/log/auth.log -maxretry = 2 -findtime = 3600 -bantime = 32400 -EOF - msg_ok "$(translate "General Fail2Ban settings configured")" - - - msg_info "$(translate "Stopping Fail2Ban service...")" - systemctl stop fail2ban >/dev/null 2>&1 - msg_ok "$(translate "Fail2Ban service stopped")" - - - msg_info "$(translate "Ensuring authentication logs exist...")" - touch /var/log/auth.log /var/log/daemon.log - chown root:adm /var/log/auth.log /var/log/daemon.log - chmod 640 /var/log/auth.log /var/log/daemon.log - msg_ok "$(translate "Authentication logs verified")" - - - if [[ ! -f /var/log/auth.log && -f /var/log/secure ]]; then - msg_warn "$(translate "Using /var/log/secure instead of /var/log/auth.log")" - sed -i 's|logpath = /var/log/auth.log|logpath = /var/log/secure|' /etc/fail2ban/jail.local - fi - - - msg_info "$(translate "Ensuring Fail2Ban runtime directory exists...")" - mkdir -p /var/run/fail2ban - chown root:root /var/run/fail2ban - chmod 755 /var/run/fail2ban - msg_ok "$(translate "Fail2Ban runtime directory verified")" - - - msg_info "$(translate "Removing old Fail2Ban database (if exists)...")" - rm -f /var/lib/fail2ban/fail2ban.sqlite3 - msg_ok "$(translate "Fail2Ban database reset")" - - - msg_info "$(translate "Reloading systemd and restarting Fail2Ban...")" - systemctl daemon-reload - systemctl enable fail2ban >/dev/null 2>&1 - systemctl restart fail2ban >/dev/null 2>&1 - msg_ok "$(translate "Fail2Ban service restarted")" - - - sleep 3 - - - msg_info "$(translate "Checking Fail2Ban service status...")" - if systemctl is-active --quiet fail2ban; then - msg_ok "$(translate "Fail2Ban is running correctly")" - else - msg_error "$(translate "Fail2Ban is NOT running! Checking logs...")" - journalctl -u fail2ban --no-pager -n 20 - - fi - - - msg_info "$(translate "Checking Fail2Ban socket...")" - if [ -S /var/run/fail2ban/fail2ban.sock ]; then - msg_ok "$(translate "Fail2Ban socket exists!")" - else - msg_warn "$(translate "Warning: Fail2Ban socket does not exist!")" - fi - - - msg_info "$(translate "Testing fail2ban-client...")" - if fail2ban-client ping >/dev/null 2>&1; then - msg_ok "$(translate "fail2ban-client successfully communicated with the server")" - else - msg_error "$(translate "fail2ban-client could not communicate with the server")" - - fi - - - msg_info "$(translate "Displaying Fail2Ban status...")" - fail2ban-client status >/dev/null 2>&1 - msg_ok "$(translate "Fail2Ban status displayed")" - - msg_success "$(translate "Fail2Ban installation and configuration completed successfully!")" - -} -install_fail2ban() { - msg_info2 "$(translate "Installing and configuring Fail2Ban to protect Proxmox web interface and SSH...")" - - - local deb_codename - deb_codename=$(grep -oP '^VERSION_CODENAME=\K.*' /etc/os-release 2>/dev/null) - - - if ! grep -RqsE "debian.*(bookworm|trixie)" /etc/apt/sources.list /etc/apt/sources.list.d 2>/dev/null; then - msg_warn "$(translate "Debian repositories missing; creating default source file")" - local src="/etc/apt/sources.list.d/debian.sources" - cat > "$src" </dev/null 2>&1 || \ - ! DEBIAN_FRONTEND=noninteractive apt-get install -y fail2ban >/dev/null 2>&1; then - msg_error "$(translate "Failed to install Fail2Ban")" - return 1 - fi - msg_ok "$(translate "Fail2Ban installed successfully")" - - - mkdir -p /etc/fail2ban/filter.d /etc/fail2ban/jail.d - msg_info "$(translate "Configuring Proxmox filter...")" - cat > /etc/fail2ban/filter.d/proxmox.conf <<'EOF' -[Definition] -failregex = pvedaemon\[.*authentication failure; rhost= user=.* msg=.* -ignoreregex = -EOF - msg_ok "$(translate "Proxmox filter configured")" - - - msg_info "$(translate "Configuring Proxmox jail...")" - cat > /etc/fail2ban/jail.d/proxmox.conf <<'EOF' -[proxmox] -enabled = true -port = 8006 -filter = proxmox -logpath = /var/log/daemon.log -maxretry = 3 -bantime = 3600 -findtime = 600 -EOF - msg_ok "$(translate "Proxmox jail configured")" - - - msg_info "$(translate "Configuring global Fail2Ban settings and SSH jail...")" - cat > /etc/fail2ban/jail.local <<'EOF' -[DEFAULT] -ignoreip = 127.0.0.1 -bantime = 86400 -maxretry = 2 -findtime = 1800 -backend = systemd -banaction = nftables -banaction_allports = nftables[type=allports] - -[sshd] -enabled = true -filter = sshd -logpath = /var/log/auth.log -maxretry = 2 -findtime = 3600 -bantime = 32400 -EOF - msg_ok "$(translate "Global settings and SSH jail configured")" - - - touch /var/log/auth.log /var/log/daemon.log - chown root:adm /var/log/auth.log /var/log/daemon.log 2>/dev/null || true - chmod 640 /var/log/auth.log /var/log/daemon.log 2>/dev/null || true - - - systemctl daemon-reload - systemctl enable --now fail2ban >/dev/null 2>&1 - sleep 2 - - - if systemctl is-active --quiet fail2ban; then - msg_ok "$(translate "Fail2Ban is running correctly")" - else - msg_error "$(translate "Fail2Ban is NOT running!")" - journalctl -u fail2ban --no-pager -n 20 - fi - - if [ -S /var/run/fail2ban/fail2ban.sock ]; then - msg_ok "$(translate "Fail2Ban socket exists!")" - else - msg_warn "$(translate "Warning: Fail2Ban socket does not exist!")" - fi - - if fail2ban-client ping >/dev/null 2>&1; then - msg_ok "$(translate "fail2ban-client successfully communicated with the server")" - else - msg_error "$(translate "fail2ban-client could not communicate with the server")" - fi - - msg_success "$(translate "Fail2Ban installation and configuration completed successfully!")" -} @@ -2180,72 +1344,7 @@ EOF -install_lynis_() { - msg_info2 "$(translate "Installing Lynis security scan tool...")" - # Install Lynis directly from Debian repositories - msg_info "$(translate "Installing Lynis packages...")" - ( - /usr/bin/env DEBIAN_FRONTEND=noninteractive apt-get -y -o Dpkg::Options::='--force-confdef' install lynis 2>&1 | \ - while IFS= read -r line; do - if [[ $line == *"Installing"* ]] || [[ $line == *"Unpacking"* ]]; then - printf "\r%-$(($(tput cols)-1))s\r" " " # Clear current line - printf "\r%s" "$line" - fi - done - ) - - if [ $? -eq 0 ]; then - printf "\r%-$(($(tput cols)-1))s\r" " " # Clear final line - msg_ok "$(translate "Lynis installed successfully")" - else - printf "\r%-$(($(tput cols)-1))s\r" " " # Clear final line - msg_warn "$(translate "Failed to install Lynis")" - fi - - # Verify installation - if command -v lynis >/dev/null 2>&1; then - msg_success "$(translate "Lynis is ready to use")" - else - msg_warn "$(translate "Lynis installation could not be verified")" - fi -} - - -install_lynis() { - msg_info2 "$(translate "Installing latest Lynis security scan tool...")" - - if ! command -v git >/dev/null 2>&1; then - msg_info "$(translate "Installing Git as a prerequisite...")" - apt-get update -qq >/dev/null 2>&1 - apt-get install -y git >/dev/null 2>&1 - msg_ok "$(translate "Git installed")" - fi - - if [ -d /opt/lynis ]; then - rm -rf /opt/lynis >/dev/null 2>&1 - fi - - msg_info "$(translate "Cloning Lynis from GitHub...")" - if git clone --quiet https://github.com/CISOfy/lynis.git /opt/lynis >/dev/null 2>&1; then - # Create wrapper script instead of symbolic link - cat << 'EOF' > /usr/local/bin/lynis -#!/bin/bash -cd /opt/lynis && ./lynis "$@" -EOF - chmod +x /usr/local/bin/lynis - msg_ok "$(translate "Lynis installed successfully from GitHub")" - else - msg_warn "$(translate "Failed to clone Lynis from GitHub")" - return 1 - fi - - if /usr/local/bin/lynis show version >/dev/null 2>&1; then - msg_success "$(translate "Lynis is ready to use")" - else - msg_warn "$(translate "Lynis installation could not be verified")" - fi -} @@ -2303,51 +1402,6 @@ install_guest_agent() { -configure_ksmtuned() { - msg_info2 "$(translate "Installing and configuring KSM (Kernel Samepage Merging) daemon...")" - NECESSARY_REBOOT=1 - - # Install ksm-control-daemon - msg_info "$(translate "Installing ksm-control-daemon...")" - if /usr/bin/env DEBIAN_FRONTEND=noninteractive apt-get -y -o Dpkg::Options::='--force-confdef' install ksm-control-daemon > /dev/null 2>&1; then - msg_ok "$(translate "ksm-control-daemon installed successfully")" - fi - - # Determine RAM size and set KSM parameters - if [[ RAM_SIZE_GB -le 16 ]]; then - KSM_THRES_COEF=50 - KSM_SLEEP_MSEC=80 - msg_info "$(translate "RAM <= 16GB: Setting KSM to start at 50% full")" - elif [[ RAM_SIZE_GB -le 32 ]]; then - KSM_THRES_COEF=40 - KSM_SLEEP_MSEC=60 - msg_info "$(translate "RAM <= 32GB: Setting KSM to start at 60% full")" - elif [[ RAM_SIZE_GB -le 64 ]]; then - KSM_THRES_COEF=30 - KSM_SLEEP_MSEC=40 - msg_info "$(translate "RAM <= 64GB: Setting KSM to start at 70% full")" - elif [[ RAM_SIZE_GB -le 128 ]]; then - KSM_THRES_COEF=20 - KSM_SLEEP_MSEC=20 - msg_info "$(translate "RAM <= 128GB: Setting KSM to start at 80% full")" - else - KSM_THRES_COEF=10 - KSM_SLEEP_MSEC=10 - msg_info "$(translate "RAM > 128GB: Setting KSM to start at 90% full")" - fi - # Update ksmtuned configuration - if sed -i -e "s/\# KSM_THRES_COEF=.*/KSM_THRES_COEF=${KSM_THRES_COEF}/g" /etc/ksmtuned.conf && \ - sed -i -e "s/\# KSM_SLEEP_MSEC=.*/KSM_SLEEP_MSEC=${KSM_SLEEP_MSEC}/g" /etc/ksmtuned.conf; then - msg_ok "$(translate "ksmtuned configuration updated successfully")" - fi - - # Enable ksmtuned service - if systemctl enable ksmtuned > /dev/null 2>&1; then - msg_ok "$(translate "ksmtuned service enabled successfully")" - fi - - msg_success "$(translate "KSM configuration completed")" -} @@ -2359,190 +1413,6 @@ configure_ksmtuned() { -enable_vfio_iommu_() { - msg_info2 "$(translate "Enabling IOMMU and configuring VFIO for PCI passthrough...")" - NECESSARY_REBOOT=1 - - # Detect if system uses ZFS - local uses_zfs=false - local cmdline_file="/etc/kernel/cmdline" - if [[ -f "$cmdline_file" && $(grep -q "root=ZFS=" "$cmdline_file") ]]; then - uses_zfs=true - fi - - # Enable IOMMU - local cpu_info=$(cat /proc/cpuinfo) - local grub_file="/etc/default/grub" - local iommu_param="" - local additional_params="pcie_acs_override=downstream,multifunction nofb nomodeset video=vesafb:off,efifb:off" - - if [[ "$cpu_info" == *"GenuineIntel"* ]]; then - msg_info "$(translate "Detected Intel CPU")" - iommu_param="intel_iommu=on" - elif [[ "$cpu_info" == *"AuthenticAMD"* ]]; then - msg_info "$(translate "Detected AMD CPU")" - iommu_param="amd_iommu=on" - else - msg_warning "$(translate "Unknown CPU type. IOMMU might not be properly enabled.")" - return 1 - fi - - if [[ "$uses_zfs" == true ]]; then - if grep -q "$iommu_param" "$cmdline_file"; then - if ! grep -q "iommu=pt" "$cmdline_file"; then - cp "$cmdline_file" "${cmdline_file}.bak" - sed -i "/^.*root=ZFS=/ s|$| iommu=pt|" "$cmdline_file" - msg_ok "$(translate "Added missing iommu=pt to ZFS configuration")" - else - msg_ok "$(translate "IOMMU and additional parameters already configured for ZFS")" - fi - else - cp "$cmdline_file" "${cmdline_file}.bak" - sed -i "/^.*root=ZFS=/ s|$| $iommu_param iommu=pt|" "$cmdline_file" - msg_ok "$(translate "IOMMU and additional parameters added for ZFS")" - fi - else - - if grep -q "$iommu_param" "$grub_file"; then - if ! grep -q "iommu=pt" "$grub_file"; then - cp "$grub_file" "${grub_file}.bak" - sed -i "/GRUB_CMDLINE_LINUX_DEFAULT=/ s|\"$| iommu=pt\"|" "$grub_file" - msg_ok "$(translate "Added missing iommu=pt to GRUB configuration")" - else - msg_ok "$(translate "IOMMU already enabled in GRUB configuration")" - fi - else - cp "$grub_file" "${grub_file}.bak" - sed -i "/GRUB_CMDLINE_LINUX_DEFAULT=/ s|\"$| $iommu_param iommu=pt\"|" "$grub_file" - msg_ok "$(translate "IOMMU enabled in GRUB configuration")" - fi - fi - - # Configure VFIO modules (avoid duplicates) - local modules_file="/etc/modules" - msg_info "$(translate "Checking VFIO modules...")" - local vfio_modules=("vfio" "vfio_iommu_type1" "vfio_pci" "vfio_virqfd") - - for module in "${vfio_modules[@]}"; do - grep -q "^$module" "$modules_file" || echo "$module" >> "$modules_file" - done - msg_ok "$(translate "VFIO modules configured.)")" - - # Blacklist conflicting drivers (avoid duplicates) - local blacklist_file="/etc/modprobe.d/blacklist.conf" - msg_info "$(translate "Checking conflicting drivers blacklist...")" - touch "$blacklist_file" - local blacklist_drivers=("nouveau" "lbm-nouveau" "amdgpu" "radeon" "nvidia" "nvidiafb") - - for driver in "${blacklist_drivers[@]}"; do - grep -q "^blacklist $driver" "$blacklist_file" || echo "blacklist $driver" >> "$blacklist_file" - done - - if ! grep -q "options nouveau modeset=0" "$blacklist_file"; then - echo "options nouveau modeset=0" >> "$blacklist_file" - fi - msg_ok "$(translate "Conflicting drivers blacklisted successfully.")" - - - # Propagate the settings - msg_info "$(translate "Updating initramfs, GRUB, and EFI boot, patience...")" - if update-initramfs -u -k all > /dev/null 2>&1 && \ - update-grub > /dev/null 2>&1 && \ - pve-efiboot-tool refresh > /dev/null 2>&1; then - msg_ok "$(translate "Initramfs, GRUB, and EFI boot updated successfully")" - else - msg_error "$(translate "Failed to update one or more components (initramfs, GRUB, or EFI boot)")" - fi - - msg_success "$(translate "IOMMU and VFIO setup completed")" -} - - - -enable_vfio_iommu__() { - msg_info2 "$(translate "Enabling IOMMU and configuring VFIO for PCI passthrough...")" - NECESSARY_REBOOT=1 - - # Detect if system uses ZFS/systemd-boot (Proxmox) - local uses_zfs=false - local cmdline_file="/etc/kernel/cmdline" - if [[ -f "$cmdline_file" ]] && grep -qE 'root=ZFS=|root=ZFS/' "$cmdline_file"; then - uses_zfs=true - fi - - # Enable IOMMU - local cpu_info=$(cat /proc/cpuinfo) - local grub_file="/etc/default/grub" - local iommu_param="" - local additional_params="pcie_acs_override=downstream,multifunction nofb nomodeset video=vesafb:off,efifb:off" - - if [[ "$cpu_info" == *"GenuineIntel"* ]]; then - msg_info "$(translate "Detected Intel CPU")" - iommu_param="intel_iommu=on" - elif [[ "$cpu_info" == *"AuthenticAMD"* ]]; then - msg_info "$(translate "Detected AMD CPU")" - iommu_param="amd_iommu=on" - else - msg_warning "$(translate "Unknown CPU type. IOMMU might not be properly enabled.")" - return 1 - fi - - if [[ "$uses_zfs" == true ]]; then - # --- SYSTEMD-BOOT: /etc/kernel/cmdline --- - if grep -q "$iommu_param" "$cmdline_file"; then - msg_ok "$(translate "IOMMU already configured in /etc/kernel/cmdline")" - else - cp "$cmdline_file" "${cmdline_file}.bak" - # sed -i "s|\"$| $iommu_param iommu=pt|" "$cmdline_file" - sed -i "s|\s*$| $iommu_param iommu=pt|" "$cmdline_file" - msg_ok "$(translate "IOMMU parameters added to /etc/kernel/cmdline")" - fi - else - # --- GRUB --- - if grep -q "$iommu_param" "$grub_file"; then - msg_ok "$(translate "IOMMU already enabled in GRUB configuration")" - else - cp "$grub_file" "${grub_file}.bak" - sed -i "/GRUB_CMDLINE_LINUX_DEFAULT=/ s|\"$| $iommu_param iommu=pt\"|" "$grub_file" - msg_ok "$(translate "IOMMU enabled in GRUB configuration")" - fi - fi - - # Configure VFIO modules (avoid duplicates) - local modules_file="/etc/modules" - msg_info "$(translate "Checking VFIO modules...")" - local vfio_modules=("vfio" "vfio_iommu_type1" "vfio_pci" "vfio_virqfd") - for module in "${vfio_modules[@]}"; do - grep -q "^$module" "$modules_file" || echo "$module" >> "$modules_file" - done - msg_ok "$(translate "VFIO modules configured.")" - - # Blacklist conflicting drivers (avoid duplicates) - local blacklist_file="/etc/modprobe.d/blacklist.conf" - msg_info "$(translate "Checking conflicting drivers blacklist...")" - touch "$blacklist_file" - local blacklist_drivers=("nouveau" "lbm-nouveau" "amdgpu" "radeon" "nvidia" "nvidiafb") - for driver in "${blacklist_drivers[@]}"; do - grep -q "^blacklist $driver" "$blacklist_file" || echo "blacklist $driver" >> "$blacklist_file" - done - if ! grep -q "options nouveau modeset=0" "$blacklist_file"; then - echo "options nouveau modeset=0" >> "$blacklist_file" - fi - msg_ok "$(translate "Conflicting drivers blacklisted successfully.")" - - # Propagate the settings - msg_info "$(translate "Updating initramfs, GRUB, and EFI boot, patience...")" - update-initramfs -u -k all > /dev/null 2>&1 - if [[ "$uses_zfs" == true ]]; then - proxmox-boot-tool refresh > /dev/null 2>&1 - else - update-grub > /dev/null 2>&1 - fi - - msg_success "$(translate "IOMMU and VFIO setup completed")" -} - - @@ -2654,11 +1524,19 @@ enable_vfio_iommu() { fi fi - # Configure VFIO modules (sin cambios) + # Configure VFIO modules local modules_file="/etc/modules" msg_info "$(translate "Checking VFIO modules...")" - local vfio_modules=("vfio" "vfio_iommu_type1" "vfio_pci" "vfio_virqfd") - + # vfio_virqfd was merged into the vfio module in kernel 6.2+ + # Adding it as a separate module on kernel >= 6.2 generates warnings + local kernel_major kernel_minor + kernel_major=$(uname -r | cut -d. -f1) + kernel_minor=$(uname -r | cut -d. -f2) + local vfio_modules=("vfio" "vfio_iommu_type1" "vfio_pci") + if (( kernel_major < 6 || ( kernel_major == 6 && kernel_minor < 2 ) )); then + vfio_modules+=("vfio_virqfd") + fi + for module in "${vfio_modules[@]}"; do if ! grep -q "^$module" "$modules_file"; then echo "$module" >> "$modules_file" @@ -2694,6 +1572,7 @@ enable_vfio_iommu() { fi msg_success "$(translate "IOMMU and VFIO setup completed")" + register_tool "vfio_iommu" true } @@ -2705,48 +1584,6 @@ enable_vfio_iommu() { -customize_bashrc_() { - msg_info2 "$(translate "Customizing bashrc for root user...")" - - local bashrc="/root/.bashrc" - local bash_profile="/root/.bash_profile" - - # Backup original .bashrc if it doesn't exist - if [ ! -f "${bashrc}.bak" ]; then - cp "$bashrc" "${bashrc}.bak" - fi - - # Function to add a line if it doesn't exist - add_line_if_not_exists() { - local line="$1" - local file="$2" - grep -qF -- "$line" "$file" || echo "$line" >> "$file" - } - - # Add custom configurations to .bashrc - add_line_if_not_exists 'export HISTTIMEFORMAT="%d/%m/%y %T "' "$bashrc" - add_line_if_not_exists 'export PS1='"'\u@\h:\W \$ '" "$bashrc" - add_line_if_not_exists "alias l='ls -CF'" "$bashrc" - add_line_if_not_exists "alias la='ls -A'" "$bashrc" - add_line_if_not_exists "alias ll='ls -alF'" "$bashrc" - add_line_if_not_exists "alias ls='ls --color=auto'" "$bashrc" - add_line_if_not_exists "alias grep='grep --color=auto'" "$bashrc" - add_line_if_not_exists "alias fgrep='fgrep --color=auto'" "$bashrc" - add_line_if_not_exists "alias egrep='egrep --color=auto'" "$bashrc" - add_line_if_not_exists "source /etc/profile.d/bash_completion.sh" "$bashrc" - add_line_if_not_exists '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\]\\$ "' "$bashrc" - - msg_ok "$(translate "Custom configurations added to .bashrc")" - - # Ensure .bashrc is sourced in .bash_profile - add_line_if_not_exists "source /root/.bashrc" "$bash_profile" - msg_ok "$(translate ".bashrc sourced in .bash_profile")" - - msg_success "$(translate "Bashrc customization completed")" -} - - - @@ -2769,7 +1606,7 @@ customize_bashrc() { fi - cat >> "$bashrc" << 'EOF' + cat >> "$bashrc" << EOF ${marker_begin} # ProxMenux core customizations export HISTTIMEFORMAT="%d/%m/%y %T " @@ -2878,6 +1715,7 @@ EOF systemctl restart logrotate > /dev/null 2>&1 msg_ok "$(translate "Logrotate service restarted successfully")" fi + register_tool "logrotate" true msg_success "$(translate "Logrotate optimization completed")" } @@ -2907,6 +1745,7 @@ remove_subscription_banner() { bash "$LOCAL_SCRIPTS/global/remove-banner-pve8.sh" fi + register_tool "subscription_banner" true } @@ -3266,19 +2105,6 @@ register_tool "fastfetch" true -add_repo_test() { - msg_info2 "$(translate "Enable Proxmox testing repository...")" - # Enable Proxmox testing repository - if [ ! -f /etc/apt/sources.list.d/pve-testing-repo.list ] || ! grep -q "pvetest" /etc/apt/sources.list.d/pve-testing-repo.list; then - msg_info "$(translate "Enabling Proxmox testing repository...")" - echo -e "deb http://download.proxmox.com/debian/pve ${OS_CODENAME} pvetest\\n" > /etc/apt/sources.list.d/pve-testing-repo.list - msg_ok "$(translate "Proxmox testing repository enabled")" - fi - msg_success "$(translate "Proxmox testing repository has been successfully enabled")" -} - - - @@ -3288,100 +2114,6 @@ add_repo_test() { -configure_figurine_() { - msg_info2 "$(translate "Installing and configuring Figurine...")" - local version="1.3.0" - local file="figurine_linux_amd64_v${version}.tar.gz" - local url="https://github.com/arsham/figurine/releases/download/v${version}/${file}" - local temp_dir; temp_dir=$(mktemp -d) - local install_dir="/usr/local/bin" - local profile_script="/etc/profile.d/figurine.sh" - local bin_path="${install_dir}/figurine" - local bashrc="/root/.bashrc" - - cleanup_dir() { rm -rf "$temp_dir" 2>/dev/null || true; } - trap cleanup_dir EXIT - - [[ -f "$bashrc" ]] || touch "$bashrc" - - if command -v figurine &>/dev/null; then - msg_info "$(translate "Updating Figurine binary...")" - else - msg_info "$(translate "Downloading Figurine v${version}...")" - fi - - if ! wget -qO "${temp_dir}/${file}" "$url"; then - msg_error "$(translate "Failed to download Figurine")" - return 1 - fi - - if ! tar -xf "${temp_dir}/${file}" -C "${temp_dir}"; then - msg_error "$(translate "Failed to extract package")" - return 1 - fi - msg_ok "$(translate "Extraction successful")" - - if [[ ! -f "${temp_dir}/deploy/figurine" ]]; then - msg_error "$(translate "Binary not found in extracted content.")" - return 1 - fi - - msg_info "$(translate "Installing binary to ${install_dir}...")" - install -m 0755 -o root -g root "${temp_dir}/deploy/figurine" "$bin_path" - - - cat > "$profile_script" << 'EOF' -/usr/local/bin/figurine -f "3d.flf" $(hostname) -EOF - chmod +x "$profile_script" - - - ensure_aliases() { - local bashrc="/root/.bashrc" - [[ -f "$bashrc" ]] || touch "$bashrc" - - local -a ALIASES=( - "aptup=apt update && apt dist-upgrade" - "lxcclean=curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/pve/clean-lxcs.sh | bash" - "lxcupdate=curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/pve/update-lxcs.sh | bash" - "kernelclean=curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/pve/kernel-clean.sh | bash" - "cpugov=curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/pve/scaling-governor.sh | bash" - "lxctrim=curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/pve/fstrim.sh | bash" - "updatecerts=pvecm updatecerts" - "seqwrite=sync; fio --randrepeat=1 --ioengine=libaio --direct=1 --name=test --filename=test --bs=4M --size=32G --readwrite=write --ramp_time=4" - "seqread=sync; fio --randrepeat=1 --ioengine=libaio --direct=1 --name=test --filename=test --bs=4M --size=32G --readwrite=read --ramp_time=4" - "ranwrite=sync; fio --randrepeat=1 --ioengine=libaio --direct=1 --name=test --filename=test --bs=4k --size=4G --readwrite=randwrite --ramp_time=4" - "ranread=sync; fio --randrepeat=1 --ioengine=libaio --direct=1 --name=test --filename=test --bs=4k --size=4G --readwrite=randread --ramp_time=4" - ) - - for entry in "${ALIASES[@]}"; do - local name="${entry%%=*}" - local cmd="${entry#*=}" - local esc_cmd - esc_cmd=$(printf "%s" "$cmd" | sed -e 's/[\\/&]/\\&/g') - - if grep -Eq "^alias[[:space:]]+$name=" "$bashrc"; then - if ! grep -Eq "^alias[[:space:]]+$name='${esc_cmd}'$" "$bashrc"; then - sed -i -E "s|^alias[[:space:]]+$name=.*$|alias $name='${esc_cmd}'|" "$bashrc" - fi - else - printf "alias %s='%s'\n" "$name" "$cmd" >> "$bashrc" - fi - done - - - awk '!seen[$0]++' "$bashrc" > "${bashrc}.tmp" && mv "${bashrc}.tmp" "$bashrc" - } - - ensure_aliases - msg_ok "$(translate "Aliases added to .bashrc")" - - msg_success "$(translate "Figurine installation and configuration completed successfully.")" - register_tool "figurine" true -} - - - @@ -3436,44 +2168,6 @@ EOF chmod +x "$profile_script" - ensure_aliases_() { - local bashrc="/root/.bashrc" - [[ -f "$bashrc" ]] || touch "$bashrc" - - local -a ALIASES=( - "aptup=apt update && apt dist-upgrade" - "lxcclean=curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/pve/clean-lxcs.sh | bash" - "lxcupdate=curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/pve/update-lxcs.sh | bash" - "kernelclean=curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/pve/kernel-clean.sh | bash" - "cpugov=curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/pve/scaling-governor.sh | bash" - "lxctrim=curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/pve/fstrim.sh | bash" - "updatecerts=pvecm updatecerts" - "seqwrite=sync; fio --randrepeat=1 --ioengine=libaio --direct=1 --name=test --filename=test --bs=4M --size=32G --readwrite=write --ramp_time=4" - "seqread=sync; fio --randrepeat=1 --ioengine=libaio --direct=1 --name=test --filename=test --bs=4M --size=32G --readwrite=read --ramp_time=4" - "ranwrite=sync; fio --randrepeat=1 --ioengine=libaio --direct=1 --name=test --filename=test --bs=4k --size=4G --readwrite=randwrite --ramp_time=4" - "ranread=sync; fio --randrepeat=1 --ioengine=libaio --direct=1 --name=test --filename=test --bs=4k --size=4G --readwrite=randread --ramp_time=4" - ) - - for entry in "${ALIASES[@]}"; do - local name="${entry%%=*}" - local cmd="${entry#*=}" - local esc_cmd - esc_cmd=$(printf "%s" "$cmd" | sed -e 's/[\\/&]/\\&/g') - - if grep -Eq "^alias[[:space:]]+$name=" "$bashrc"; then - if ! grep -Eq "^alias[[:space:]]+$name='${esc_cmd}'$" "$bashrc"; then - sed -i -E "s|^alias[[:space:]]+$name=.*$|alias $name='${esc_cmd}'|" "$bashrc" - fi - else - printf "alias %s='%s'\n" "$name" "$cmd" >> "$bashrc" - fi - done - - - awk '!seen[$0]++' "$bashrc" > "${bashrc}.tmp" && mv "${bashrc}.tmp" "$bashrc" - } - - ensure_aliases() { local bashrc="/root/.bashrc" [[ -f "$bashrc" ]] || touch "$bashrc" @@ -3552,159 +2246,6 @@ update_pve_appliance_manager() { -configure_log2ram_() { - msg_info2 "$(translate "Preparing Log2RAM configuration")" - sleep 2 - - 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 - DEFAULT_SIZE="128" - DEFAULT_HOURS="1" - elif (( RAM_SIZE_GB <= 16 )); then - DEFAULT_SIZE="256" - DEFAULT_HOURS="3" - else - DEFAULT_SIZE="512" - DEFAULT_HOURS="6" - fi - - USER_SIZE=$(whiptail --title "Log2RAM" --inputbox "$(translate "Enter the maximum size (in MB) to allocate for /var/log in RAM (e.g. 128, 256, 512):")\n\n$(translate "Recommended for $RAM_SIZE_GB GB RAM:") ${DEFAULT_SIZE}M" 12 70 "$DEFAULT_SIZE" 3>&1 1>&2 2>&3) || return 0 - LOG2RAM_SIZE="${USER_SIZE}M" - - CRON_HOURS=$(whiptail --title "Log2RAM" --radiolist "$(translate "Select the sync interval (in hours):")\n\n$(translate "Suggested interval: every $DEFAULT_HOURS hour(s)")" 15 70 5 \ - "1" "$(translate "Every hour")" OFF \ - "3" "$(translate "Every 3 hours")" OFF \ - "6" "$(translate "Every 6 hours")" OFF \ - "12" "$(translate "Every 12 hours")" OFF \ - 3>&1 1>&2 2>&3) || return 0 - - if whiptail --title "Log2RAM" --yesno "$(translate "Enable auto-sync if /var/log exceeds 90% of its size?")" 10 60; then - ENABLE_AUTOSYNC=true - else - ENABLE_AUTOSYNC=false - fi - - msg_info "$(translate "Cleaning previous Log2RAM installation...")" - - systemctl stop log2ram log2ram-daily.timer >/dev/null 2>&1 || true - systemctl disable log2ram log2ram-daily.timer >/dev/null 2>&1 || true - - rm -f /etc/cron.d/log2ram /etc/cron.d/log2ram-auto-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/sbin/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 2>/dev/null || true - rm -rf /etc/systemd/system/log2ram.service.d 2>/dev/null || true - rm -f /etc/log2ram.conf* 2>/dev/null || true - rm -rf /etc/logrotate.d/log2ram /var/log.hdd /tmp/log2ram 2>/dev/null || true - - systemctl daemon-reload >/dev/null 2>&1 || true - systemctl restart cron >/dev/null 2>&1 || true - - msg_ok "$(translate "Previous installation cleaned")" - msg_info "$(translate "Installing Log2RAM from GitHub...")" - - if ! command -v git >/dev/null 2>&1; then - msg_info "$(translate "Installing required package: git")" - apt-get update -qq >/dev/null 2>&1 - apt-get install -y git >/dev/null 2>&1 - fi - - rm -rf /tmp/log2ram 2>/dev/null || true - if ! git clone https://github.com/azlux/log2ram.git /tmp/log2ram >/dev/null 2>>/tmp/log2ram_install.log; then - msg_error "$(translate "Failed to clone log2ram repository. Check /tmp/log2ram_install.log")" - return 1 - fi - - cd /tmp/log2ram || { msg_error "$(translate "Failed to access log2ram directory")"; return 1; } - - if ! bash install.sh >>/tmp/log2ram_install.log 2>&1; then - msg_error "$(translate "Failed to run log2ram installer. Check /tmp/log2ram_install.log")" - return 1 - fi - - systemctl daemon-reload >/dev/null 2>&1 || true - systemctl enable --now log2ram >/dev/null 2>&1 || true - - if [[ -f /etc/log2ram.conf ]] && command -v log2ram >/dev/null 2>&1; then - msg_ok "$(translate "Log2RAM installed successfully")" - else - msg_error "$(translate "Log2RAM installation verification failed. Check /tmp/log2ram_install.log")" - return 1 - fi - - sed -i "s/^SIZE=.*/SIZE=$LOG2RAM_SIZE/" /etc/log2ram.conf - LOG2RAM_BIN="$(command -v log2ram || echo /usr/sbin/log2ram)" - - cat > /etc/cron.d/log2ram </dev/null 2>&1 -EOF - chmod 0644 /etc/cron.d/log2ram - chown root:root /etc/cron.d/log2ram - msg_ok "$(translate "Log2RAM write scheduled every") $CRON_HOURS $(translate "hour(s)")" - - if [[ "$ENABLE_AUTOSYNC" == true ]]; then - cat > /usr/local/bin/log2ram-check.sh <<'EOF' -#!/usr/bin/env bash -PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" - -CONF_FILE="/etc/log2ram.conf" -L2R_BIN="$(command -v log2ram || true)" -[[ -z "$L2R_BIN" && -x /usr/sbin/log2ram ]] && L2R_BIN="/usr/sbin/log2ram" -[[ -z "$L2R_BIN" ]] && exit 0 - -SIZE_MiB="$(grep -E '^SIZE=' "$CONF_FILE" 2>/dev/null | cut -d'=' -f2 | tr -dc '0-9')" -[[ -z "$SIZE_MiB" ]] && SIZE_MiB=128 -LIMIT_BYTES=$(( SIZE_MiB * 1024 * 1024 )) -THRESHOLD_BYTES=$(( LIMIT_BYTES * 90 / 100 )) - -USED_BYTES="$(df -B1 --output=used /var/log 2>/dev/null | tail -1 | tr -dc '0-9')" -[[ -z "$USED_BYTES" ]] && exit 0 - -LOCK="/run/log2ram-check.lock" -exec 9>"$LOCK" 2>/dev/null || exit 0 -flock -n 9 || exit 0 - -if (( USED_BYTES > THRESHOLD_BYTES )); then - "$L2R_BIN" write 2>/dev/null || true -fi -EOF - chmod +x /usr/local/bin/log2ram-check.sh - - cat > /etc/cron.d/log2ram-auto-sync <<'EOF' -# Log2RAM auto-sync based on /var/log usage - Created by ProxMenux -SHELL=/bin/bash -PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin -MAILTO="" -*/5 * * * * root /usr/local/bin/log2ram-check.sh >/dev/null 2>&1 -EOF - chmod 0644 /etc/cron.d/log2ram-auto-sync - chown root:root /etc/cron.d/log2ram-auto-sync - - msg_ok "$(translate "Auto-sync enabled when /var/log exceeds 90% of") $LOG2RAM_SIZE" - else - rm -f /usr/local/bin/log2ram-check.sh /etc/cron.d/log2ram-auto-sync 2>/dev/null || true - msg_info2 "$(translate "Auto-sync was not enabled")" - fi - - systemctl restart cron >/dev/null 2>&1 || true - systemctl restart log2ram >/dev/null 2>&1 || true - - msg_success "$(translate "Log2RAM installation and configuration completed successfully.")" - register_tool "log2ram" true -} - - - @@ -3900,8 +2441,10 @@ Compress=yes SystemMaxUse=${USE_MB}M SystemKeepFree=${KEEP_MB}M RuntimeMaxUse=${RUNTIME_MB}M -MaxLevelStore=warning -MaxLevelSyslog=warning +# MaxLevelStore=info: required for ProxMenux Monitor log display and Fail2Ban detection. +# Using "warning" silently discards most system logs making date filters useless. +MaxLevelStore=info +MaxLevelSyslog=info MaxLevelKMsg=warning MaxLevelConsole=notice MaxLevelWall=crit @@ -3948,7 +2491,9 @@ EOF setup_persistent_network() { local LINK_DIR="/etc/systemd/network" local BACKUP_DIR="/etc/systemd/network/backup-$(date +%Y%m%d-%H%M%S)" - + local pve_version + pve_version=$(pveversion 2>/dev/null | grep -oP 'pve-manager/\K[0-9]+' | head -1) + msg_info "$(translate "Setting up persistent network interfaces")" sleep 2 @@ -3984,6 +2529,14 @@ EOF if [[ $count -gt 0 ]]; then msg_ok "$(translate "Created persistent names for") $count $(translate "interfaces")" + # In PVE9, systemd-networkd is the native network backend and udev processes + # .link files directly. Reloading udev rules makes the new .link files effective + # immediately for any interface added later (hotplug, new NICs) without waiting + # for a full reboot. On PVE8 (ifupdown2), names are resolved at boot anyway. + if [[ "$pve_version" -ge 9 ]]; then + udevadm control --reload-rules 2>/dev/null || true + msg_ok "$(translate "PVE9: udev rules reloaded — new interfaces will get correct names without reboot")" + fi msg_ok "$(translate "Changes will apply after reboot.")" else msg_warn "$(translate "No physical interfaces found")" @@ -4010,60 +2563,6 @@ EOF # Auxiliary help functions # ========================================================== -# Rest of the functions remain the same... -cleanup_duplicate_repos() { - msg_info "$(translate "Cleaning up duplicate repositories...")" - - local sources_file="/etc/apt/sources.list" - local temp_file=$(mktemp) - local cleaned_count=0 - declare -A seen_repos - - # Clean main sources.list - 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" - - # Clean up old Proxmox repository files - local old_pve_files=(/etc/apt/sources.list.d/pve-*.list) - for file in "${old_pve_files[@]}"; do - if [ -f "$file" ] && [[ "$file" != "/etc/apt/sources.list.d/pve-enterprise.list" ]]; then - # Check if we have the new .sources format - if [ -f "/etc/apt/sources.list.d/proxmox.sources" ]; then - msg_info "$(translate "Removing old repository file: $(basename "$file")")" - rm -f "$file" - cleaned_count=$((cleaned_count + 1)) - fi - fi - done - - if [ $cleaned_count -gt 0 ]; then - msg_ok "$(translate "Cleaned up $cleaned_count duplicate/old repositories")" - apt-get update > /dev/null 2>&1 - else - msg_ok "$(translate "No duplicate repositories found")" - fi -} @@ -4072,41 +2571,6 @@ cleanup_duplicate_repos() { -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.")" - 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 -} - - - - - - # ========================================================== @@ -4145,11 +2609,9 @@ main_menu() { "System|Optimize Memory|MEMORYFIXES" "System|Enable fast reboots|KEXEC" "System|Enable restart on kernel panic|KERNELPANIC" - "System|Install kernel headers|KERNELHEADERS" "Optional|Apply AMD CPU fixes|AMDFIXES" "Virtualization|Install relevant guest agent|GUESTAGENT" "Virtualization|Enable VFIO IOMMU support|VFIO_IOMMU" - "Virtualization|KSM control daemon|KSMTUNED" "Network|Force APT to use IPv4|APTIPV4" "Network|Apply network optimizations|NET" "Network|Install Open vSwitch|OPENVSWITCH" @@ -4159,8 +2621,6 @@ main_menu() { "Storage|Install ZFS auto-snapshot|ZFSAUTOSNAPSHOT" "Storage|Increase vzdump backup speed|VZDUMP" "Security|Disable portmapper/rpcbind|DISABLERPC" - "Security|Protect web interface with fail2ban|FAIL2BAN" - "Security|Install Lynis security tool|LYNIS" "Customization|Customize bashrc|BASHRC" "Customization|Set up custom MOTD banner|MOTD" "Customization|Remove subscription banner|NOSUBBANNER" @@ -4169,7 +2629,6 @@ main_menu() { "Optional|Install and configure Fastfetch|FASTFETCH" "Optional|Update Proxmox VE Appliance Manager|PVEAM" "Optional|Add latest Ceph support|CEPH" - "Optional|Add Proxmox testing repository|REPOTEST" "Optional|Enable High Availability services|ENABLE_HA" "Optional|Install Figurine|FIGURINE" "Optional|Install and configure Log2RAM|LOG2RAM" @@ -4291,7 +2750,7 @@ done APTUPGRADE) apt_upgrade ;; TIMESYNC) configure_time_sync ;; NOAPTLANG) skip_apt_languages ;; - UTILS) install_system_utils ;; + UTILS) bash "$LOCAL_SCRIPTS/utilities/system_utils.sh" ;; JOURNALD) optimize_journald ;; LOGROTATE) optimize_logrotate ;; LIMITS) increase_system_limits ;; @@ -4299,11 +2758,9 @@ done MEMORYFIXES) optimize_memory_settings ;; KEXEC) enable_kexec ;; KERNELPANIC) configure_kernel_panic ;; - KERNELHEADERS) install_kernel_headers ;; AMDFIXES) apply_amd_fixes ;; GUESTAGENT) install_guest_agent ;; VFIO_IOMMU) enable_vfio_iommu ;; - KSMTUNED) configure_ksmtuned ;; APTIPV4) force_apt_ipv4 ;; NET) apply_network_optimizations ;; OPENVSWITCH) install_openvswitch ;; @@ -4312,8 +2769,6 @@ done ZFSAUTOSNAPSHOT) install_zfs_auto_snapshot ;; VZDUMP) optimize_vzdump ;; DISABLERPC) disable_rpc ;; - FAIL2BAN) install_fail2ban ;; - LYNIS) install_lynis ;; BASHRC) customize_bashrc ;; MOTD) setup_motd ;; NOSUBBANNER) remove_subscription_banner ;; @@ -4321,7 +2776,6 @@ done PIGZ) configure_pigz ;; FASTFETCH) configure_fastfetch ;; CEPH) install_ceph ;; - REPOTEST) add_repo_test ;; ENABLE_HA) enable_ha ;; FIGURINE) configure_figurine ;; LOG2RAM) configure_log2ram ;; diff --git a/scripts/post_install/uninstall-tools.sh b/scripts/post_install/uninstall-tools.sh index 458d8857..46cc165d 100644 --- a/scripts/post_install/uninstall-tools.sh +++ b/scripts/post_install/uninstall-tools.sh @@ -69,22 +69,6 @@ uninstall_fastfetch() { ################################################################ -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_figurine() { if ! command -v figurine &>/dev/null; then msg_warn "$(translate "Figurine is not installed.")" @@ -150,124 +134,6 @@ uninstall_apt_upgrade() { ################################################################ -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_subscription_banner__() { - msg_info "$(translate "Restoring subscription banner...")" - - local JS_FILE="/usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js" - local MOBILE_TPL="/usr/share/pve-manager/templates/index.html.tpl" - local PATCH_BIN="/usr/local/bin/pve-remove-nag.sh" - local BASE_DIR="/opt/pve-nag-buster" - 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 MARK_MOBILE=" PVE9 Mobile Subscription Banner Removal " - - local restored=false - - # Remove APT hook (both old and new versions) - for hook in /etc/apt/apt.conf.d/*nag* /etc/apt/apt.conf.d/no-nag-script; do - if [[ -e "$hook" ]]; then - rm -f "$hook" - msg_ok "$(translate "Removed APT hook: $hook")" - fi - done - - # Remove patch script - if [[ -f "$PATCH_BIN" ]]; then - rm -f "$PATCH_BIN" - msg_ok "$(translate "Removed patch script: $PATCH_BIN")" - fi - - # Restore JavaScript file from backups (new script method) - if [[ -d "$BASE_DIR/backups" ]]; then - local latest_backup - latest_backup=$(ls -t "$BASE_DIR/backups"/proxmoxlib.js.backup.* 2>/dev/null | head -1) - if [[ -n "$latest_backup" && -f "$latest_backup" ]]; then - if [[ -s "$latest_backup" ]] && grep -q "Ext\|function" "$latest_backup" && ! grep -q $'\0' "$latest_backup"; then - cp -a "$latest_backup" "$JS_FILE" - msg_ok "$(translate "Restored from backup: $latest_backup")" - restored=true - fi - fi - fi - - # Restore from old script backups (if new method didn't work) - if [[ "$restored" == false ]]; then - local old_backup - old_backup=$(ls -t "${JS_FILE}".backup.pve9.* "${JS_FILE}".backup.* 2>/dev/null | head -1) - if [[ -n "$old_backup" && -f "$old_backup" ]]; then - if [[ -s "$old_backup" ]] && grep -q "Ext\|function" "$old_backup" && ! grep -q $'\0' "$old_backup"; then - cp -a "$old_backup" "$JS_FILE" - msg_ok "$(translate "Restored from old backup: $old_backup")" - restored=true - fi - fi - fi - - # Restore mobile template if patched - if [[ -f "$MOBILE_TPL" ]] && grep -q "$MARK_MOBILE" "$MOBILE_TPL"; then - 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" ]]; then - cp -a "$mobile_backup" "$MOBILE_TPL" - msg_ok "$(translate "Restored mobile template from backup")" - else - # Remove the patch manually if no backup available - sed -i "/^$MARK_MOBILE$/,\$d" "$MOBILE_TPL" - msg_ok "$(translate "Removed mobile template patches")" - fi - fi - - # If no valid backups found, reinstall packages - if [[ "$restored" == false ]]; then - msg_info "$(translate "No valid backups found, reinstalling packages...")" - - if apt --reinstall install proxmox-widget-toolkit -y >/dev/null 2>&1; then - msg_ok "$(translate "Reinstalled proxmox-widget-toolkit")" - restored=true - else - msg_error "$(translate "Failed to reinstall proxmox-widget-toolkit")" - fi - - # Also try to reinstall pve-manager if mobile template was patched - if [[ -f "$MOBILE_TPL" ]] && grep -q "$MARK_MOBILE" "$MOBILE_TPL"; then - apt --reinstall install pve-manager -y >/dev/null 2>&1 || true - fi - fi - - rm -f "$MIN_JS_FILE" "$GZ_FILE" 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 - - register_tool "subscription_banner" false - - if [[ "$restored" == true ]]; then - msg_ok "$(translate "Subscription banner restored successfully")" - 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_subscription_banner() { @@ -577,9 +443,7 @@ uninstall_network_optimization() { local interfaces_file="/etc/network/interfaces" if [ -f "$interfaces_file" ]; then - if tail -1 "$interfaces_file" | grep -q "^source /etc/network/interfaces.d/\*$"; then - sed -i '$d' "$interfaces_file" - fi + sed -i '/^source \/etc\/network\/interfaces\.d\/\*/d' "$interfaces_file" fi rm -f /etc/sysctl.d/97-proxmenux-fwbr.conf \ @@ -610,8 +474,8 @@ uninstall_bashrc_custom() { 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 + # Remove the customization block using the markers written by customize_bashrc + sed -i '/# BEGIN PMX_CORE_BASHRC/,/# END PMX_CORE_BASHRC/d' /root/.bashrc fi msg_ok "$(translate "ProxMenux customizations removed from bashrc")" fi @@ -727,6 +591,57 @@ uninstall_persistent_network() { +uninstall_vfio_iommu() { + 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 + sed -i '/^vfio$/d;/^vfio_iommu_type1$/d;/^vfio_pci$/d;/^vfio_virqfd$/d' "$modules_file" + 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 + sed -i '/^blacklist nouveau$/d;/^blacklist lbm-nouveau$/d;/^blacklist radeon$/d;/^blacklist nvidia$/d;/^blacklist nvidiafb$/d;/^options nouveau modeset=0$/d' "$blacklist_file" + [ ! -s "$blacklist_file" ] && rm -f "$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)" + sed -i -E 's/\b(intel_iommu=on|amd_iommu=on|iommu=pt|pcie_acs_override=[^ ]*)\b//g' "$cmdline_file" + sed -i -E 's/[[:space:]]+/ /g; s/^ //; s/ $//' "$cmdline_file" + command -v proxmox-boot-tool >/dev/null 2>&1 && proxmox-boot-tool refresh >/dev/null 2>&1 || true + 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)" + sed -i -E 's/\b(intel_iommu=on|amd_iommu=on|iommu=pt|pcie_acs_override=[^ "]*)\b//g' "$grub_file" + awk -F\" 'BEGIN{OFS="\""} /GRUB_CMDLINE_LINUX_DEFAULT=/{gsub(/[[:space:]]+/," ",$2);sub(/^ /,"",$2);sub(/ $/,"",$2)}1' \ + "$grub_file" > "${grub_file}.tmp" && mv "${grub_file}.tmp" "$grub_file" + update-grub >/dev/null 2>&1 || true + msg_ok "$(translate "IOMMU parameters removed from GRUB")" + fi + fi + + update-initramfs -u -k all >/dev/null 2>&1 || true + + msg_ok "$(translate "IOMMU/VFIO configuration reverted")" + register_tool "vfio_iommu" false +} + +################################################################ + uninstall_amd_fixes() { msg_info2 "$(translate "Reverting AMD (Ryzen/EPYC) fixes...")" NECESSARY_REBOOT=1 @@ -926,6 +841,7 @@ show_uninstall_menu() { 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";; *) desc="$tool";; esac