1. Fixed the apt hook logic The original script used dpkg -V with backwards logic. The new version directly checks if nag patterns are present in the files using grep, which is much more reliable: 2. More robust pattern matching Added multiple sed patterns to catch different variations of how the subscription check might be written: data.status !== 'active' data.status!=='active' data.status != 'active' data.status!='active' 3. Better testing and validation The script now includes a test_current_fix() function that verifies whether nags are actually present and whether the fix is working. 4. Improved error handling Better feedback about what's happening and whether the fix is working correctly.
381 lines
13 KiB
Bash
381 lines
13 KiB
Bash
#!/usr/bin/env bash
|
||
|
||
# Universal Proxmox Subscription Nag Remover - Improved Version
|
||
# Works with PVE (Proxmox VE), PBS (Proxmox Backup Server), and PMG (Proxmox Mail Gateway)
|
||
#
|
||
# Based on community-scripts by tteck and contributors
|
||
# Original scripts: https://community-scripts.github.io/ProxmoxVE/
|
||
# License: MIT
|
||
# Copyright (c) 2021-2025 community-scripts contributors
|
||
|
||
set -euo pipefail
|
||
|
||
# Colors for output
|
||
RD=$(echo "\033[01;31m")
|
||
YW=$(echo "\033[33m")
|
||
GN=$(echo "\033[1;92m")
|
||
BL=$(echo "\033[94m")
|
||
CL=$(echo "\033[m")
|
||
BFR="\\r\\033[K"
|
||
HOLD="-"
|
||
CM="${GN}✓${CL}"
|
||
CROSS="${RD}✗${CL}"
|
||
INFO="${BL}ℹ${CL}"
|
||
|
||
# Output functions
|
||
msg_info() {
|
||
local msg="$1"
|
||
echo -ne " ${HOLD} ${YW}${msg}..."
|
||
}
|
||
|
||
msg_ok() {
|
||
local msg="$1"
|
||
echo -e "${BFR} ${CM} ${GN}${msg}${CL}"
|
||
}
|
||
|
||
msg_error() {
|
||
local msg="$1"
|
||
echo -e "${BFR} ${CROSS} ${RD}${msg}${CL}"
|
||
}
|
||
|
||
msg_note() {
|
||
local msg="$1"
|
||
echo -e " ${INFO} ${BL}${msg}${CL}"
|
||
}
|
||
|
||
# Header
|
||
header_info() {
|
||
clear
|
||
cat <<"EOF"
|
||
╔═════════════════════════════════════════════════════════════════════════════╗
|
||
║ Universal Proxmox Nag Remover - Improved ║
|
||
║ PVE • PBS • PMG Support ║
|
||
╚═════════════════════════════════════════════════════════════════════════════╝
|
||
|
||
EOF
|
||
echo -e "${BL}Universal Subscription Nag Remover for All Proxmox Products${CL}"
|
||
echo -e "${YW}Based on community-scripts: https://community-scripts.github.io/ProxmoxVE/${CL}"
|
||
echo ""
|
||
}
|
||
|
||
# Detect Proxmox product
|
||
detect_proxmox() {
|
||
local product=""
|
||
local version=""
|
||
|
||
if command -v pveversion >/dev/null 2>&1; then
|
||
product="PVE"
|
||
version=$(pveversion | head -1)
|
||
elif command -v proxmox-backup-manager >/dev/null 2>&1; then
|
||
product="PBS"
|
||
version=$(proxmox-backup-manager version 2>/dev/null | head -1 || echo "PBS detected")
|
||
elif command -v pmgversion >/dev/null 2>&1; then
|
||
product="PMG"
|
||
version=$(pmgversion | head -1)
|
||
elif [ -f /usr/bin/pmg-admin ]; then
|
||
product="PMG"
|
||
version="PMG detected"
|
||
else
|
||
msg_error "No supported Proxmox product detected"
|
||
echo ""
|
||
echo "This script supports:"
|
||
echo " • Proxmox VE (PVE)"
|
||
echo " • Proxmox Backup Server (PBS)"
|
||
echo " • Proxmox Mail Gateway (PMG)"
|
||
exit 1
|
||
fi
|
||
|
||
echo "$product|$version"
|
||
}
|
||
|
||
# Function to apply nag removal to files
|
||
apply_nag_patch() {
|
||
local file="$1"
|
||
local backup_file="${file}.backup-$(date +%s)"
|
||
|
||
if [ -f "$file" ]; then
|
||
# Create backup
|
||
cp "$file" "$backup_file"
|
||
|
||
# Apply multiple patterns to catch different variations
|
||
sed -i.tmp \
|
||
-e "s/data\.status !== 'active'/false/g" \
|
||
-e "s/data\.status!=='active'/false/g" \
|
||
-e "s/data\.status != 'active'/false/g" \
|
||
-e "s/data\.status!='active'/false/g" \
|
||
-e "s/checked_command: 'subscription'/checked_command: 'no-subscription'/g" \
|
||
-e "/getNoSubKeyHtml.*{/,/},/{s/text: gettext('No valid subscription')/text: ''/g}" \
|
||
-e "s/'No valid subscription'/''/g" \
|
||
-e "/.*data\.status.*{/{s/\!//g; s/active/NoMoreNagging/g}" \
|
||
"$file"
|
||
|
||
# Clean up tmp file
|
||
rm -f "${file}.tmp"
|
||
|
||
echo "Patched: $file"
|
||
return 0
|
||
else
|
||
echo "File not found: $file"
|
||
return 1
|
||
fi
|
||
}
|
||
|
||
# Check if nag is present in file
|
||
check_nag_present() {
|
||
local file="$1"
|
||
if [ -f "$file" ]; then
|
||
grep -q "No valid subscription\|data\.status.*active" "$file" 2>/dev/null
|
||
else
|
||
return 1
|
||
fi
|
||
}
|
||
|
||
# Apply nag removal based on product
|
||
apply_nag_removal() {
|
||
local product="$1"
|
||
|
||
case $product in
|
||
PVE)
|
||
msg_info "Applying PVE subscription nag removal"
|
||
|
||
# More robust apt hook for PVE
|
||
cat > /etc/apt/apt.conf.d/no-nag-script << 'EOF'
|
||
DPkg::Post-Invoke {
|
||
"if [ -f /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js ]; then
|
||
if grep -q 'No valid subscription\\|data\\.status.*active' /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js 2>/dev/null; then
|
||
echo 'Reapplying PVE subscription nag removal...';
|
||
sed -i \
|
||
-e 's/data\\.status !== '\"'\"'active'\"'\"'/false/g' \
|
||
-e 's/data\\.status!==='\"'\"'active'\"'\"'/false/g' \
|
||
-e 's/data\\.status != '\"'\"'active'\"'\"'/false/g' \
|
||
-e 's/data\\.status!='\"'\"'active'\"'\"'/false/g' \
|
||
-e 's/checked_command: '\"'\"'subscription'\"'\"'/checked_command: '\"'\"'no-subscription'\"'\"'/g' \
|
||
-e '/getNoSubKeyHtml.*{/,/},/{s/text: gettext('\"'\"'No valid subscription'\"'\"')/text: '\"'\"''\"'\"'/g}' \
|
||
-e 's/'\"'\"'No valid subscription'\"'\"'/'\"'\"''\"'\"'/g' \
|
||
-e '/.*data\\.status.*{/{s/\\!//g; s/active/NoMoreNagging/g}' \
|
||
/usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js;
|
||
echo 'PVE nag removal reapplied successfully.';
|
||
fi;
|
||
fi";
|
||
};
|
||
EOF
|
||
|
||
# Apply initial patch
|
||
apply_nag_patch "/usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js"
|
||
msg_ok "PVE subscription nag removal applied"
|
||
;;
|
||
|
||
PBS)
|
||
msg_info "Applying PBS subscription nag removal"
|
||
|
||
# More robust apt hook for PBS
|
||
cat > /etc/apt/apt.conf.d/no-nag-script << 'EOF'
|
||
DPkg::Post-Invoke {
|
||
"if [ -f /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js ]; then
|
||
if grep -q 'No valid subscription\\|data\\.status.*active' /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js 2>/dev/null; then
|
||
echo 'Reapplying PBS subscription nag removal...';
|
||
sed -i \
|
||
-e 's/data\\.status !== '\"'\"'active'\"'\"'/false/g' \
|
||
-e 's/data\\.status!==='\"'\"'active'\"'\"'/false/g' \
|
||
-e 's/data\\.status != '\"'\"'active'\"'\"'/false/g' \
|
||
-e 's/data\\.status!='\"'\"'active'\"'\"'/false/g' \
|
||
-e '/data\\.status.*{/{s/\\!//g; s/active/NoMoreNagging/g}' \
|
||
/usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js;
|
||
echo 'PBS nag removal reapplied successfully.';
|
||
fi;
|
||
fi";
|
||
};
|
||
EOF
|
||
|
||
# Apply initial patch
|
||
apply_nag_patch "/usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js"
|
||
msg_ok "PBS subscription nag removal applied"
|
||
;;
|
||
|
||
PMG)
|
||
msg_info "Applying PMG subscription nag removal"
|
||
|
||
# More robust apt hook for PMG (both desktop and mobile)
|
||
cat > /etc/apt/apt.conf.d/no-nag-script << 'EOF'
|
||
DPkg::Post-Invoke {
|
||
"if [ -f /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js ]; then
|
||
if grep -q 'No valid subscription\\|data\\.status.*active' /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js 2>/dev/null; then
|
||
echo 'Reapplying PMG subscription nag removal (desktop)...';
|
||
sed -i \
|
||
-e 's/data\\.status !== '\"'\"'active'\"'\"'/false/g' \
|
||
-e 's/data\\.status!==='\"'\"'active'\"'\"'/false/g' \
|
||
-e 's/data\\.status != '\"'\"'active'\"'\"'/false/g' \
|
||
-e 's/data\\.status!='\"'\"'active'\"'\"'/false/g' \
|
||
-e '/.*data\\.status.*{/{s/\\!//g; s/active/NoMoreNagging/g}' \
|
||
/usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js;
|
||
echo 'PMG desktop nag removal reapplied successfully.';
|
||
fi;
|
||
fi;
|
||
if [ -f /usr/share/javascript/pmg-gui/js/pmgmanagerlib-mobile.js ]; then
|
||
if grep -q 'No valid subscription\\|data\\.status.*active' /usr/share/javascript/pmg-gui/js/pmgmanagerlib-mobile.js 2>/dev/null; then
|
||
echo 'Reapplying PMG subscription nag removal (mobile)...';
|
||
sed -i \
|
||
-e 's/data\\.status !== '\"'\"'active'\"'\"'/false/g' \
|
||
-e 's/data\\.status!==='\"'\"'active'\"'\"'/false/g' \
|
||
-e 's/data\\.status != '\"'\"'active'\"'\"'/false/g' \
|
||
-e 's/data\\.status!='\"'\"'active'\"'\"'/false/g' \
|
||
-e '/data\\.status.*{/{s/\\!//g; s/active/NoMoreNagging/g}' \
|
||
/usr/share/javascript/pmg-gui/js/pmgmanagerlib-mobile.js;
|
||
echo 'PMG mobile nag removal reapplied successfully.';
|
||
fi;
|
||
fi";
|
||
};
|
||
EOF
|
||
|
||
# Apply initial patches
|
||
apply_nag_patch "/usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js"
|
||
apply_nag_patch "/usr/share/javascript/pmg-gui/js/pmgmanagerlib-mobile.js"
|
||
msg_ok "PMG subscription nag removal applied (desktop & mobile)"
|
||
;;
|
||
esac
|
||
}
|
||
|
||
# Test if the current fix is working
|
||
test_current_fix() {
|
||
local product="$1"
|
||
local files_to_check=()
|
||
|
||
case $product in
|
||
PVE|PBS)
|
||
files_to_check=("/usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js")
|
||
;;
|
||
PMG)
|
||
files_to_check=(
|
||
"/usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js"
|
||
"/usr/share/javascript/pmg-gui/js/pmgmanagerlib-mobile.js"
|
||
)
|
||
;;
|
||
esac
|
||
|
||
local nag_found=false
|
||
for file in "${files_to_check[@]}"; do
|
||
if check_nag_present "$file"; then
|
||
nag_found=true
|
||
echo "⚠ Nag still present in: $file"
|
||
fi
|
||
done
|
||
|
||
if [ "$nag_found" = false ]; then
|
||
echo "✓ No subscription nags detected in relevant files"
|
||
return 0
|
||
else
|
||
return 1
|
||
fi
|
||
}
|
||
|
||
# Main execution
|
||
main() {
|
||
# Check if running as root
|
||
if [[ $EUID -ne 0 ]]; then
|
||
echo "This script must be run as root (use sudo)"
|
||
exit 1
|
||
fi
|
||
|
||
header_info
|
||
|
||
# Detect Proxmox product
|
||
msg_info "Detecting Proxmox product"
|
||
detection_result=$(detect_proxmox)
|
||
IFS='|' read -r PRODUCT VERSION <<< "$detection_result"
|
||
msg_ok "Detected $PRODUCT"
|
||
|
||
msg_note "$VERSION"
|
||
echo ""
|
||
|
||
# Check current status
|
||
msg_info "Checking current nag status"
|
||
if test_current_fix "$PRODUCT"; then
|
||
msg_ok "No subscription nags currently present"
|
||
|
||
if [[ -f /etc/apt/apt.conf.d/no-nag-script ]]; then
|
||
echo ""
|
||
echo "✓ Apt hook is installed and nags are already removed"
|
||
echo "✓ The fix should persist through updates"
|
||
echo ""
|
||
echo "If nags return after updates, there may be a new pattern to patch."
|
||
echo "Run this script again to update the fix."
|
||
exit 0
|
||
fi
|
||
else
|
||
msg_ok "Subscription nags detected - fix needed"
|
||
fi
|
||
|
||
# Check if hook exists but isn't working
|
||
if [[ -f /etc/apt/apt.conf.d/no-nag-script ]]; then
|
||
msg_info "Updating existing apt hook"
|
||
rm -f /etc/apt/apt.conf.d/no-nag-script
|
||
msg_ok "Old hook removed"
|
||
fi
|
||
|
||
echo ""
|
||
|
||
# Show subscription support message
|
||
echo -e "${YW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${CL}"
|
||
echo -e "${BL} Support Subscriptions${CL}"
|
||
echo -e "${YW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${CL}"
|
||
echo ""
|
||
echo "Supporting the software's development team is essential. Check their official"
|
||
echo "website's Support Subscriptions for pricing. Without their dedicated work,"
|
||
echo "we wouldn't have this exceptional software."
|
||
echo ""
|
||
echo -e "${YW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${CL}"
|
||
echo ""
|
||
|
||
# Confirm installation
|
||
echo "This will disable the subscription nag message that appears when logging"
|
||
echo "into the web interface. The fix will automatically reapply after updates."
|
||
echo ""
|
||
while true; do
|
||
read -p "Continue with subscription nag removal? (y/n): " yn
|
||
case $yn in
|
||
[Yy]*) break ;;
|
||
[Nn]*)
|
||
echo "Aborted."
|
||
exit 0
|
||
;;
|
||
*) echo "Please answer yes or no." ;;
|
||
esac
|
||
done
|
||
|
||
echo ""
|
||
|
||
# Apply the fix
|
||
apply_nag_removal "$PRODUCT"
|
||
|
||
echo ""
|
||
|
||
# Test the fix
|
||
msg_info "Testing nag removal"
|
||
if test_current_fix "$PRODUCT"; then
|
||
msg_ok "Nag removal test passed"
|
||
else
|
||
msg_error "Nag removal test failed - manual intervention may be needed"
|
||
fi
|
||
|
||
echo ""
|
||
echo -e "${GN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${CL}"
|
||
echo -e "${GN} Installation Complete${CL}"
|
||
echo -e "${GN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${CL}"
|
||
echo ""
|
||
echo "✓ The subscription nag has been disabled for $PRODUCT"
|
||
echo "✓ The fix will automatically reapply after Proxmox updates"
|
||
echo "✓ Clear your browser cache and refresh the web interface"
|
||
echo ""
|
||
if [[ "$PRODUCT" == "PMG" ]]; then
|
||
echo "✓ Both desktop and mobile interfaces have been patched"
|
||
echo ""
|
||
fi
|
||
echo "To test the apt hook manually, run:"
|
||
echo " apt --reinstall install proxmox-widget-toolkit"
|
||
echo ""
|
||
echo -e "${YW}Original community-scripts: https://community-scripts.github.io/ProxmoxVE/${CL}"
|
||
echo ""
|
||
}
|
||
|
||
# Run main function
|
||
main "$@" |