Skip to content
jumpsmm7 edited this page Jan 5, 2021 · 41 revisions

Automatic Update For Linux

The script below will check to see if dnscrypt-proxy needs updating by comparing the installed version with the latest git version.

If the installed version is older, then the script will update to the newest version.

Tested on: Ubuntu 18.04

Requirements

This script requires dnscrypt-proxy to be installed as a service using,./dnscrypt-proxy -service install and for dnscrypt-proxy to be installed in /opt/dnscrypt-proxy.

(optional) Install Minisign to verify downloaded update.

Configuration

Initially make sure all the above requirements are met.

Then to get this script to automatically run add this as a cron job under root using sudo crontab -e but, change the file path to the file path the script is saved.

Run sudo crontab -e in terminal. If running for the first time, it would ask you to choose an editor. nano is the recommended one.

Enter this command in a new line: 0 */12 * * * /path/dnscrypt-proxy-update.sh

replace path with where you saved the dnscrypt-proxy-update.sh file.

This script needs to be run as root.

It assumes that you are running Linux on an x86_64 CPU. Change linux and x86_64 in the PLATFORM and CPU_ARCH variables respectivly to the actual platform you are running if it is different (for example, on a Raspberry Pi, it should probably be linux_arm instead of linux_x86_64).

#! /bin/sh

INSTALL_DIR="/opt/dnscrypt-proxy"
LATEST_URL="https://api.github.com/repos/DNSCrypt/dnscrypt-proxy/releases/latest"
DNSCRYPT_PUBLIC_KEY="RWTk1xXqcTODeYttYMCMLo0YJHaFEHn7a3akqHlb/7QvIQXHVPxKbjB5"
PLATFORM="linux"
CPU_ARCH="x86_64"

Update() {
  workdir="$(mktemp -d)"
  download_url="$(curl -sL "$LATEST_URL" | grep dnscrypt-proxy-${PLATFORM}_${CPU_ARCH}- | grep browser_download_url | head -1 | cut -d \" -f 4)"
  echo "[INFO] Downloading update from '$download_url'..."
  download_file="dnscrypt-proxy-update.tar.gz"
  curl --request GET -sL --url "$download_url" --output "$workdir/$download_file"
  response=$?

  if [ $response -ne 0 ]; then
    echo "[ERROR] Could not download file from '$download_url'" >&2
    rm -Rf "$workdir"
    return 1
  fi

  if [ -x "$(command -v minisign)" ]; then
    curl --request GET -sL --url "${download_url}.minisig" --output "$workdir/${download_file}.minisig"
    minisign -Vm "$workdir/$download_file" -P "$DNSCRYPT_PUBLIC_KEY"
    valid_file=$?

    if [ $valid_file -ne 0 ]; then
      echo "[ERROR] Downloaded file has failed signature verification. Update aborted." >&2
      rm -Rf "$workdir"
      return 1
    fi
  else
    echo '[WARN] minisign is not installed, downloaded file signature could not be verified.'
  fi

  echo '[INFO] Initiating update of DNSCrypt-proxy'

  tar xz -C "$workdir" -f "$workdir/$download_file" ${PLATFORM}-${CPU_ARCH}/dnscrypt-proxy &&
    mv -f "${INSTALL_DIR}/dnscrypt-proxy" "${INSTALL_DIR}/dnscrypt-proxy.old" &&
    mv -f "${workdir}/${PLATFORM}-${CPU_ARCH}/dnscrypt-proxy" "${INSTALL_DIR}/" &&
    chmod u+x "${INSTALL_DIR}/dnscrypt-proxy" &&
    cd "$INSTALL_DIR" &&
    ./dnscrypt-proxy -check && ./dnscrypt-proxy -service install 2>/dev/null || : &&
    ./dnscrypt-proxy -service restart || ./dnscrypt-proxy -service start

  updated_successfully=$?

  rm -Rf "$workdir"
  if [ $updated_successfully -eq 0 ]; then
    echo '[INFO] DNSCrypt-proxy has been successfully updated!'
    return 0
  else
    echo '[ERROR] Unable to complete DNSCrypt-proxy update. Update has been aborted.' >&2
    return 1
  fi
}

if [ ! -f "${INSTALL_DIR}/dnscrypt-proxy" ]; then
  echo "[ERROR] DNSCrypt-proxy is not installed in '${INSTALL_DIR}/dnscrypt-proxy'. Update aborted..." >&2
  exit 1
