Browse Source

Add support for local builds to the new kickstart script. (#11654)

* Initial local build support.

* Add support for soft disabling cloud on native packages and static builds.

* Don’t use sudo to run dependency installer on macOS.

* Fixes for source-based installs.

* Document the `--install` option.

* Improved reinstall handling.

* Fix install prefix handling for claiming.

* Update determining the latest static build tag.

This avoids using a rate-limited API.

* Improved existing install support error message.

* Improved reinstall handling to be more robust.

* Fix redirect URL handling.

* Fix handling of claiming of existing installs.

* Fix install-type handling.

* Address feedback from @vkalintiris.

* Add comment explaining non-obvious conditional case.

* Added better handling of unsafe reinstall situations.

Allowing the user to explicitly ask for a reinstall even if it may be
unsafe.

* Fix conditional in new reinstall code.

* Properly set `${INSTALL_PREFIX}` for successful static installs.

* Properly handle disabling telemetry.

The static builds and local builds already handle things correctly, so
we only need to handle native packages, but the opt-out has to happen
before the package gets installed as Netdata will usually be started by
the package install process.

* Fix handling of disabling cloud support.

* Fix redirection issue in cloud runtime handling.

* Assorted fixes in response to feedback from @ilyam8.

* Add cleanup call to other expected exit paths.

* Apply fixes from code review suggested by @ilyam8

Co-authored-by: Ilya Mashchenko <ilya@netdata.cloud>

* Update error messages.

* Fix indentation.

Co-authored-by: Ilya Mashchenko <ilya@netdata.cloud>
Austin S. Hemmelgarn 3 years ago
parent
commit
1a9bc2dadc
1 changed files with 402 additions and 121 deletions
  1. 402 121
      packaging/installer/kickstart-ng.sh

+ 402 - 121
packaging/installer/kickstart-ng.sh

@@ -5,6 +5,7 @@
 # ======================================================================
 # ======================================================================
 # Constants
 # Constants
 
 
+PACKAGES_SCRIPT="https://raw.githubusercontent.com/netdata/netdata/master/packaging/installer/install-required-packages.sh"
 REPOCONFIG_URL_PREFIX="https://packagecloud.io/netdata/netdata-repoconfig/packages"
 REPOCONFIG_URL_PREFIX="https://packagecloud.io/netdata/netdata-repoconfig/packages"
 REPOCONFIG_VERSION="1-1"
 REPOCONFIG_VERSION="1-1"
 PATH="${PATH}:/usr/local/bin:/usr/local/sbin"
 PATH="${PATH}:/usr/local/bin:/usr/local/sbin"
@@ -12,16 +13,20 @@ PATH="${PATH}:/usr/local/bin:/usr/local/sbin"
 # ======================================================================
 # ======================================================================
 # Defaults for environment variables
 # Defaults for environment variables
 
 
-RELEASE_CHANNEL="nightly"
-NETDATA_CLAIM_URL="https://app.netdata.cloud"
-NETDATA_CLAIM_ONLY=0
-NETDATA_USER_CONFIG_DIR="/etc/netdata"
+INSTALL_PREFIX=""
 NETDATA_AUTO_UPDATES="1"
 NETDATA_AUTO_UPDATES="1"
+NETDATA_CLAIM_ONLY=0
+NETDATA_CLAIM_URL="https://app.netdata.cloud"
+NETDATA_DISABLE_CLOUD=0
+NETDATA_ONLY_BUILD=0
 NETDATA_ONLY_NATIVE=0
 NETDATA_ONLY_NATIVE=0
 NETDATA_ONLY_STATIC=0
 NETDATA_ONLY_STATIC=0
+NETDATA_REQUIRE_CLOUD=1
+RELEASE_CHANNEL="nightly"
 
 
 NETDATA_DISABLE_TELEMETRY="${DO_NOT_TRACK:-0}"
 NETDATA_DISABLE_TELEMETRY="${DO_NOT_TRACK:-0}"
 NETDATA_TARBALL_BASEURL="${NETDATA_TARBALL_BASEURL:-https://storage.googleapis.com/netdata-nightlies}"
 NETDATA_TARBALL_BASEURL="${NETDATA_TARBALL_BASEURL:-https://storage.googleapis.com/netdata-nightlies}"
+NETDATA_INSTALLER_OPTIONS="${NETDATA_INSTALLER_OPTIONS:-""}"
 
 
 if [ ! -t 1 ]; then
 if [ ! -t 1 ]; then
   INTERACTIVE=0
   INTERACTIVE=0
@@ -47,7 +52,12 @@ USAGE: kickstart.sh [options]
   --disable-telemetry        Opt-out of anonymous statistics.
   --disable-telemetry        Opt-out of anonymous statistics.
   --native-only              Only install if native binary packages are available.
   --native-only              Only install if native binary packages are available.
   --static-only              Only install if a static build is available.
   --static-only              Only install if a static build is available.
+  --build-only               Only install using a local build.
   --reinstall                Explicitly reinstall instead of updating any existing install.
   --reinstall                Explicitly reinstall instead of updating any existing install.
+  --reinstall-even-if-unsafe Even try to reinstall if we don't think we can do so safely (implies --reinstall).
+  --disable-cloud            Disable support for Netdata Cloud (default: detect)
+  --require-cloud            Only install if Netdata Cloud can be enabled. Overrides --disable-cloud.
+  --install <path>           Specify an installation prefix for local builds (default: autodetect based on system type).
   --claim-token              Use a specified token for claiming to Netdata Cloud.
   --claim-token              Use a specified token for claiming to Netdata Cloud.
   --claim-rooms              When claiming, add the node to the specified rooms.
   --claim-rooms              When claiming, add the node to the specified rooms.
   --claim-only               If there is an existing install, only try to claim it, not update it.
   --claim-only               If there is an existing install, only try to claim it, not update it.
@@ -64,6 +74,7 @@ Additionally, this script may use the following environment variables:
                              you need special options for one of those to work, or have a different tool to do
                              you need special options for one of those to work, or have a different tool to do
                              the same thing on your system, you can specify it here.
                              the same thing on your system, you can specify it here.
   DO_NOT_TRACK               If set to a value other than 0, behave as if \`--disable-telemetry\` was specified.
   DO_NOT_TRACK               If set to a value other than 0, behave as if \`--disable-telemetry\` was specified.
+  NETDATA_INSTALLER_OPTIONS: Specifies extra options to pass to the static installer or local build script.
 
 
 HEREDOC
 HEREDOC
 }
 }
@@ -99,8 +110,15 @@ setup_terminal() {
   return 0
   return 0
 }
 }
 
 
+cleanup() {
+  if [ -z "${NO_CLEANUP}" ]; then
+    ${ROOTCMD} rm -rf "${tmpdir}"
+  fi
+}
+
 fatal() {
 fatal() {
   printf >&2 "%s\n\n" "${TPUT_BGRED}${TPUT_WHITE}${TPUT_BOLD} ABORTED ${TPUT_RESET} ${*}"
   printf >&2 "%s\n\n" "${TPUT_BGRED}${TPUT_WHITE}${TPUT_BOLD} ABORTED ${TPUT_RESET} ${*}"
+  cleanup
   exit 1
   exit 1
 }
 }
 
 
@@ -216,10 +234,20 @@ download() {
     run curl -q -sSL --connect-timeout 10 --retry 3 --output "${dest}" "${url}" || return 1
     run curl -q -sSL --connect-timeout 10 --retry 3 --output "${dest}" "${url}" || return 1
   elif command -v wget > /dev/null 2>&1; then
   elif command -v wget > /dev/null 2>&1; then
     run wget -T 15 -O "${dest}" "${url}" || return 1
     run wget -T 15 -O "${dest}" "${url}" || return 1
-  elif command -v fetch > /dev/null 2>&1; then # Native FreeBSD tool
-    run fetch -T 15 -a -o "${dest}" "${url}" || return 1
   else
   else
-    fatal "I need curl, wget, or fetch to proceed, but none of them are available on this system."
+    fatal "I need curl or wget to proceed, but neither of them are available on this system."
+  fi
+}
+
+get_redirect() {
+  url="${1}"
+
+  if command -v curl > /dev/null 2>&1; then
+    run sh -c "curl ${url} -s -L -I -o /dev/null -w '%{url_effective}' | grep -o '[^/]*$'" || return 1
+  elif command -v wget > /dev/null 2>&1; then
+    run sh -c "wget --max-redirect=0 ${url} 2>&1 | grep Location | cut -d ' ' -f2  | grep -o '[^/]*$'" || return 1
+  else
+    fatal "I need curl or wget to proceed, but neither of them are available on this system."
   fi
   fi
 }
 }
 
 
@@ -316,6 +344,21 @@ confirm_root_support() {
   fi
   fi
 }
 }
 
 
+confirm() {
+  prompt="${1} [y/n]"
+
+  while true; do
+    echo "${prompt}"
+    read -r yn
+
+    case "$yn" in
+      [Yy]*) return 0;;
+      [Nn]*) return 1;;
+      *) echo "Please answer yes or no.";;
+    esac
+  done
+}
+
 # ======================================================================
 # ======================================================================
 # Existing install handling code
 # Existing install handling code
 
 
@@ -369,74 +412,131 @@ handle_existing_install() {
   fi
   fi
 
 
   case "${INSTALL_TYPE}" in
   case "${INSTALL_TYPE}" in
-    kickstart-*|legacy-*|manual-static)
-      if [ -n "${NETDATA_REINSTALL}" ]; then
+    kickstart-*|legacy-*|binpkg-*|manual-static|unknown)
+      if [ "${INSTALL_TYPE}" = "unknown" ]; then
+        warning "Found an existing netdata install at ${ndprefix}, but could not determine the install type."
+      else
+        progress "Found an existing netdata install at ${ndprefix}, with installation type '${INSTALL_TYPE}'."
+      fi
+
+      if [ -n "${NETDATA_REINSTALL}" ] || [ -n "${NETDATA_UNSAFE_REINSTALL}" ]; then
         progress "Found an existing netdata install at ${ndprefix}, but user requested reinstall, continuing."
         progress "Found an existing netdata install at ${ndprefix}, but user requested reinstall, continuing."
+
+        case "${INSTALL_TYPE}" in
+          binpkg-*) NETDATA_ONLY_NATIVE=1 ;;
+          *-build) NETDATA_ONLY_BUILD=1 ;;
+          *-static) NETDATA_ONLY_STATIC=1 ;;
+          *)
+            if [ -n "${NETDATA_UNSAFE_REINSTALL}" ]; then
+              warning "Reinstalling over top of a ${INSTALL_TYPE} installation may be unsafe, but the user has requested we proceed."
+            elif [ "${INTERACTIVE}" -eq 0 ]; then
+              fatal "User requested reinstall, but we cannot safely reinstall over top of a ${INSTALL_TYPE} installation, exiting."
+            else
+              if confirm "Reinstalling over top of a ${INSTALL_TYPE} installation may be unsafe, do you want to continue?"; then
+                progress "OK, continuing."
+              else
+                fatal "Cancelling reinstallation at user request."
+              fi
+            fi
+            ;;
+        esac
+
         return 0
         return 0
       fi
       fi
 
 
       ret=0
       ret=0
 
 
-      if [ "${NETDATA_CLAIM_ONLY}" -eq 0 ]; then
+      if [ "${NETDATA_CLAIM_ONLY}" -eq 0 ] && echo "${INSTALL_TYPE}" | grep -vq "binpkg-*"; then
         if ! update; then
         if ! update; then
           warning "Unable to find usable updater script, not updating existing install at ${ndprefix}."
           warning "Unable to find usable updater script, not updating existing install at ${ndprefix}."
         fi
         fi
+      else
+        warning "Not updating existing install at ${ndprefix}."
       fi
       fi
 
 
       if [ -n "${NETDATA_CLAIM_TOKEN}" ]; then
       if [ -n "${NETDATA_CLAIM_TOKEN}" ]; then
         progress "Attempting to claim existing install at ${ndprefix}."
         progress "Attempting to claim existing install at ${ndprefix}."
+        INSTALL_PREFIX="${ndprefix}"
         claim
         claim
         ret=$?
         ret=$?
       elif [ "${NETDATA_CLAIM_ONLY}" -eq 1 ]; then
       elif [ "${NETDATA_CLAIM_ONLY}" -eq 1 ]; then
         fatal "User asked to claim, but did not proide a claiming token."
         fatal "User asked to claim, but did not proide a claiming token."
+      else
+        progress "Not attempting to claim existing install at ${ndprefix} (no claiming token provided)."
       fi
       fi
 
 
-      exit $ret
-      ;;
-    binpkg-*)
-      ret=0
-
-      if [ -n "${NETDATA_CLAIM_TOKEN}" ]; then
-        progress "Attempting to claim existing install at ${ndprefix}."
-        claim
-        ret=$?
-      fi
-
+      cleanup
       exit $ret
       exit $ret
       ;;
       ;;
     oci)
     oci)
       fatal "This is an OCI container, use the regular image lifecycle management commands in your container instead of this script for managing it."
       fatal "This is an OCI container, use the regular image lifecycle management commands in your container instead of this script for managing it."
       ;;
       ;;
-    unknown)
-      warning "Found an existing netdata install at ${ndprefix}, but could not determine the install type."
-
-      if [ -n "${NETDATA_REINSTALL}" ]; then
-        progress "Found an existing netdata install at ${ndprefix}, but user requested reinstall, continuing."
-        return 0
+    *)
+      if [ -n "${NETDATA_REINSTALL}" ] || [ -n "${NETDATA_UNSAFE_REINSTALL}" ]; then
+        if [ -n "${NETDATA_UNSAFE_REINSTALL}" ]; then
+          warning "Reinstalling over top of a ${INSTALL_TYPE} installation may be unsafe, but the user has requested we proceed."
+        elif [ "${INTERACTIVE}" -eq 0 ]; then
+          fatal "User requested reinstall, but we cannot safely reinstall over top of a ${INSTALL_TYPE} installation, exiting."
+        else
+          if confirm "Reinstalling over top of a ${INSTALL_TYPE} installation may be unsafe, do you want to continue?"; then
+            progress "OK, continuing."
+          else
+            fatal "Cancelling reinstallation at user request."
+          fi
+        fi
+      else
+        fatal "Found an existing netdata install at ${ndprefix}, but the install type is '${INSTALL_TYPE}', which is not supported, refusing to proceed."
       fi
       fi
+      ;;
+  esac
+}
 
 
-      ret=0
-
-      if [ "${NETDATA_CLAIM_ONLY}" -eq 0 ]; then
-        if ! update; then
-          warning "Unable to find usable updater script, not updating existing install at ${ndprefix}."
+soft_disable_cloud() {
+  cloud_prefix="${INSTALL_PREFIX}/var/lib/netdata/cloud.d"
+
+  run ${ROOTCMD} mkdir -p "${cloud_prefix}"
+
+  cat > "${tmpdir}/cloud.conf" << EOF
+[global]
+  enabled = no
+EOF
+
+  run ${ROOTCMD} cp "${tmpdir}/cloud.conf" "${cloud_prefix}/cloud.conf"
+
+  if [ -z "${NETDATA_NO_START}" ]; then
+    case "${SYSTYPE}" in
+      Darwin) run ${ROOTCMD} launchctl kickstart -k com.github.netdata ;;
+      FreeBSD) run ${ROOTCMD} service netdata restart ;;
+      Linux)
+        initpath="$(${ROOTCMD} readlink /proc/1/exe)"
+
+        if command -v service > /dev/null 2>&1; then
+          run ${ROOTCMD} service netdata restart
+        elif command -v rc-service > /dev/null 2>&1; then
+          run ${ROOTCMD} rc-service netdata restart
+        elif [ "$(basename "${initpath}" 2> /dev/null)" = "systemd" ]; then
+          run ${ROOTCMD} systemctl restart netdata
+        elif [ -f /etc/init.d/netdata ]; then
+          run ${ROOTCMD} /etc/init.d/netdata restart
         fi
         fi
-      fi
+        ;;
+    esac
+  fi
+}
 
 
-      if [ -n "${NETDATA_CLAIM_TOKEN}" ]; then
-        progress "Attempting to claim existing install at ${ndprefix}."
-        claim
-        ret=$?
-      elif [ "${NETDATA_CLAIM_ONLY}" -eq 1 ]; then
-        fatal "User asked to claim, but did not proide a claiming token."
-      fi
+confirm_install_prefix() {
+  if [ -n "${INSTALL_PREFIX}" ] && [ "${NETDATA_ONLY_BUILD}" -ne 1 ]; then
+    fatal "The \`--install\` option is only supported together with the \`--only-build\` option."
+  fi
 
 
-      exit $ret
-      ;;
-    *)
-      fatal "Found an existing netdata install at ${ndprefix}, but it is not a supported install type, refusing to proceed."
-      ;;
+  case "${SYSTYPE}" in
+    Darwin) INSTALL_PREFIX="${INSTALL_PREFIX:-/usr/local/netdata}" ;;
+    FreeBSD) INSTALL_PREFIX="${INSTALL_PREFIX:-/usr/local}" ;;
   esac
   esac
+
+  if [ -n "${INSTALL_PREFIX}" ]; then
+    NETDATA_INSTALLER_OPTIONS="${NETDATA_INSTALLER_OPTIONS} --install ${INSTALL_PREFIX}"
+  fi
 }
 }
 
 
 # ======================================================================
 # ======================================================================
@@ -448,17 +548,19 @@ check_claim_opts() {
     fatal "Invalid claiming options, claim rooms may only be specified when a token and URL are specified."
     fatal "Invalid claiming options, claim rooms may only be specified when a token and URL are specified."
   elif [ -z "${NETDATA_CLAIM_TOKEN}" ] && [ -n "${NETDATA_CLAIM_EXTRA}" ]; then
   elif [ -z "${NETDATA_CLAIM_TOKEN}" ] && [ -n "${NETDATA_CLAIM_EXTRA}" ]; then
     fatal "Invalid claiming options, a claiming token must be specified."
     fatal "Invalid claiming options, a claiming token must be specified."
+  elif [ "${NETDATA_DISABLE_CLOUD}" -eq 1 ] && [ -n "${NETDATA_CLAIM_TOKEN}" ]; then
+    fatal "Cloud explicitly disabled, but automatic claiming requested. Either enable Netdata Cloud, or remove the --claim-* options."
   fi
   fi
 }
 }
 
 
 claim() {
 claim() {
   progress "Attempting to claim agent to ${NETDATA_CLAIM_URL}"
   progress "Attempting to claim agent to ${NETDATA_CLAIM_URL}"
-  if [ -z "${NETDATA_PREFIX}" ]; then
+  if [ -z "${INSTALL_PREFIX}" ]; then
     NETDATA_CLAIM_PATH=/usr/sbin/netdata-claim.sh
     NETDATA_CLAIM_PATH=/usr/sbin/netdata-claim.sh
-  elif [ "${NETDATA_PREFIX}" = "/opt/netdata" ]; then
+  elif [ "${INSTALL_PREFIX}" = "/opt/netdata" ]; then
     NETDATA_CLAIM_PATH="/opt/netdata/bin/netdata-claim.sh"
     NETDATA_CLAIM_PATH="/opt/netdata/bin/netdata-claim.sh"
   else
   else
-    NETDATA_CLAIM_PATH="${NETDATA_PREFIX}/netdata/usr/sbin/netdata-claim.sh"
+    NETDATA_CLAIM_PATH="${INSTALL_PREFIX}/netdata/usr/sbin/netdata-claim.sh"
   fi
   fi
 
 
   if ! pgrep netdata > /dev/null; then
   if ! pgrep netdata > /dev/null; then
@@ -471,6 +573,7 @@ claim() {
   else
   else
     warning "Unable to claim node, you must do so manually."
     warning "Unable to claim node, you must do so manually."
     if [ -z "${NETDATA_NEW_INSTALL}" ]; then
     if [ -z "${NETDATA_NEW_INSTALL}" ]; then
+      cleanup
       exit 1
       exit 1
     fi
     fi
   fi
   fi
@@ -697,6 +800,11 @@ try_package_install() {
     return 2
     return 2
   fi
   fi
 
 
+  if [ "${NETDATA_DISABLE_TELEMETRY}" -eq 1 ]; then
+    run ${ROOTCMD} mkdir -p "/etc/netdata"
+    run ${ROOTCMD} touch "/etc/netdata/.opt-out-from-anonymous-statistics"
+  fi
+
   progress "Installing Netdata package."
   progress "Installing Netdata package."
   # shellcheck disable=SC2086
   # shellcheck disable=SC2086
   if ! run ${ROOTCMD} env ${env} ${pm_cmd} install ${pkg_install_opts} netdata; then
   if ! run ${ROOTCMD} env ${env} ${pm_cmd} install ${pkg_install_opts} netdata; then
@@ -715,7 +823,7 @@ try_package_install() {
 
 
 set_static_archive_urls() {
 set_static_archive_urls() {
   if [ "${RELEASE_CHANNEL}" = "stable" ]; then
   if [ "${RELEASE_CHANNEL}" = "stable" ]; then
-    latest="$(download "https://api.github.com/repos/netdata/netdata/releases/latest" /dev/stdout | grep tag_name | cut -d'"' -f4)"
+    latest="$(get_redirect "https://github.com/netdata/netdata/releases/latest")"
     export NETDATA_STATIC_ARCHIVE_URL="https://github.com/netdata/netdata/releases/download/${latest}/netdata-${SYSARCH}-${latest}.gz.run"
     export NETDATA_STATIC_ARCHIVE_URL="https://github.com/netdata/netdata/releases/download/${latest}/netdata-${SYSARCH}-${latest}.gz.run"
     export NETDATA_STATIC_ARCHIVE_CHECKSUM_URL="https://github.com/netdata/netdata/releases/download/${latest}/sha256sums.txt"
     export NETDATA_STATIC_ARCHIVE_CHECKSUM_URL="https://github.com/netdata/netdata/releases/download/${latest}/sha256sums.txt"
   else
   else
@@ -738,7 +846,7 @@ try_static_install() {
   fi
   fi
 
 
   if ! grep "netdata-${SYSARCH}-latest.gz.run" "${tmpdir}/sha256sum.txt" | safe_sha256sum -c - > /dev/null 2>&1; then
   if ! grep "netdata-${SYSARCH}-latest.gz.run" "${tmpdir}/sha256sum.txt" | safe_sha256sum -c - > /dev/null 2>&1; then
-    fatal "Static binary checksum validation failed. Stopping Netdata Agent installation and leaving binary in ${tmpdir}. Usually this is a result of an older copy of the file being cached somewhere upstream and can be resolved by retrying in an hour."
+    fatal "Static binary checksum validation failed. Usually this is a result of an older copy of the file being cached somewhere upstream and can be resolved by retrying in an hour."
   fi
   fi
 
 
   if [ "${INTERACTIVE}" -eq 0 ]; then
   if [ "${INTERACTIVE}" -eq 0 ]; then
@@ -766,6 +874,209 @@ try_static_install() {
   fi
   fi
 }
 }
 
 
+# ======================================================================
+# Local build install code
+
+set_source_archive_urls() {
+  if [ "$1" = "stable" ]; then
+    latest="$(get_redirect "https://github.com/netdata/netdata/releases/latest")"
+    export NETDATA_SOURCE_ARCHIVE_URL="https://github.com/netdata/netdata/releases/download/${latest}/netdata-${latest}.tar.gz"
+    export NETDATA_SOURCE_ARCHIVE_CHECKSUM_URL="https://github.com/netdata/netdata/releases/download/${latest}/sha256sums.txt"
+  else
+    export NETDATA_SOURCE_ARCHIVE_URL="${NETDATA_TARBALL_BASEURL}/netdata-latest.tar.gz"
+    export NETDATA_SOURCE_ARCHIVE_CHECKSUM_URL="${NETDATA_TARBALL_BASEURL}/sha256sums.txt"
+  fi
+}
+
+install_local_build_dependencies() {
+  bash="$(command -v bash 2> /dev/null)"
+
+  if [ -z "${bash}" ] || [ ! -x "${bash}" ]; then
+    warning "Unable to find a usable version of \`bash\` (required for local build)."
+    return 1
+  fi
+
+  progress "Fetching script to detect required packages..."
+  download "${PACKAGES_SCRIPT}" "${tmpdir}/install-required-packages.sh"
+
+  if [ ! -s "${tmpdir}/install-required-packages.sh" ]; then
+    warning "Downloaded dependency installation script is empty."
+  else
+    progress "Running downloaded script to detect required packages..."
+
+    if [ "${INTERACTIVE}" -eq 0 ]; then
+      opts="--dont-wait --non-interactive"
+    fi
+
+    if [ "${SYSTYPE}" = "Darwin" ]; then
+      sudo=""
+    else
+      sudo="${ROOTCMD}"
+    fi
+
+    # shellcheck disable=SC2086
+    if ! run ${sudo} "${bash}" "${tmpdir}/install-required-packages.sh" ${opts} netdata; then
+      warning "It failed to install all the required packages, but installation might still be possible."
+    fi
+  fi
+}
+
+build_and_install() {
+  progress "Building netdata"
+
+  echo "INSTALL_TYPE='kickstart-build'" > system/.install-type
+
+  opts="${NETDATA_INSTALLER_OPTIONS}"
+
+  if [ "${INTERACTIVE}" -eq 0 ]; then
+    opts="${opts} --dont-wait"
+  fi
+
+  if [ "${NETDATA_AUTO_UPDATES}" -eq 1 ]; then
+    opts="${opts} --auto-update"
+  fi
+
+  if [ "${RELEASE_CHANNEL}" = "stable" ]; then
+    opts="${opts} --stable-channel"
+  fi
+
+  if [ "${NETDATA_REQUIRE_CLOUD}" -eq 1 ]; then
+    opts="${opts} --require-cloud"
+  elif [ "${NETDATA_DISABLE_CLOUD}" -eq 1 ]; then
+    opts="${opts} --disable-cloud"
+  fi
+
+  # shellcheck disable=SC2086
+  run ${ROOTCMD} ./netdata-installer.sh ${opts} || fatal "netdata-installer.sh exited with error"
+}
+
+try_build_install() {
+  if ! install_local_build_dependencies; then
+    return 1
+  fi
+
+  set_source_archive_urls "${RELEASE_CHANNEL}"
+
+  download "${NETDATA_SOURCE_ARCHIVE_CHECKSUM_URL}" "${tmpdir}/sha256sum.txt"
+  download "${NETDATA_SOURCE_ARCHIVE_URL}" "${tmpdir}/netdata-latest.tar.gz"
+
+  if ! grep netdata-latest.tar.gz "${tmpdir}/sha256sum.txt" | safe_sha256sum -c - > /dev/null 2>&1; then
+    fatal "Tarball checksum validation failed. Usually this is a result of an older copy of the file being cached somewhere upstream and can be resolved by retrying in an hour."
+  fi
+
+  run tar -xf "${tmpdir}/netdata-latest.tar.gz" -C "${tmpdir}"
+  rm -rf "${tmpdir}/netdata-latest.tar.gz" > /dev/null 2>&1
+  cd "$(find "${tmpdir}" -mindepth 1 -maxdepth 1 -type d -name netdata-)" || fatal "Cannot cd to netdata source tree"
+
+  if [ -x netdata-installer.sh ]; then
+    build_and_install || return 1
+  else
+    # This case is needed because some platforms produce an extra directory on the source tarball extraction.
+    if [ "$(find . -mindepth 1 -maxdepth 1 -type d | wc -l)" -eq 1 ] && [ -x "$(find . -mindepth 1 -maxdepth 1 -type d)/netdata-installer.sh" ]; then
+      cd "$(find . -mindepth 1 -maxdepth 1 -type d)" &&  build_and_install || return 1
+    else
+      fatal "Cannot install netdata from source (the source directory does not include netdata-installer.sh). Leaving all files in ${tmpdir}"
+    fi
+  fi
+}
+
+# ======================================================================
+# Per system-type install logic
+
+install_on_linux() {
+  if [ "${NETDATA_ONLY_STATIC}" -ne 1 ] && [ "${NETDATA_ONLY_BUILD}" -ne 1 ]; then
+    try_package_install
+
+    case "$?" in
+      0)
+        NETDATA_INSTALL_SUCCESSFUL=1
+        ;;
+      1)
+        fatal "Unable to install on this system."
+        ;;
+      2)
+        if [ "${NETDATA_ONLY_NATIVE}" -eq 1 ]; then
+          fatal "Could not install native binary packages."
+        else
+          warning "Could not install native binary packages, falling back to alternative installation method."
+        fi
+        ;;
+    esac
+  fi
+
+  if [ "${NETDATA_ONLY_NATIVE}" -ne 1 ] && [ "${NETDATA_ONLY_BUILD}" -ne 1 ] && [ -z "${NETDATA_INSTALL_SUCCESSFUL}" ]; then
+    try_static_install
+
+    case "$?" in
+      0)
+        NETDATA_INSTALL_SUCCESSFUL=1
+        INSTALL_PREFIX="/opt/netdata"
+        ;;
+      1)
+        fatal "Unable to install on this system."
+        ;;
+      2)
+        if [ "${NETDATA_ONLY_STATIC}" -eq 1 ]; then
+          fatal "Could not install static build."
+        else
+          warning "Could not install static build, falling back to alternative installation method."
+        fi
+        ;;
+    esac
+  fi
+
+  if [ "${NETDATA_ONLY_NATIVE}" -ne 1 ] && [ "${NETDATA_ONLY_STATIC}" -ne 1 ] && [ -z "${NETDATA_INSTALL_SUCCESSFUL}" ]; then
+    try_build_install
+
+    case "$?" in
+      0)
+        NETDATA_INSTALL_SUCCESSFUL=1
+        ;;
+      *)
+        fatal "Unable to install on this system."
+        ;;
+    esac
+  fi
+}
+
+install_on_macos() {
+  if [ "${NETDATA_ONLY_NATIVE}" -eq 1 ]; then
+    fatal "User requested native package, but native packages are not available for macOS. Try installing without \`--only-native\` option."
+  elif [ "${NETDATA_ONLY_STATIC}" -eq 1 ]; then
+    fatal "User requested static build, but static builds are not available for macOS. Try installing without \`--only-static\` option."
+  else
+    try_build_install
+
+    case "$?" in
+      0)
+        NETDATA_INSTALL_SUCCESSFUL=1
+        ;;
+      *)
+        fatal "Unable to install on this system."
+        ;;
+    esac
+  fi
+}
+
+install_on_freebsd() {
+  if [ "${NETDATA_ONLY_NATIVE}" -eq 1 ]; then
+    fatal "User requested native package, but native packages are not available for FreeBSD. Try installing without \`--only-native\` option."
+  elif [ "${NETDATA_ONLY_STATIC}" -eq 1 ]; then
+    fatal "User requested static build, but static builds are not available for FreeBSD. Try installing without \`--only-static\` option."
+  else
+    try_build_install
+
+    case "$?" in
+      0)
+        NETDATA_INSTALL_SUCCESSFUL=1
+        ;;
+      *)
+        fatal "Unable to install on this system."
+        ;;
+    esac
+  fi
+}
+
 # ======================================================================
 # ======================================================================
 # Main program
 # Main program
 
 
@@ -775,28 +1086,54 @@ while [ -n "${1}" ]; do
   case "${1}" in
   case "${1}" in
     "--help")
     "--help")
       usage
       usage
+      cleanup
       exit 0
       exit 0
       ;;
       ;;
     "--no-cleanup") NO_CLEANUP=1 ;;
     "--no-cleanup") NO_CLEANUP=1 ;;
     "--dont-wait"|"--non-interactive") INTERACTIVE=0 ;;
     "--dont-wait"|"--non-interactive") INTERACTIVE=0 ;;
     "--interactive") INTERACTIVE=1 ;;
     "--interactive") INTERACTIVE=1 ;;
     "--stable-channel") RELEASE_CHANNEL="stable" ;;
     "--stable-channel") RELEASE_CHANNEL="stable" ;;
-    "--no-updates") NETDATA_AUTO_UPDATES="" ;;
+    "--no-updates") NETDATA_AUTO_UPDATES=0 ;;
     "--auto-update") NETDATA_AUTO_UPDATES="1" ;;
     "--auto-update") NETDATA_AUTO_UPDATES="1" ;;
-    "--disable-telemetry") NETDATA_DISABLE_TELEMETRY="1" ;;
     "--reinstall") NETDATA_REINSTALL=1 ;;
     "--reinstall") NETDATA_REINSTALL=1 ;;
+    "--reinstall-even-if-unsafe") NETDATA_UNSAFE_REINSTALL=1 ;;
     "--claim-only") NETDATA_CLAIM_ONLY=1 ;;
     "--claim-only") NETDATA_CLAIM_ONLY=1 ;;
+    "--disable-cloud")
+      NETDATA_DISABLE_CLOUD=1
+      NETDATA_REQUIRE_CLOUD=0
+      ;;
+    "--require-cloud")
+      NETDATA_DISABLE_CLOUD=0
+      NETDATA_REQUIRE_CLOUD=1
+      ;;
+    "--dont-start-it")
+      NETDATA_NO_START=1
+      NETDATA_INSTALLER_OPTIONS="${NETDATA_INSTALLER_OPTIONS} --dont-start-it"
+      ;;
+    "--disable-telemetry")
+      NETDATA_DISABLE_TELEMETRY="0"
+      NETDATA_INSTALLER_OPTIONS="${NETDATA_INSTALLER_OPTIONS} --disable-telemetry"
+      ;;
+    "--install")
+      INSTALL_PREFIX="${2}"
+      shift 1
+      ;;
     "--native-only")
     "--native-only")
       NETDATA_ONLY_NATIVE=1
       NETDATA_ONLY_NATIVE=1
       NETDATA_ONLY_STATIC=0
       NETDATA_ONLY_STATIC=0
+      NETDATA_ONLY_BUILD=0
       ;;
       ;;
     "--static-only")
     "--static-only")
       NETDATA_ONLY_STATIC=1
       NETDATA_ONLY_STATIC=1
       NETDATA_ONLY_NATIVE=0
       NETDATA_ONLY_NATIVE=0
+      NETDATA_ONLY_BUILD=0
       ;;
       ;;
-    "--dont-start-it")
-      NETDATA_INSTALLER_OPTIONS="${NETDATA_INSTALLER_OPTIONS} --dont-start-it"
+    "--build-only")
+      NETDATA_ONLY_BUILD=1
+      NETDATA_ONLY_NATIVE=0
+      NETDATA_ONLY_STATIC=0
       ;;
       ;;
+
     "--claim-token")
     "--claim-token")
       NETDATA_CLAIM_TOKEN="${2}"
       NETDATA_CLAIM_TOKEN="${2}"
       shift 1
       shift 1
@@ -824,6 +1161,10 @@ while [ -n "${1}" ]; do
           ;;
           ;;
       esac
       esac
       ;;
       ;;
+    *)
+      warning "Passing unrecognized option '${1}' to installer script. If this is intended, please add it to \$NETDATA_INSTALLER_OPTIONS instead."
+      NETDATA_INSTALLER_OPTIONS="${NETDATA_INSTALLER_OPTIONS} ${1}"
+      ;;
   esac
   esac
   shift 1
   shift 1
 done
 done
@@ -831,6 +1172,7 @@ done
 check_claim_opts
 check_claim_opts
 confirm_root_support
 confirm_root_support
 get_system_info
 get_system_info
+confirm_install_prefix
 
 
 tmpdir="$(create_tmp_directory)"
 tmpdir="$(create_tmp_directory)"
 progress "Using ${tmpdir} as a temporary directory."
 progress "Using ${tmpdir} as a temporary directory."
@@ -839,76 +1181,15 @@ cd "${tmpdir}" || exit 1
 handle_existing_install
 handle_existing_install
 
 
 case "${SYSTYPE}" in
 case "${SYSTYPE}" in
-  Linux)
-    if [ "${NETDATA_ONLY_STATIC}" -ne 1 ]; then
-      try_package_install
-
-      case "$?" in
-        0)
-          NETDATA_INSTALL_SUCCESSFUL=1
-          ;;
-        1)
-          fatal "Unable to install on this system."
-          ;;
-        2)
-          if [ "${NETDATA_ONLY_NATIVE}" -eq 1 ]; then
-            fatal "Could not install native binary packages."
-          else
-            warning "Could not install native binary packages, falling back to alternative installation method."
-          fi
-          ;;
-      esac
-    fi
-
-    if [ "${NETDATA_ONLY_NATIVE}" -ne 1 ] && [ -z "${NETDATA_INSTALL_SUCCESSFUL}" ]; then
-      try_static_install
-
-      case "$?" in
-        0)
-          NETDATA_INSTALL_SUCCESSFUL=1
-          NETDATA_USER_CONFIG_DIR="/opt/netdata/etc/netdata"
-          ;;
-        1)
-          fatal "Unable to install on this system."
-          ;;
-        2)
-          if [ "${NETDATA_ONLY_STATIC}" -eq 1 ]; then
-            fatal "Could not install static build."
-          else
-            warning "Could not install static build, falling back to alternative installation method."
-          fi
-          ;;
-      esac
-    fi
-    ;;
-  Darwin)
-    if [ "${NETDATA_ONLY_NATIVE}" -eq 1 ]; then
-      fatal "User requested native package, but native packages are not available for macOS. Try installing without \`--only-native\` option."
-    elif [ "${NETDATA_ONLY_STATIC}" -eq 1 ]; then
-      fatal "User requested static build, but static builds are not available for macOS. Try installing without \`--only-static\` option."
-    else
-      fatal "This script currently does not support installation on macOS."
-    fi
-    ;;
-  FreeBSD)
-    if [ "${NETDATA_ONLY_NATIVE}" -eq 1 ]; then
-      fatal "User requested native package, but native packages are not available for FreeBSD. Try installing without \`--only-native\` option."
-    elif [ "${NETDATA_ONLY_STATIC}" -eq 1 ]; then
-      fatal "User requested static build, but static builds are not available for FreeBSD. Try installing without \`--only-static\` option."
-    else
-      fatal "This script currently does not support installation on FreeBSD."
-    fi
-    ;;
+  Linux) install_on_linux ;;
+  Darwin) install_on_macos ;;
+  FreeBSD) install_on_freebsd ;;
 esac
 esac
 
 
-if [ "${NETDATA_DISABLE_TELEMETRY}" -eq 1 ]; then
-  run ${ROOTCMD} touch "${NETDATA_USER_CONFIG_DIR}/.opt-out-from-anonymous-statistics"
-fi
-
 if [ -n "${NETDATA_CLAIM_TOKEN}" ]; then
 if [ -n "${NETDATA_CLAIM_TOKEN}" ]; then
   claim
   claim
+elif [ "${NETDATA_DISABLE_CLOUD}" -eq 1 ]; then
+  soft_disable_cloud
 fi
 fi
 
 
-if [ -z "${NO_CLEANUP}" ]; then
-  ${ROOTCMD} rm -rf "${tmpdir}"
-fi
+cleanup