diff --git a/one-button-optimizer.sh b/one-button-optimizer.sh index e75b033..087125d 100755 --- a/one-button-optimizer.sh +++ b/one-button-optimizer.sh @@ -42,6 +42,154 @@ check_root() { fi } +analyze_proxmox_status() { + echo -e "${CYAN}🔍 Proxmox Host Analysis${NC}" + echo "========================" + echo "" + + # System info + local ram_gb=$(free -g | awk '/^Mem:|^Speicher:/{print $2}') + local ram_used=$(free -g | awk '/^Mem:|^Speicher:/{print $3}') + local ram_available=$(free -g | awk '/^Mem:|^Speicher:/{print $7}') + local cpu_cores=$(nproc) + local pve_version=$(pveversion | head -1 || echo "Unknown") + + echo "📊 System Information:" + echo " 💾 RAM: ${ram_gb}GB (Used: ${ram_used}GB, Available: ${ram_available}GB)" + echo " 🖥️ CPU: ${cpu_cores} cores" + echo " 📦 Proxmox: $pve_version" + echo "" + + # VM/Container workload + local vm_count=$(qm list 2>/dev/null | tail -n +2 | wc -l || echo "0") + local ct_count=$(pct list 2>/dev/null | tail -n +2 | wc -l || echo "0") + local vm_running=$(qm list 2>/dev/null | grep -c "running" || echo "0") + local ct_running=$(pct list 2>/dev/null | grep -c "running" || echo "0") + + echo "🖥️ Workload:" + echo " 🖼️ VMs: $vm_count total ($vm_running running)" + echo " 📦 Containers: $ct_count total ($ct_running running)" + echo "" + + # Check VM memory allocation + local total_vm_mem=0 + if command -v qm &>/dev/null; then + while read -r vmid; do + local mem=$(qm config "$vmid" 2>/dev/null | grep "^memory:" | awk '{print $2}' || echo "0") + total_vm_mem=$((total_vm_mem + mem)) + done < <(qm list 2>/dev/null | tail -n +2 | awk '{print $1}') + local total_vm_mem_gb=$((total_vm_mem / 1024)) + echo " 📊 Total VM memory allocated: ${total_vm_mem_gb}GB" + local overcommit_ratio=$(echo "scale=1; $total_vm_mem_gb * 100 / $ram_gb" | bc 2>/dev/null || echo "N/A") + echo " 📈 Memory overcommit: ${overcommit_ratio}%" + echo "" + fi + + # Storage + echo "💾 Storage:" + if command -v pvesm &>/dev/null; then + pvesm status 2>/dev/null | tail -n +2 | while read -r name type status total used avail percent; do + echo " • $name ($type): ${used}/${total} used" + done + fi + echo "" + + # Check current kernel parameters + echo "⚙️ Current Kernel Parameters:" + local swappiness=$(sysctl -n vm.swappiness 2>/dev/null || echo "60") + local dirty_ratio=$(sysctl -n vm.dirty_ratio 2>/dev/null || echo "20") + local dirty_bg=$(sysctl -n vm.dirty_background_ratio 2>/dev/null || echo "10") + local cache_pressure=$(sysctl -n vm.vfs_cache_pressure 2>/dev/null || echo "100") + local qdisc=$(sysctl -n net.core.default_qdisc 2>/dev/null || echo "pfifo_fast") + local tcp_congestion=$(sysctl -n net.ipv4.tcp_congestion_control 2>/dev/null || echo "cubic") + + echo " 📊 Memory:" + echo " vm.swappiness: $swappiness (Proxmox recommended: 10)" + echo " vm.dirty_ratio: $dirty_ratio (Proxmox recommended: 10)" + echo " vm.dirty_background_ratio: $dirty_bg (Proxmox recommended: 5)" + echo " vm.vfs_cache_pressure: $cache_pressure (Proxmox recommended: 50)" + echo "" + echo " 📡 Network:" + echo " net.core.default_qdisc: $qdisc (Proxmox recommended: fq)" + echo " net.ipv4.tcp_congestion_control: $tcp_congestion (Proxmox recommended: bbr)" + echo "" + + # Check CPU governor + local governor=$(cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor 2>/dev/null || echo "unknown") + echo "🖥️ CPU Governor: $governor (Recommended: performance)" + echo "" + + # Check ZFS if present + if command -v zpool &>/dev/null && zpool list &>/dev/null 2>&1; then + echo "🗄️ ZFS Configuration:" + local arc_max=$(cat /sys/module/zfs/parameters/zfs_arc_max 2>/dev/null || echo "0") + local arc_max_gb=$((arc_max / 1024 / 1024 / 1024)) + local recommended_arc=$((ram_gb / 4)) + echo " � Current ARC max: ${arc_max_gb}GB" + echo " 💡 Recommended: ${recommended_arc}GB (25% of RAM, leaves more for VMs)" + echo "" + fi + + # Check for existing optimizations + echo "🔍 Existing Optimizations:" + local has_optimizations=false + + if [[ -f /etc/sysctl.d/99-system-optimization.conf ]] || [[ -f /etc/sysctl.d/99-proxmox-tuning.conf ]]; then + echo " ✅ Custom sysctl configuration found" + has_optimizations=true + else + echo " ❌ No custom sysctl configuration" + fi + + if mount | grep -q "tmpfs.*tmpfs-cache"; then + local tmpfs_count=$(mount | grep -c "tmpfs.*tmpfs-cache") + echo " ⚠️ tmpfs mounts found: $tmpfs_count (may use RAM needed by VMs)" + has_optimizations=true + else + echo " ✅ No tmpfs cache mounts (good for Proxmox)" + fi + + if [[ -e /dev/zram0 ]] && swapon --show | grep -q zram0; then + local zram_size=$(swapon --show | grep zram0 | awk '{print $3}') + echo " ⚠️ zram active: $zram_size (reduces RAM for VMs)" + has_optimizations=true + else + echo " ✅ No zram (good for Proxmox)" + fi + echo "" + + # Assessment + echo "📋 Assessment:" + local needs_optimization=false + + if [[ "$swappiness" != "10" ]] || [[ "$dirty_ratio" != "10" ]] || [[ "$qdisc" != "fq" ]] || [[ "$tcp_congestion" != "bbr" ]]; then + echo " ⚠️ Kernel parameters not optimized for hypervisor workload" + needs_optimization=true + else + echo " ✅ Kernel parameters look good" + fi + + if [[ "$governor" != "performance" ]] && [[ "$governor" != "unknown" ]]; then + echo " ⚠️ CPU governor not set to 'performance'" + needs_optimization=true + fi + + if command -v zpool &>/dev/null && zpool list &>/dev/null 2>&1; then + if [[ $arc_max_gb -gt $recommended_arc ]]; then + echo " ⚠️ ZFS ARC could be limited to give VMs more RAM" + needs_optimization=true + fi + fi + + if [[ "$needs_optimization" == "false" ]]; then + echo " ✅ System is already well-optimized for Proxmox!" + fi + + echo "" + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + echo "" +} + check_proxmox() { # Detect if running on Proxmox host if [[ -f /etc/pve/.version ]] || [[ -d /etc/pve ]] || pveversion &>/dev/null; then @@ -49,17 +197,14 @@ check_proxmox() { warn "⚠️ Proxmox VE host detected!" echo "" - # Get VM/CT count - local vm_count=$(qm list 2>/dev/null | tail -n +2 | wc -l || echo "0") - local ct_count=$(pct list 2>/dev/null | tail -n +2 | wc -l || echo "0") + # Show detailed analysis + analyze_proxmox_status - echo "🖥️ System: Proxmox VE (${vm_count} VMs, ${ct_count} containers)" - echo "" echo "This tool has TWO modes:" echo "" echo " 1️⃣ Proxmox Host Mode (Hypervisor Optimization)" echo " • Optimized kernel params for VM workloads" - echo " • Minimal RAM allocation (5-10% max)" + echo " • Minimal RAM allocation (2GB APT cache only)" echo " • CPU performance governor" echo " • ZFS ARC limiting (if applicable)" echo " • No desktop app configuration" @@ -1320,6 +1465,90 @@ EOF success "Kernel parameters optimized ($profile profile)" } +optimize_cpu_governor() { + if [[ "${PROXMOX_MODE:-false}" != "true" ]]; then + return 0 + fi + + log "Optimizing CPU governor for Proxmox..." + + # Check current governor + local current_governor=$(cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor 2>/dev/null || echo "unknown") + + if [[ "$current_governor" == "performance" ]]; then + success "CPU governor already set to 'performance'" + return 0 + fi + + if [[ "$current_governor" == "unknown" ]]; then + warn "CPU frequency scaling not available on this system" + return 0 + fi + + # Install cpufrequtils if needed + if ! command -v cpufreq-set &>/dev/null; then + log "Installing cpufrequtils..." + apt-get update -qq + apt-get install -y cpufrequtils >/dev/null 2>&1 + fi + + # Set governor to performance + for cpu in /sys/devices/system/cpu/cpu[0-9]*; do + if [[ -f "$cpu/cpufreq/scaling_governor" ]]; then + echo "performance" > "$cpu/cpufreq/scaling_governor" 2>/dev/null || true + fi + done + + # Make persistent + cat > /etc/default/cpufrequtils << 'EOF' +# CPU governor for Proxmox host +GOVERNOR="performance" +EOF + + success "CPU governor set to 'performance' (full speed for VMs)" +} + +optimize_zfs_arc() { + if [[ "${PROXMOX_MODE:-false}" != "true" ]]; then + return 0 + fi + + # Check if ZFS is present + if ! command -v zpool &>/dev/null || ! zpool list &>/dev/null 2>&1; then + return 0 + fi + + log "Optimizing ZFS ARC limit..." + + local ram_gb=$(free -g | awk '/^Mem:|^Speicher:/{print $2}') + local current_arc=$(cat /sys/module/zfs/parameters/zfs_arc_max 2>/dev/null || echo "0") + local current_arc_gb=$((current_arc / 1024 / 1024 / 1024)) + local recommended_arc=$((ram_gb / 4)) # 25% of RAM + + if [[ $current_arc_gb -le $recommended_arc ]] && [[ $current_arc_gb -gt 0 ]]; then + success "ZFS ARC already limited to ${current_arc_gb}GB (good for VMs)" + return 0 + fi + + local arc_bytes=$((recommended_arc * 1024 * 1024 * 1024)) + + # Set immediately + echo "$arc_bytes" > /sys/module/zfs/parameters/zfs_arc_max 2>/dev/null || true + + # Make persistent + mkdir -p /etc/modprobe.d + if ! grep -q "zfs_arc_max" /etc/modprobe.d/zfs.conf 2>/dev/null; then + echo "options zfs zfs_arc_max=$arc_bytes" >> /etc/modprobe.d/zfs.conf + else + sed -i "s/zfs_arc_max=[0-9]*/zfs_arc_max=$arc_bytes/" /etc/modprobe.d/zfs.conf + fi + + # Update initramfs + update-initramfs -u -k all >/dev/null 2>&1 || true + + success "ZFS ARC limited to ${recommended_arc}GB (frees RAM for VMs)" +} + create_service() { if [[ $SETUP_SERVICE != true ]]; then return 0 @@ -1494,6 +1723,11 @@ main() { setup_zram setup_tmpfs tune_kernel + + # Proxmox-specific optimizations + optimize_cpu_governor + optimize_zfs_arc + create_service # Show results