fi

local_version=$("${INSTALL_DIR}/dnscrypt-proxy" -version)
remote_version=$(curl -sL "$LATEST_URL" | grep "tag_name" | head -1 | cut -d \" -f 4)

if [ -z "$local_version" ] || [ -z "$remote_version" ]; then
  echo "[ERROR] Could not retrieve DNSCrypt-proxy version. Update aborted... " >&2
  exit 1
else
  echo "[INFO] local_version=$local_version, remote_version=$remote_version"
fi

if [ "$local_version" != "$remote_version" ]; then
  echo "[INFO] local_version not synced with remote_version, initiating update..."
  Update
  exit $?
else
  echo "[INFO] No updated needed."
  exit 0
fi

(Continuation...)The version below is a more complex addition of the script that can be adapted for keeping server/relay files up-to-date. In some cases it may be more portable. In the below version it is configured for arm7l and arm8l(aarch64).

#!/bin/bash

readonly BOLD="\033[1m"
readonly NORM="\033[0m"
readonly INFO="${BOLD}[INFO]: $NORM"
readonly ERROR="${BOLD}[ERROR]: $NORM"
readonly WARNING="${BOLD}[WARNING]: $NORM"

readonly BASE_DIR="/opt"
readonly TARG_DIR="${BASE_DIR}/dnscrypt-proxy"
readonly LATEST_URL="https://api.github.com/repos/jedisct1/dnscrypt-proxy/releases/latest"
readonly RESOLVERS_URL_PREFIX="https://download.dnscrypt.info/resolvers-list/v3/"

readonly LOCAL_VERSION=$("${TARG_DIR}/dnscrypt-proxy" -version)
readonly REMOTE_VERSION=$(curl -sL "$LATEST_URL" | grep "tag_name" | head -1 | cut -d \" -f 4)

case $(uname -m) in
  armv7l)
    DNSCRYPT_ARCH=linux_arm
    DNSCRYPT_ARCH_TAR=linux-arm
    echo -e "$INFO Detected ARMv7 architecture."
    ;;
  aarch64)
    DNSCRYPT_ARCH=linux_arm64
    DNSCRYPT_ARCH_TAR=linux-arm64
    echo -e "$INFO Detected ARMv8 architecture."
    ;;
  *)
    echo "$ERROR This is unsupported platform, sorry."
    exit 1
    ;;
esac

download () {
  local TARG="$1"; shift
  local PERM=$1; shift
  local URL
  local FILENAME
  local MD5SUM_OLD
  local MD5SUM_CURR
  for URL in "$@"; do
    FILENAME="`basename $URL`"
    MD5SUM_OLD="`[ -f $TARG/$FILENAME ] && md5sum $TARG/$FILENAME | cut -d' ' -f1`"
    MD5SUM_CURR="$(curl -fsL "$URL" | md5sum | awk '{print $1}')"
    if [ `echo -n $MD5SUM_CURR | wc -c` -eq 32 ] && [ "$MD5SUM_CURR" == "$MD5SUM_OLD" ]; then
      echo -e "$INFO $FILENAME is up to date. Skipping..."
    else
      local COUNT=0
      while [ $COUNT -lt 3 ]; do
        echo -e "$INFO Downloading $FILENAME"
        curl -L -k -s "$URL" -o $TARG/$FILENAME
        if [ $? -eq 0 ]; then
          chmod $PERM $TARG/$FILENAME
          break
        fi
        COUNT=$((COUNT+1))
      done
      if [ $COUNT -eq 3 ]; then
        echo -e "$ERROR Unable to download ${BOLD}${URL}${NORM}"
      fi
    fi
  done
}

