#!/bin/sh # shellcheck disable=SC2064 set -eu # pve-nag-buster (v04) https://github.com/foundObjects/pve-nag-buster # Copyright (C) 2019 /u/seaQueue (reddit.com/u/seaQueue) # # Removes Proxmox VE 6.x+ license nags automatically after updates # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # ensure a predictable environment PATH=/usr/sbin:/usr/bin:/sbin:/bin \unalias -a # installer main body: _main() { # detect environment PVE=$(systemctl show pveproxy.service --no-page | grep 'LoadState=' | cut -f2 -d=) PMG=$(systemctl show pmgproxy.service --no-page | grep 'LoadState=' | cut -f2 -d=) PBS=$(systemctl show proxmox-backup-proxy.service --no-page | grep 'LoadState=' | cut -f2 -d=) if [ "$PVE" = "loaded" ]; then SERVICE="pve" SERVICE_MANAGER="pve-manager" elif [ "$PMG" = "loaded" ]; then SERVICE="pmg" SERVICE_MANAGER="pmg-manager" elif [ "$PBS" = "loaded" ]; then SERVICE="pbs" SERVICE_MANAGER="proxmox-backup-manager" else echo "No Proxmox service detected; exiting." exit 1 fi # ensure $1 exists so 'set -u' doesn't error out { [ "$#" -eq "0" ] && set -- ""; } > /dev/null 2>&1 case "$1" in "--emit") # call the emit_script() function to stdout and exit, use this to verify # that the base64 encoded script below isn't doing anything malicious # does not require root emit_script ;; "--uninstall") # uninstall, requires root assert_root _uninstall ;; "--install" | "--offline" | "") # install dpkg hooks, requires root assert_root _install "$@" ;; *) # unknown flags, print usage and exit _usage ;; esac exit 0 } _uninstall() { set -x [ -f "/etc/apt/apt.conf.d/86${SERVICE}-nags" ] && rm -f "/etc/apt/apt.conf.d/86${SERVICE}-nags" [ -f "/usr/share/${SERVICE}-nag-buster.sh" ] && rm -f "/usr/share/${SERVICE}-nag-buster.sh" echo "Script and dpkg hooks removed, please manually remove /etc/apt/sources.list.d/${SERVICE}-no-subscription.list if desired" } _install() { # create hooks and no-subscription repo list, install hook script, run once VERSION_CODENAME='' ID='' . /etc/os-release if [ -n "$VERSION_CODENAME" ]; then RELEASE="$VERSION_CODENAME" else RELEASE=$(awk -F"[)(]+" '/VERSION=/ {print $2}' /etc/os-release) fi # create the ${SERVICE}-no-subscription list echo "Creating ${SERVICE} no-subscription repo list ..." cat <<- EOF > "/etc/apt/sources.list.d/${SERVICE}-no-subscription.list" # .list file automatically generated by ${SERVICE}-nag-buster at $(date) # # If ${SERVICE}-nag-buster is installed again this file will be overwritten # deb http://download.proxmox.com/debian/${SERVICE} $RELEASE ${SERVICE}-no-subscription EOF # create dpkg pre/post install hooks for persistence echo "Creating dpkg hooks in /etc/apt/apt.conf.d ..." cat <<- EOF > "/etc/apt/apt.conf.d/86${SERVICE}-nags" DPkg::Pre-Install-Pkgs { "while read -r pkg; do case \$pkg in *proxmox-widget-toolkit* | *${SERVICE_MANAGER}*) touch /tmp/.${SERVICE}-nag-buster && exit 0; esac done < /dev/stdin"; }; DPkg::Post-Invoke { "[ -f /tmp/.${SERVICE}-nag-buster ] && { /usr/share/${SERVICE}-nag-buster.sh; rm -f /tmp/.${SERVICE}-nag-buster; }; exit 0"; }; EOF # install the hook script temp='' if [ "$1" = "--offline" ]; then # packed script requested temp="$(mktemp)" && trap "rm -f $temp" EXIT emit_script > "$temp" elif [ -f "${SERVICE}-nag-buster.sh" ]; then # local copy available temp="${SERVICE}-nag-buster.sh" else # fetch from github echo "Fetching hook script from GitHub ..." tempd="$(mktemp -d)" && trap "echo 'Cleaning up temporary files ...'; rm -f $tempd/*; rmdir $tempd" EXIT temp="$tempd/${SERVICE}-nag-buster.sh" wget https://raw.githubusercontent.com/foundObjects/pve-nag-buster/master/${SERVICE}-nag-buster.sh \ -q --show-progress -O "$temp" fi echo "Installing hook script as /usr/share/${SERVICE}-nag-buster.sh" install -o root -m 0550 "$temp" "/usr/share/${SERVICE}-nag-buster.sh" echo "Running patch script" /usr/share/${SERVICE}-nag-buster.sh return 0 } # emit a stored copy of pve-nag-buster.sh offline -- this is intended to be used during # offline provisioning where we don't have access to github or a full cloned copy of the # project # run 'install.sh --emit' to dump stored script to stdout # Important: if you're not me you should probably decode this and read it to make sure I'm not doing # something malicious like mining dogecoin or stealing your valuable cat pictures # pve-nag-buster.sh (v04) encoded below: emit_script() { pve_script="IyEvYmluL3NoCiMKIyBwdmUtbmFnLWJ1c3Rlci5zaCAodjA1KSBodHRwczovL2dpdGh1Yi5jb20vZm91bmRPYmplY3RzL3B2ZS1uYWctYnVzdGVyCiMgQ29weXJpZ2h0IChDKSAyMDE5IC91L3NlYVF1ZXVlIChyZWRkaXQuY29tL3Uvc2VhUXVldWUpCiMKIyBSZW1vdmVzIFByb3htb3ggVkUgNi54KyBsaWNlbnNlIG5hZ3MgYXV0b21hdGljYWxseSBhZnRlciB1cGRhdGVzCiMKIyBUaGlzIHByb2dyYW0gaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yCiMgbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UKIyBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyIHZlcnNpb24gMgojIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLgojCiMgVGhpcyBwcm9ncmFtIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsCiMgYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YKIyBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlCiMgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy4KIwojIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlCiMgYWxvbmcgd2l0aCB0aGlzIHByb2dyYW07IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmUKIyBGb3VuZGF0aW9uLCBJbmMuLCA1MSBGcmFua2xpbiBTdHJlZXQsIEZpZnRoIEZsb29yLCBCb3N0b24sIE1BICAwMjExMC0xMzAxLCBVU0EuCgpOQUdUT0tFTj0iZGF0YS5zdGF0dXMudG9Mb3dlckNhc2UoKSAhPT0gJ2FjdGl2ZSciCk5BR0ZJTEU9Ii91c3Ivc2hhcmUvamF2YXNjcmlwdC9wcm94bW94LXdpZGdldC10b29sa2l0L3Byb3htb3hsaWIuanMiClNDUklQVD0iJChiYXNlbmFtZSAiJDAiKSIKUEFJRF9CQVNFPSIvZXRjL2FwdC9zb3VyY2VzLmxpc3QuZC9wdmUtZW50ZXJwcmlzZSIKCiMgZGlzYWJsZSBwYWlkIHJlcG8gbGlzdAoKaWYgWyAtZiAiJFBBSURfQkFTRS5saXN0IiBdOyB0aGVuCiAgZWNobyAiJFNDUklQVDogRGlzYWJsaW5nIFBWRSBwYWlkIHJlcG8gbGlzdCAuLi4iCiAgbXYgLWYgIiRQQUlEX0JBU0UubGlzdCIgIiRQQUlEX0JBU0UuZGlzYWJsZWQiCmZpCgoKIyBkaXNhYmxlIGxpY2Vuc2UgbmFnOiBodHRwczovL2pvaG5zY3MuY29tL3JlbW92ZS1wcm94bW94NTEtc3Vic2NyaXB0aW9uLW5vdGljZS8KCmlmIGdyZXAgLXFzICIkTkFHVE9LRU4iICIkTkFHRklMRSIgPiAvZGV2L251bGwgMj4mMTsgdGhlbgogIGVjaG8gIiRTQ1JJUFQ6IFJlbW92aW5nIE5hZyAuLi4iCiAgc2VkIC1pLm9yaWcgInMvJE5BR1RPS0VOL2ZhbHNlL2ciICIkTkFHRklMRSIKICBzeXN0ZW1jdGwgcmVzdGFydCBwdmVwcm94eS5zZXJ2aWNlCmZp" pmg_script="IyEvYmluL3NoCiMKIyBwbWctbmFnLWJ1c3Rlci5zaCAodjA1KSBodHRwczovL2dpdGh1Yi5jb20vZm91bmRPYmplY3RzL3B2ZS1uYWctYnVzdGVyCiMgQ29weXJpZ2h0IChDKSAyMDE5IC91L3NlYVF1ZXVlIChyZWRkaXQuY29tL3Uvc2VhUXVldWUpCiMKIyBSZW1vdmVzIFByb3htb3ggTWFpbCBHYXRld2F5IGxpY2Vuc2UgbmFncyBhdXRvbWF0aWNhbGx5IGFmdGVyIHVwZGF0ZXMKIwojIFRoaXMgcHJvZ3JhbSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IKIyBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZQojIGFzIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXIgdmVyc2lvbiAyCiMgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uCiMKIyBUaGlzIHByb2dyYW0gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwKIyBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZgojIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUKIyBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLgojCiMgWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UKIyBhbG9uZyB3aXRoIHRoaXMgcHJvZ3JhbTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZQojIEZvdW5kYXRpb24sIEluYy4sIDUxIEZyYW5rbGluIFN0cmVldCwgRmlmdGggRmxvb3IsIEJvc3RvbiwgTUEgIDAyMTEwLTEzMDEsIFVTQS4KCk5BR1RPS0VOPSJkYXRhLnN0YXR1cy50b0xvd2VyQ2FzZSgpICE9PSAnYWN0aXZlJyIKTkFHRklMRT0iL3Vzci9zaGFyZS9qYXZhc2NyaXB0L3Byb3htb3gtd2lkZ2V0LXRvb2xraXQvcHJveG1veGxpYi5qcyIKU0NSSVBUPSIkKGJhc2VuYW1lICIkMCIpIgpQQUlEX0JBU0U9Ii9ldGMvYXB0L3NvdXJjZXMubGlzdC5kL3BtZy1lbnRlcnByaXNlIgoKIyBkaXNhYmxlIHBhaWQgcmVwbyBsaXN0CgppZiBbIC1mICIkUEFJRF9CQVNFLmxpc3QiIF07IHRoZW4KICBlY2hvICIkU0NSSVBUOiBEaXNhYmxpbmcgUE1HIHBhaWQgcmVwbyBsaXN0IC4uLiIKICBtdiAtZiAiJFBBSURfQkFTRS5saXN0IiAiJFBBSURfQkFTRS5kaXNhYmxlZCIKZmkKCiMgZGlzYWJsZSBsaWNlbnNlIG5hZzogaHR0cHM6Ly9qb2huc2NzLmNvbS9yZW1vdmUtcHJveG1veDUxLXN1YnNjcmlwdGlvbi1ub3RpY2UvCgppZiBncmVwIC1xcyAiJE5BR1RPS0VOIiAiJE5BR0ZJTEUiID4gL2Rldi9udWxsIDI+JjE7IHRoZW4KICBlY2hvICIkU0NSSVBUOiBSZW1vdmluZyBOYWcgLi4uIgogIHNlZCAtaS5vcmlnICJzLyROQUdUT0tFTi9mYWxzZS9nIiAiJE5BR0ZJTEUiCiAgc3lzdGVtY3RsIHJlc3RhcnQgcG1ncHJveHkuc2VydmljZQpmaQ==" pbs_script="IyEvYmluL3NoCiMKIyBwYnMtbmFnLWJ1c3Rlci5zaCAodjA1KSBodHRwczovL2dpdGh1Yi5jb20vZm91bmRPYmplY3RzL3B2ZS1uYWctYnVzdGVyCiMgQ29weXJpZ2h0IChDKSAyMDE5IC91L3NlYVF1ZXVlIChyZWRkaXQuY29tL3Uvc2VhUXVldWUpCiMKIyBSZW1vdmVzIFByb3htb3ggQmFja3VwIFNlcnZlciBsaWNlbnNlIG5hZ3MgYXV0b21hdGljYWxseSBhZnRlciB1cGRhdGVzCiMKIyBUaGlzIHByb2dyYW0gaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yCiMgbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UKIyBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyIHZlcnNpb24gMgojIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLgojCiMgVGhpcyBwcm9ncmFtIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsCiMgYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YKIyBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlCiMgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy4KIwojIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlCiMgYWxvbmcgd2l0aCB0aGlzIHByb2dyYW07IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmUKIyBGb3VuZGF0aW9uLCBJbmMuLCA1MSBGcmFua2xpbiBTdHJlZXQsIEZpZnRoIEZsb29yLCBCb3N0b24sIE1BICAwMjExMC0xMzAxLCBVU0EuCgpOQUdUT0tFTj0iZGF0YS5zdGF0dXMudG9Mb3dlckNhc2UoKSAhPT0gJ2FjdGl2ZSciCk5BR0ZJTEU9Ii91c3Ivc2hhcmUvamF2YXNjcmlwdC9wcm94bW94LXdpZGdldC10b29sa2l0L3Byb3htb3hsaWIuanMiClNDUklQVD0iJChiYXNlbmFtZSAiJDAiKSIKUEFJRF9CQVNFPSIvZXRjL2FwdC9zb3VyY2VzLmxpc3QuZC9wYnMtZW50ZXJwcmlzZSIKCiMgZGlzYWJsZSBwYWlkIHJlcG8gbGlzdAoKaWYgWyAtZiAiJFBBSURfQkFTRS5saXN0IiBdOyB0aGVuCiAgZWNobyAiJFNDUklQVDogRGlzYWJsaW5nIFBWRSBwYWlkIHJlcG8gbGlzdCAuLi4iCiAgbXYgLWYgIiRQQUlEX0JBU0UubGlzdCIgIiRQQUlEX0JBU0UuZGlzYWJsZWQiCmZpCgojIGRpc2FibGUgbGljZW5zZSBuYWc6IGh0dHBzOi8vam9obnNjcy5jb20vcmVtb3ZlLXByb3htb3g1MS1zdWJzY3JpcHRpb24tbm90aWNlLwoKaWYgZ3JlcCAtcXMgIiROQUdUT0tFTiIgIiROQUdGSUxFIiA+IC9kZXYvbnVsbCAyPiYxOyB0aGVuCiAgZWNobyAiJFNDUklQVDogUmVtb3ZpbmcgTmFnIC4uLiIKICBzZWQgLWkub3JpZyAicy8kTkFHVE9LRU4vZmFsc2UvZyIgIiROQUdGSUxFIgogIHN5c3RlbWN0bCByZXN0YXJ0IHByb3htb3gtYmFja3VwLXByb3h5LnNlcnZpY2UKZmk=" case "$SERVICE" in "pve") echo ${pve_script} | base64 -d ;; "pmg") echo ${pmg_script} | base64 -d ;; "pbs") echo ${pbs_script} | base64 -d ;; esac } assert_root() { [ "$(id -u)" -eq '0' ] || { echo "This action requires root." && exit 1; }; } _usage() { echo "Usage: $(basename "$0") (--emit|--offline|--uninstall)"; } _main "$@"