#!/bin/bash # ============================================================================== # PROXMOX LIBRARY: Post-Install Configuration and Management # ============================================================================== # Part of unified bootstrap system for homelab infrastructure # Comprehensive Proxmox VE post-install routines inspired by community scripts # (tteck/community-scripts ProxmoxVE post-pve-install.sh) # ============================================================================== # Source detection library if not already loaded if ! type -t detect_os_family &>/dev/null; then SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # shellcheck source=./detection.sh source "${SCRIPT_DIR}/detection.sh" fi # --- PROXMOX VERSION DETECTION --- get_pve_version() { # Get Proxmox VE version (e.g., 8.2.4) if ! command -v pveversion &>/dev/null; then echo "unknown" return 1 fi pveversion | awk -F'/' '{print $2}' | awk -F'-' '{print $1}' } get_pve_major_version() { # Get major version (8 or 9) local ver=$(get_pve_version) echo "$ver" | cut -d. -f1 } is_pve_supported_version() { # Check if PVE version is supported (8.0-8.9.x or 9.0-9.1.x) local major=$(get_pve_major_version) case "$major" in 8|9) return 0 ;; *) return 1 ;; esac } # --- REPOSITORY MANAGEMENT --- disable_pve_enterprise_repo() { # Disable enterprise repository (requires subscription) local major=$(get_pve_major_version) echo "[⚙] Disabling Proxmox enterprise repository..." >&2 if [ "$major" == "9" ]; then # PVE 9.x uses .sources format for file in /etc/apt/sources.list.d/*.sources; do if [ -f "$file" ] && grep -q "pve-enterprise" "$file"; then # Use Enabled: false instead of commenting if grep -q "^Enabled:" "$file"; then sudo sed -i 's/^Enabled:.*/Enabled: false/' "$file" else echo "Enabled: false" | sudo tee -a "$file" >/dev/null fi fi done else # PVE 8.x uses .list format if [ -f /etc/apt/sources.list.d/pve-enterprise.list ]; then sudo sed -i 's/^deb/# deb/' /etc/apt/sources.list.d/pve-enterprise.list fi fi echo " [✓] Enterprise repository disabled" >&2 } enable_pve_no_subscription_repo() { # Enable no-subscription repository (free updates) local major=$(get_pve_major_version) echo "[⚙] Enabling Proxmox no-subscription repository..." >&2 if [ "$major" == "9" ]; then # PVE 9.x deb822 format sudo tee /etc/apt/sources.list.d/proxmox.sources >/dev/null </dev/null <&2 } configure_ceph_repos() { # Configure Ceph storage repositories (disabled by default) local major=$(get_pve_major_version) echo "[⚙] Configuring Ceph package repositories..." >&2 if [ "$major" == "9" ]; then # PVE 9.x - Squid version sudo tee /etc/apt/sources.list.d/ceph.sources >/dev/null </dev/null <&2 } add_pvetest_repo() { # Add pvetest repository for beta features (disabled by default) local major=$(get_pve_major_version) echo "[⚙] Adding pvetest repository (disabled)..." >&2 if [ "$major" == "9" ]; then sudo tee /etc/apt/sources.list.d/pve-test.sources >/dev/null </dev/null <&2 } configure_all_pve_repos() { # Run complete repository configuration disable_pve_enterprise_repo enable_pve_no_subscription_repo configure_ceph_repos add_pvetest_repo echo "[✓] Proxmox repository configuration complete" >&2 } # --- SUBSCRIPTION NAG REMOVAL --- disable_subscription_nag() { # Remove subscription nag from web UI and mobile UI # Creates apt hook to persist after updates echo "[⚙] Disabling subscription nag dialog..." >&2 # Create persistent script sudo mkdir -p /usr/local/bin sudo tee /usr/local/bin/pve-remove-nag.sh >/dev/null <<'SCRIPT_EOF' #!/bin/sh # Auto-generated by homelab bootstrap - removes Proxmox subscription nag WEB_JS=/usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js if [ -s "$WEB_JS" ] && ! grep -q NoMoreNagging "$WEB_JS"; then echo "Patching Web UI subscription nag..." sed -i -e "/data\.status/ s/!//" -e "/data\.status/ s/active/NoMoreNagging/" "$WEB_JS" fi MOBILE_TPL=/usr/share/pve-yew-mobile-gui/index.html.tpl MARKER="" if [ -f "$MOBILE_TPL" ] && ! grep -q "$MARKER" "$MOBILE_TPL"; then echo "Patching Mobile UI subscription nag..." printf "%s\n" \ "$MARKER" \ "" >> "$MOBILE_TPL" fi SCRIPT_EOF sudo chmod 755 /usr/local/bin/pve-remove-nag.sh # Create apt hook to run after updates sudo tee /etc/apt/apt.conf.d/90-pve-no-nag <<'APT_EOF' DPkg::Post-Invoke { "/usr/local/bin/pve-remove-nag.sh"; }; APT_EOF sudo chmod 644 /etc/apt/apt.conf.d/90-pve-no-nag # Apply immediately sudo /usr/local/bin/pve-remove-nag.sh 2>/dev/null || true echo " [✓] Subscription nag disabled (clear browser cache)" >&2 } enable_subscription_nag() { # Remove nag removal script (restore default behavior) echo "[⚙] Re-enabling subscription nag..." >&2 sudo rm -f /usr/local/bin/pve-remove-nag.sh sudo rm -f /etc/apt/apt.conf.d/90-pve-no-nag # Reinstall widget toolkit to restore original sudo apt --reinstall install proxmox-widget-toolkit &>/dev/null || true echo " [✓] Subscription nag re-enabled" >&2 } # --- HIGH AVAILABILITY MANAGEMENT --- disable_ha_services() { # Disable HA services for single-node setups (saves resources) echo "[⚙] Disabling high availability services..." >&2 if systemctl is-active --quiet pve-ha-lrm || systemctl is-active --quiet pve-ha-crm; then sudo systemctl disable --now pve-ha-lrm 2>/dev/null || true sudo systemctl disable --now pve-ha-crm 2>/dev/null || true sudo systemctl disable --now corosync 2>/dev/null || true echo " [✓] HA services disabled" >&2 else echo " [✓] HA services already disabled" >&2 fi } enable_ha_services() { # Enable HA services for clustered environments echo "[⚙] Enabling high availability services..." >&2 sudo systemctl enable --now pve-ha-lrm sudo systemctl enable --now pve-ha-crm sudo systemctl enable --now corosync echo " [✓] HA services enabled" >&2 } check_ha_status() { # Check if HA services are running if systemctl is-active --quiet pve-ha-lrm; then echo "enabled" else echo "disabled" fi } # --- SYSTEM MAINTENANCE --- update_pve_system() { # Run full system update echo "[⚙] Updating Proxmox VE system (this may take several minutes)..." >&2 sudo apt-get update -qq sudo apt-get dist-upgrade -y -qq echo " [✓] System update complete" >&2 } check_reboot_required() { # Check if reboot is needed after updates if [ -f /var/run/reboot-required ]; then return 0 fi # Check if kernel was updated local running_kernel=$(uname -r) local latest_kernel=$(dpkg -l | grep linux-image | sort -V | tail -n1 | awk '{print $2}' | sed 's/linux-image-//') if [ "$running_kernel" != "$latest_kernel" ]; then return 0 fi return 1 } # --- COMPREHENSIVE POST-INSTALL --- run_proxmox_post_install() { # Complete post-install routine for Proxmox hosts # Args: $1 = mode (auto|interactive) - default: auto local mode="${1:-auto}" echo "=======================================" >&2 echo "PROXMOX POST-INSTALL CONFIGURATION" >&2 echo "Version: $(get_pve_version)" >&2 echo "Mode: $mode" >&2 echo "=======================================" >&2 echo "" >&2 # Verify Proxmox installation if ! is_pve_supported_version; then echo "[✗] Unsupported Proxmox VE version" >&2 return 1 fi # Repository configuration configure_all_pve_repos echo "" >&2 # Subscription nag removal (auto mode) if [ "$mode" == "auto" ]; then disable_subscription_nag echo "" >&2 fi # HA service management local cluster_nodes=$(pvesh get /nodes --output-format=json 2>/dev/null | jq -r 'length' 2>/dev/null || echo "1") if [ "$cluster_nodes" -eq 1 ]; then echo "[⚙] Single-node setup detected" >&2 disable_ha_services echo "" >&2 else echo "[⚙] Multi-node cluster detected ($cluster_nodes nodes)" >&2 echo " [✓] HA services left enabled" >&2 echo "" >&2 fi # System update if [ "$mode" == "auto" ]; then echo "[⚙] Checking for updates..." >&2 sudo apt-get update -qq local upgrades=$(apt list --upgradable 2>/dev/null | grep -c upgradable || echo "0") if [ "$upgrades" -gt 1 ]; then echo " [!] $((upgrades - 1)) packages can be upgraded" >&2 echo " [!] Run manually: apt update && apt dist-upgrade" >&2 else echo " [✓] System up to date" >&2 fi echo "" >&2 fi # Check reboot requirement if check_reboot_required; then echo "[!] REBOOT REQUIRED" >&2 echo " Kernel or critical services updated" >&2 echo " Run: reboot" >&2 echo "" >&2 fi echo "=======================================" >&2 echo "POST-INSTALL COMPLETE" >&2 echo "=======================================" >&2 echo "" >&2 echo "Next Steps:" >&2 echo " 1. Clear browser cache (Ctrl+Shift+R)" >&2 echo " 2. Reboot if kernel was updated" >&2 echo " 3. Configure storage/networking in web UI" >&2 echo "" >&2 } # --- VALIDATION --- validate_proxmox_config() { # Validate Proxmox configuration local errors=0 echo "[⚙] Validating Proxmox configuration..." >&2 # Check PVE version if ! is_pve_supported_version; then echo " [✗] Unsupported PVE version: $(get_pve_version)" >&2 ((errors++)) else echo " [✓] PVE version: $(get_pve_version)" >&2 fi # Check no-subscription repo if grep -rq "pve-no-subscription" /etc/apt/sources.list.d/ 2>/dev/null; then echo " [✓] No-subscription repository configured" >&2 else echo " [✗] No-subscription repository not found" >&2 ((errors++)) fi # Check enterprise repo disabled if grep -rq "^deb.*pve-enterprise" /etc/apt/sources.list.d/ 2>/dev/null; then echo " [!] Enterprise repository still active (requires subscription)" >&2 else echo " [✓] Enterprise repository disabled" >&2 fi # Check cluster status local cluster_status=$(pvesh get /cluster/status --output-format=json 2>/dev/null | jq -r '.[0].type' 2>/dev/null || echo "unknown") if [ "$cluster_status" == "cluster" ]; then echo " [✓] Part of Proxmox cluster" >&2 else echo " [✓] Standalone node" >&2 fi if [ $errors -eq 0 ]; then echo "[✓] Proxmox validation passed" >&2 return 0 else echo "[✗] Proxmox validation failed ($errors errors)" >&2 return 1 fi } # Export functions export -f get_pve_version export -f get_pve_major_version export -f is_pve_supported_version export -f disable_pve_enterprise_repo export -f enable_pve_no_subscription_repo export -f configure_ceph_repos export -f add_pvetest_repo export -f configure_all_pve_repos export -f disable_subscription_nag export -f enable_subscription_nag export -f disable_ha_services export -f enable_ha_services export -f check_ha_status export -f update_pve_system export -f check_reboot_required export -f run_proxmox_post_install export -f validate_proxmox_config