Update() {
  DNSCRYPT_TAR=dnscrypt-proxy-${DNSCRYPT_ARCH}-${REMOTE_VERSION}.tar.gz
  DOWNLOAD_URL="https://github.com/jedisct1/dnscrypt-proxy/releases/download/"${REMOTE_VERSION}"/"${DNSCRYPT_TAR}""
  echo -e "$INFO Downloading update from '$DOWNLOAD_URL'..."
  download $BASE_DIR 644 $DOWNLOAD_URL
  response=$?

  if [ $response -ne 0 ]; then
    echo -e "$ERROR Could not download file from '$DOWNLOAD_URL'" >&2
    rm -Rf "${BASE_DIR}/${DNSCRYPT_TAR}"
    return 1
  fi

  if [ -x "$(command -v minisign)" ]; then
    #curl --request GET -sL --url "${download_url}.minisig" --output "$workdir/${download_file}.minisig"
    download $BASE_DIR 644 ${DOWNLOAD_URL}.minisig
    minisign -Vm "${BASE_DIR}/${DNSCRYPT_TAR}" -P "$DNSCRYPT_PUBLIC_KEY"
    valid_file=$?

    if [ $valid_file -ne 0 ]; then
      echo -e "$ERROR Downloaded file has failed signature verification. Update aborted." >&2
      rm -Rf "${BASE_DIR}/${DNSCRYPT_TAR}"
      return 1
    fi
  else
    echo -e "$WARNING minisign is not installed, downloaded file signature could not be verified."
  fi

  echo -e "$INFO Initiating update of DNSCrypt-proxy"
  tar xzv -C "${BASE_DIR}" -f "${BASE_DIR}/${DNSCRYPT_TAR}" &&
    mv -f "${TARG_DIR}/dnscrypt-proxy" "${TARG_DIR}/dnscrypt-proxy.old" &&
    mv -f ${BASE_DIR}/${DNSCRYPT_ARCH_TAR}/* ${TARG_DIR}/ &&
    chmod u+x "${TARG_DIR}/dnscrypt-proxy" &&
    cd "$TARG_DIR" && 
    download $TARG_DIR 644 $RESOLVERS_URL_PREFIX/public-resolvers.md \
        $RESOLVERS_URL_PREFIX/public-resolvers.md.minisig \
        $RESOLVERS_URL_PREFIX/relays.md \
        $RESOLVERS_URL_PREFIX/relays.md.minisig ||
    chown root:root ${TARG_DIR}/public-resolvers.md ${TARG_DIR}/public-resolvers.md.minisig ${TARG_DIR}/relays.md ${TARG_DIR}/relays.md.minisig ||
    ./dnscrypt-proxy -check && ./dnscrypt-proxy -service install 2>/dev/null || : &&
    ./dnscrypt-proxy -service restart || ./dnscrypt-proxy -service start

  updated_successfully=$?

  rm -Rf "${BASE_DIR}/${DNSCRYPT_TAR}" "${BASE_DIR}/${DNSCRYPT_ARCH_TAR}"
  if [ $updated_successfully -eq 0 ]; then
    echo -e "$INFO DNSCrypt-proxy has been successfully updated!"
    return 0
  else
    echo -e "$ERROR Unable to complete DNSCrypt-proxy update. Update has been aborted." >&2
    return 1
  fi
}

if [ ! -f "${TARG_DIR}/dnscrypt-proxy" ]; then
  echo -e "$ERROR DNSCrypt-proxy is not installed in '${TARG_DIR}/dnscrypt-proxy'. Update aborted..." >&2
  exit 1
fi

if [ -z "$LOCAL_VERSION" ] || [ -z "$REMOTE_VERSION" ]; then
  echo -e "$ERROR Could not retrieve DNSCrypt-proxy version. Update aborted... " >&2
  exit 1
else
  echo -e "$INFO LOCAL_VERSION=$LOCAL_VERSION, REMOTE_VERSION=$REMOTE_VERSION"
fi

if [ "$LOCAL_VERSION" != "$REMOTE_VERSION" ]; then
  echo -e "$INFO LOCAL_VERSION is not synced with REMOTE_VERSION, initiating update..."
  Update
  exit $?
else
  cd "$TARG_DIR" && 
  download $TARG_DIR 644 $RESOLVERS_URL_PREFIX/public-resolvers.md \
      $RESOLVERS_URL_PREFIX/public-resolvers.md.minisig \
      $RESOLVERS_URL_PREFIX/relays.md \
      $RESOLVERS_URL_PREFIX/relays.md.minisig ||
  chown root:root ${TARG_DIR}/public-resolvers.md ${TARG_DIR}/public-resolvers.md.minisig ${TARG_DIR}/relays.md ${TARG_DIR}/relays.md.minisig ||
  ./dnscrypt-proxy -check && ./dnscrypt-proxy -service install 2>/dev/null || : &&
  ./dnscrypt-proxy -service restart || ./dnscrypt-proxy -service start
  echo -e "$INFO No updated needed."
  exit 0
fi
Clone this wiki locally