Pull request: improve installation script
Merge in DNS/adguard-home from 2542-2462-imp-script to master Closes #2462. Updates #2542. Updates #2613. Squashed commit of the following: commit 4a7472200f2ae07aeccc3511a75a94674b655cdb Author: Eugene Burkov <e.burkov@adguard.com> Date: Mon May 17 15:11:08 2021 +0300 scripts: imp naming, docs commit acbb5864a34e81d8c80767dd7ef57dffb189dc64 Author: Eugene Burkov <e.burkov@adguard.com> Date: Mon May 17 15:05:57 2021 +0300 scripts: imp fix commit 64777015b6d50e7330fbe7546de1f436f4cb707f Author: Eugene Burkov <e.burkov@adguard.com> Date: Mon May 17 14:54:05 2021 +0300 scripts: fix bsd commit 3308921f4c253c8670c4be70896c55f7a892ff3e Author: Eugene Burkov <e.burkov@adguard.com> Date: Mon May 17 14:04:04 2021 +0300 scripts: imp requirements checking commit 453cf7a4ce676d2eb09d423304e4d5a8962ac4e5 Author: Eugene Burkov <e.burkov@adguard.com> Date: Mon May 17 13:54:38 2021 +0300 scripts: fix docs commit a2229052f6cf747247c8290cd0de27cc88c14977 Merge: 0852c87b120ba967
Author: Eugene Burkov <e.burkov@adguard.com> Date: Mon May 17 13:50:45 2021 +0300 Merge branch 'master' into 2542-2462-imp-script commit 0852c87bf33b833095644e649bbcedbf89ad4f82 Author: Eugene Burkov <e.burkov@adguard.com> Date: Mon May 17 13:49:27 2021 +0300 scripts: add os-specific requirements check commit 6313d8fd19f70c41b7091511ca8d979859ddb10c Merge: 1b4092d5a031cae4
Author: Eugene Burkov <e.burkov@adguard.com> Date: Fri May 14 19:46:57 2021 +0300 Merge branch 'master' into 2542-2462-imp-script commit 1b4092d5ee1de5b56c6252bf9debe8b90cdf954e Author: Eugene Burkov <e.burkov@adguard.com> Date: Fri May 14 19:46:09 2021 +0300 scripts: imp install.sh a little commit 0584b30b4648b88f542fff6f2879c4a7ae042af4 Merge: 22621c869d788a29
Author: Eugene Burkov <e.burkov@adguard.com> Date: Fri May 14 19:27:47 2021 +0300 Merge branch 'master' into 2542-2462-imp-script commit 22621c86a70e61f98850a10f0c5e450c8aeaa90f Author: Eugene Burkov <e.burkov@adguard.com> Date: Fri May 14 19:25:47 2021 +0300 all: imp code commit a38f4adc4688995ca515f8d0d8d271427365623c Author: Eugene Burkov <e.burkov@adguard.com> Date: Fri May 14 18:40:37 2021 +0300 all: fix url variable commit 238cb859184da4af025137d99216d51d3b481dc0 Author: Eugene Burkov <e.burkov@adguard.com> Date: Fri May 14 18:27:13 2021 +0300 imp code quality commit 0e36c125369d47612fd97c2841a2a688bed5841d Author: Eugene Burkov <e.burkov@adguard.com> Date: Fri May 14 16:34:49 2021 +0300 all: fix typos commit b20f0b72141f5abb5e598324a3f2bd750164e612 Author: Eugene Burkov <e.burkov@adguard.com> Date: Thu Apr 29 14:02:40 2021 +0300 all: imp installation script
This commit is contained in:
parent
120ba96727
commit
d9ae6dbcc3
|
@ -19,16 +19,21 @@ and this project adheres to
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
- Support for reinstall (`-r`) and uninstall (`-u`) flags in the installation
|
||||||
|
script ([#2462]).
|
||||||
- Support for DHCP `DECLINE` and `RELEASE` message types ([#3053]).
|
- Support for DHCP `DECLINE` and `RELEASE` message types ([#3053]).
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
- Error when using installation script on some ARMv7 devices ([#2542]).
|
||||||
- DHCP leases validation ([#3107], [#3127]).
|
- DHCP leases validation ([#3107], [#3127]).
|
||||||
- Local PTR request recursion in Docker containers ([#3064]).
|
- Local PTR request recursion in Docker containers ([#3064]).
|
||||||
- Ignoring client-specific filtering settings when filtering is disabled in
|
- Ignoring client-specific filtering settings when filtering is disabled in
|
||||||
general settings ([#2875]).
|
general settings ([#2875]).
|
||||||
- Disallowed domains are now case-insensitive ([#3115]).
|
- Disallowed domains are now case-insensitive ([#3115]).
|
||||||
|
|
||||||
|
[#2462]: https://github.com/AdguardTeam/AdGuardHome/issues/2462
|
||||||
|
[#2542]: https://github.com/AdguardTeam/AdGuardHome/issues/2542
|
||||||
[#2875]: https://github.com/AdguardTeam/AdGuardHome/issues/2875
|
[#2875]: https://github.com/AdguardTeam/AdGuardHome/issues/2875
|
||||||
[#3053]: https://github.com/AdguardTeam/AdGuardHome/issues/3053
|
[#3053]: https://github.com/AdguardTeam/AdGuardHome/issues/3053
|
||||||
[#3064]: https://github.com/AdguardTeam/AdGuardHome/issues/3064
|
[#3064]: https://github.com/AdguardTeam/AdGuardHome/issues/3064
|
||||||
|
|
|
@ -313,6 +313,8 @@ on GitHub and most other Markdown renderers. -->
|
||||||
|
|
||||||
* Avoid bashisms and GNUisms, prefer POSIX features only.
|
* Avoid bashisms and GNUisms, prefer POSIX features only.
|
||||||
|
|
||||||
|
* Avoid spaces between patterns of the same `case` condition.
|
||||||
|
|
||||||
* Prefer `'raw strings'` to `"double quoted strings"` whenever possible.
|
* Prefer `'raw strings'` to `"double quoted strings"` whenever possible.
|
||||||
|
|
||||||
* Put spaces within `$( cmd )`, `$(( expr ))`, and `{ cmd; }`.
|
* Put spaces within `$( cmd )`, `$(( expr ))`, and `{ cmd; }`.
|
||||||
|
@ -328,10 +330,10 @@ on GitHub and most other Markdown renderers. -->
|
||||||
* UPPERCASE names for external exported variables, lowercase for local,
|
* UPPERCASE names for external exported variables, lowercase for local,
|
||||||
unexported ones.
|
unexported ones.
|
||||||
|
|
||||||
* Use `set -e -f -u` and also `set -x` in verbose mode.
|
|
||||||
|
|
||||||
* Use `readonly` liberally.
|
* Use `readonly` liberally.
|
||||||
|
|
||||||
|
* Use `set -e -f -u` and also `set -x` in verbose mode.
|
||||||
|
|
||||||
* Use the `"$var"` form instead of the `$var` form, unless word splitting is
|
* Use the `"$var"` form instead of the `$var` form, unless word splitting is
|
||||||
required.
|
required.
|
||||||
|
|
||||||
|
@ -356,6 +358,7 @@ on GitHub and most other Markdown renderers. -->
|
||||||
* When using `test` (aka `[`), spell compound conditions with `&&`, `||`, and
|
* When using `test` (aka `[`), spell compound conditions with `&&`, `||`, and
|
||||||
`!` **outside** of `test` instead of `-a`, `-o`, and `!` inside of `test`
|
`!` **outside** of `test` instead of `-a`, `-o`, and `!` inside of `test`
|
||||||
correspondingly. The latter ones are pretty much deprecated in POSIX.
|
correspondingly. The latter ones are pretty much deprecated in POSIX.
|
||||||
|
Also, prefer `!= ''` form instead of `-n` to check if string is empty.
|
||||||
|
|
||||||
See also: “[Problems With the `test` Builtin: What Does `-a` Mean?]”.
|
See also: “[Problems With the `test` Builtin: What Does `-a` Mean?]”.
|
||||||
|
|
||||||
|
|
10
README.md
10
README.md
|
@ -68,9 +68,17 @@ It operates as a DNS server that re-routes tracking domains to a "black hole", t
|
||||||
### Automated install (Linux and Mac)
|
### Automated install (Linux and Mac)
|
||||||
Run the following command in your terminal:
|
Run the following command in your terminal:
|
||||||
```
|
```
|
||||||
curl -sSL https://raw.githubusercontent.com/AdguardTeam/AdGuardHome/master/scripts/install.sh | sh
|
curl -s -S -L https://raw.githubusercontent.com/AdguardTeam/AdGuardHome/master/scripts/install.sh | sh -s -- -v
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The script also accepts some options:
|
||||||
|
* `-c <channel>` to use specified channel.
|
||||||
|
* `-r` to reinstall AdGuard Home;
|
||||||
|
* `-u` to uninstall AdGuard Home;
|
||||||
|
* `-v` for verbose output;
|
||||||
|
|
||||||
|
Note that options `-r` and `-u` are mutually exclusive.
|
||||||
|
|
||||||
### Alternative methods
|
### Alternative methods
|
||||||
|
|
||||||
#### Manual installation
|
#### Manual installation
|
||||||
|
|
|
@ -1,249 +1,507 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
# AdGuard Home Installation Script
|
# AdGuard Home Installation Script
|
||||||
#
|
|
||||||
# 1. Download the package
|
|
||||||
# 2. Unpack it
|
|
||||||
# 3. Install as a service
|
|
||||||
#
|
|
||||||
# Requirements:
|
|
||||||
# . bash
|
|
||||||
# . which
|
|
||||||
# . printf
|
|
||||||
# . uname
|
|
||||||
# . id
|
|
||||||
# . head, tail
|
|
||||||
# . curl
|
|
||||||
# . tar or unzip
|
|
||||||
# . rm
|
|
||||||
|
|
||||||
set -e
|
# Function log is an echo wrapper that writes to stderr if the caller
|
||||||
|
# requested verbosity level greater than 0. Otherwise, it does nothing.
|
||||||
log_info()
|
log() {
|
||||||
{
|
if [ "$verbose" -gt '0' ]
|
||||||
printf "[info] %s\\n" "$1"
|
then
|
||||||
}
|
echo "$1" 1>&2
|
||||||
|
|
||||||
log_error()
|
|
||||||
{
|
|
||||||
printf "[error] %s\\n" "$1"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Get OS
|
|
||||||
# Return: darwin, linux, freebsd
|
|
||||||
detect_os()
|
|
||||||
{
|
|
||||||
UNAME_S="$(uname -s)"
|
|
||||||
OS=
|
|
||||||
case "$UNAME_S" in
|
|
||||||
Linux)
|
|
||||||
OS=linux
|
|
||||||
;;
|
|
||||||
|
|
||||||
FreeBSD)
|
|
||||||
OS=freebsd
|
|
||||||
;;
|
|
||||||
|
|
||||||
Darwin)
|
|
||||||
OS=darwin
|
|
||||||
;;
|
|
||||||
|
|
||||||
*)
|
|
||||||
return 1
|
|
||||||
;;
|
|
||||||
|
|
||||||
esac
|
|
||||||
|
|
||||||
echo $OS
|
|
||||||
}
|
|
||||||
|
|
||||||
# Get CPU endianness
|
|
||||||
# Return: le, ""
|
|
||||||
cpu_little_endian()
|
|
||||||
{
|
|
||||||
ENDIAN_FLAG="$(head -c 6 /bin/bash | tail -c 1)"
|
|
||||||
if [ "$ENDIAN_FLAG" = "$(printf '\001')" ]; then
|
|
||||||
echo 'le'
|
|
||||||
return 0
|
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Get CPU
|
# Function error_exit is an echo wrapper that writes to stderr and stops the
|
||||||
# Return: amd64, 386, armv5, armv6, armv7, arm64, mips_softfloat, mipsle_softfloat, mips64_softfloat, mips64le_softfloat
|
# script execution with code 1.
|
||||||
detect_cpu()
|
error_exit() {
|
||||||
{
|
echo "$1" 1>&2
|
||||||
UNAME_M="$(uname -m)"
|
|
||||||
CPU=
|
|
||||||
|
|
||||||
case "$UNAME_M" in
|
|
||||||
|
|
||||||
x86_64 | x86-64 | x64 | amd64)
|
|
||||||
CPU=amd64
|
|
||||||
;;
|
|
||||||
|
|
||||||
i386 | i486 | i686 | i786 | x86)
|
|
||||||
CPU=386
|
|
||||||
;;
|
|
||||||
|
|
||||||
armv5l)
|
|
||||||
CPU=armv5
|
|
||||||
;;
|
|
||||||
|
|
||||||
armv6l)
|
|
||||||
CPU=armv6
|
|
||||||
;;
|
|
||||||
|
|
||||||
armv7l | armv8l)
|
|
||||||
CPU=armv7
|
|
||||||
;;
|
|
||||||
|
|
||||||
aarch64 | arm64)
|
|
||||||
CPU=arm64
|
|
||||||
;;
|
|
||||||
|
|
||||||
mips)
|
|
||||||
LE=$(cpu_little_endian)
|
|
||||||
CPU=mips${LE}_softfloat
|
|
||||||
;;
|
|
||||||
|
|
||||||
mips64)
|
|
||||||
LE=$(cpu_little_endian)
|
|
||||||
CPU=mips64${LE}_softfloat
|
|
||||||
;;
|
|
||||||
|
|
||||||
*)
|
|
||||||
return 1
|
|
||||||
|
|
||||||
esac
|
|
||||||
|
|
||||||
echo "${CPU}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Get package file name extension
|
|
||||||
# Return: tar.gz, zip
|
|
||||||
package_extension()
|
|
||||||
{
|
|
||||||
if [ "$OS" = "darwin" ]; then
|
|
||||||
echo "zip"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
echo "tar.gz"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Download data to a file
|
|
||||||
# Use: download URL OUTPUT
|
|
||||||
download()
|
|
||||||
{
|
|
||||||
log_info "Downloading package from $1 -> $2"
|
|
||||||
if is_command curl ; then
|
|
||||||
curl -s "$1" --output "$2" || error_exit "Failed to download $1"
|
|
||||||
else
|
|
||||||
error_exit "curl is necessary to install AdGuard Home"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Unpack package to a directory
|
|
||||||
# Use: unpack INPUT OUTPUT_DIR PKG_EXT
|
|
||||||
unpack()
|
|
||||||
{
|
|
||||||
log_info "Unpacking package from $1 -> $2"
|
|
||||||
mkdir -p "$2"
|
|
||||||
if [ "$3" = "zip" ]; then
|
|
||||||
unzip -qq "$1" -d "$2" || return 1
|
|
||||||
elif [ "$3" = "tar.gz" ]; then
|
|
||||||
tar xzf "$1" -C "$2" || return 1
|
|
||||||
else
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Print error message and exit
|
|
||||||
# Use: error_exit MESSAGE
|
|
||||||
error_exit()
|
|
||||||
{
|
|
||||||
log_error "$1"
|
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check if command exists
|
# Function usage prints the note about how to use the script.
|
||||||
# Use: is_command COMMAND
|
#
|
||||||
|
# TODO(e.burkov): Document each option.
|
||||||
|
usage() {
|
||||||
|
echo 'install.sh: usage: [-c channel] [-C cpu_type] [-h] [-O os] [-o output_dir]'\
|
||||||
|
'[-r|-R] [-u|-U] [-v|-V]' 1>&2
|
||||||
|
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function is_command checks if the command exists on the machine.
|
||||||
is_command() {
|
is_command() {
|
||||||
check_command="$1"
|
command -v "$1" >/dev/null 2>&1
|
||||||
command -v "${check_command}" >/dev/null 2>&1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Entry point
|
# Function is_little_endian checks if the CPU is little-endian.
|
||||||
main() {
|
is_little_endian() {
|
||||||
log_info "Starting AdGuard Home installation script"
|
[ "$( head -c 6 /bin/sh | tail -c 1 )" = "$( printf '\001' )" ]
|
||||||
|
|
||||||
CHANNEL=${1}
|
|
||||||
if [ "${CHANNEL}" != "beta" ] && [ "${CHANNEL}" != "edge" ]; then
|
|
||||||
CHANNEL=release
|
|
||||||
fi
|
|
||||||
log_info "Channel ${CHANNEL}"
|
|
||||||
|
|
||||||
OS=$(detect_os) || error_exit "Cannot detect your OS"
|
|
||||||
CPU=$(detect_cpu) || error_exit "Cannot detect your CPU"
|
|
||||||
|
|
||||||
# TODO: Remove when Mac M1 native support is added
|
|
||||||
if [ "${OS}" = "darwin" ] && [ "${CPU}" = "arm64" ]; then
|
|
||||||
CPU="amd64"
|
|
||||||
log_info "Use ${CPU} build on Mac M1 until the native ARM support is added"
|
|
||||||
fi
|
|
||||||
|
|
||||||
PKG_EXT=$(package_extension)
|
|
||||||
PKG_NAME=AdGuardHome_${OS}_${CPU}.${PKG_EXT}
|
|
||||||
|
|
||||||
SCRIPT_URL="https://raw.githubusercontent.com/AdguardTeam/AdGuardHome/master/scripts/install.sh"
|
|
||||||
URL="https://static.adguard.com/adguardhome/${CHANNEL}/${PKG_NAME}"
|
|
||||||
OUT_DIR="/opt"
|
|
||||||
if [ "${OS}" = "darwin" ]; then
|
|
||||||
# It may be important to install AdGuard Home to /Applications on MacOS
|
|
||||||
# Otherwise, it may not grant enough privileges to it
|
|
||||||
OUT_DIR="/Applications"
|
|
||||||
fi
|
|
||||||
|
|
||||||
AGH_DIR="${OUT_DIR}/AdGuardHome"
|
|
||||||
|
|
||||||
# Root check
|
|
||||||
if [ "$(id -u)" -eq 0 ]; then
|
|
||||||
log_info "Script called with root privileges"
|
|
||||||
else
|
|
||||||
if is_command sudo ; then
|
|
||||||
log_info "Please note, that AdGuard Home requires root privileges to install using this script."
|
|
||||||
log_info "Restarting with root privileges"
|
|
||||||
|
|
||||||
exec curl -sSL ${SCRIPT_URL} | sudo sh -s "$@"
|
|
||||||
exit $?
|
|
||||||
else
|
|
||||||
log_info "Root privileges are required to install AdGuard Home using this installer."
|
|
||||||
log_info "Please, re-run this script as root."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
log_info "AdGuard Home will be installed to ${AGH_DIR}"
|
|
||||||
|
|
||||||
[ -d "${AGH_DIR}" ] && [ -n "$(ls -1 -A -q ${AGH_DIR})" ] && error_exit "Directory ${AGH_DIR} is not empty, abort installation"
|
|
||||||
|
|
||||||
download "${URL}" "${PKG_NAME}" || error_exit "Cannot download the package"
|
|
||||||
|
|
||||||
if [ "${OS}" = "darwin" ]; then
|
|
||||||
# TODO: remove this after v0.106.0 release
|
|
||||||
mkdir "${AGH_DIR}"
|
|
||||||
unpack "${PKG_NAME}" "${AGH_DIR}" "${PKG_EXT}" || error_exit "Cannot unpack the package"
|
|
||||||
else
|
|
||||||
unpack "${PKG_NAME}" "${OUT_DIR}" "${PKG_EXT}" || error_exit "Cannot unpack the package"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Install AdGuard Home service and run it.
|
|
||||||
( cd "${AGH_DIR}" && ./AdGuardHome -s install || error_exit "Cannot install AdGuardHome as a service" )
|
|
||||||
|
|
||||||
rm "${PKG_NAME}"
|
|
||||||
|
|
||||||
log_info "AdGuard Home is now installed and running."
|
|
||||||
log_info "You can control the service status with the following commands:"
|
|
||||||
log_info " sudo ${AGH_DIR}/AdGuardHome -s start|stop|restart|status|install|uninstall"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
main "$@"
|
# Function check_required checks if the required software is available on the
|
||||||
|
# machine. The required software:
|
||||||
|
#
|
||||||
|
# curl
|
||||||
|
# unzip (macOS) / tar (other unices)
|
||||||
|
#
|
||||||
|
check_required() {
|
||||||
|
readonly required_darwin="unzip"
|
||||||
|
readonly required_unix="tar"
|
||||||
|
|
||||||
|
# Split with space.
|
||||||
|
required="curl"
|
||||||
|
if [ "$os" = 'linux' ] || [ "$os" = 'freebsd' ]
|
||||||
|
then
|
||||||
|
required="$required $required_unix"
|
||||||
|
elif [ "$os" = 'darwin' ]
|
||||||
|
then
|
||||||
|
required="$required $required_darwin"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Don't use quotes to get word splitting.
|
||||||
|
for cmd in ${required}
|
||||||
|
do
|
||||||
|
echo "checking $cmd"
|
||||||
|
if ! is_command "$cmd"
|
||||||
|
then
|
||||||
|
log "the full list of required software: [$required]"
|
||||||
|
|
||||||
|
error_exit "$cmd is required to install AdGuard Home via this script"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function check_out_dir requires the output directory to be set and exist.
|
||||||
|
check_out_dir() {
|
||||||
|
if [ "$out_dir" = '' ]
|
||||||
|
then
|
||||||
|
error_exit 'output directory should be presented'
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! [ -d "$out_dir" ]
|
||||||
|
then
|
||||||
|
log "$out_dir directory will be created"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function parse_opts parses the options list and validates it's combinations.
|
||||||
|
parse_opts() {
|
||||||
|
while getopts "C:c:hO:o:rRuUvV" opt $*
|
||||||
|
do
|
||||||
|
case "$opt"
|
||||||
|
in
|
||||||
|
(C)
|
||||||
|
cpu="$OPTARG"
|
||||||
|
;;
|
||||||
|
(c)
|
||||||
|
channel="$OPTARG"
|
||||||
|
;;
|
||||||
|
(h)
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
(O)
|
||||||
|
os="$OPTARG"
|
||||||
|
;;
|
||||||
|
(o)
|
||||||
|
out_dir="$OPTARG"
|
||||||
|
;;
|
||||||
|
(R)
|
||||||
|
reinstall='0'
|
||||||
|
;;
|
||||||
|
(U)
|
||||||
|
uninstall='0'
|
||||||
|
;;
|
||||||
|
(r)
|
||||||
|
reinstall='1'
|
||||||
|
;;
|
||||||
|
(u)
|
||||||
|
uninstall='1'
|
||||||
|
;;
|
||||||
|
(V)
|
||||||
|
verbose='0'
|
||||||
|
;;
|
||||||
|
(v)
|
||||||
|
verbose='1'
|
||||||
|
;;
|
||||||
|
(*)
|
||||||
|
log "bad option $OPTARG"
|
||||||
|
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "$uninstall" = '1' ] && [ "$reinstall" = '1' ]
|
||||||
|
then
|
||||||
|
error_exit 'the -r and -u options are mutually exclusive'
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function set_channel sets the channel if needed and validates the value.
|
||||||
|
set_channel() {
|
||||||
|
# Validate.
|
||||||
|
case "$channel"
|
||||||
|
in
|
||||||
|
('development'|'edge'|'beta'|'release')
|
||||||
|
# All is well, go on.
|
||||||
|
;;
|
||||||
|
(*)
|
||||||
|
error_exit \
|
||||||
|
"invalid channel '$channel'
|
||||||
|
supported values are 'development', 'edge', 'beta', and 'release'"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Log.
|
||||||
|
log "channel: $channel"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function set_os sets the os if needed and validates the value.
|
||||||
|
set_os() {
|
||||||
|
# Set if needed.
|
||||||
|
if [ "$os" = '' ]
|
||||||
|
then
|
||||||
|
os="$( uname -s )"
|
||||||
|
case "$os"
|
||||||
|
in
|
||||||
|
('Linux')
|
||||||
|
os='linux'
|
||||||
|
;;
|
||||||
|
('FreeBSD')
|
||||||
|
os='freebsd'
|
||||||
|
;;
|
||||||
|
('Darwin')
|
||||||
|
os='darwin'
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Validate.
|
||||||
|
case "$os"
|
||||||
|
in
|
||||||
|
('linux'|'freebsd'|'darwin')
|
||||||
|
# All right, go on.
|
||||||
|
;;
|
||||||
|
(*)
|
||||||
|
error_exit "unsupported operating system: $os"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Log.
|
||||||
|
log "operating system: $os"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function set_cpu sets the cpu if needed and validates the value.
|
||||||
|
set_cpu() {
|
||||||
|
# Set if needed.
|
||||||
|
if [ "$cpu" = '' ]
|
||||||
|
then
|
||||||
|
cpu="$( uname -m )"
|
||||||
|
case "$cpu"
|
||||||
|
in
|
||||||
|
('x86_64'|'x86-64'|'x64'|'amd64')
|
||||||
|
cpu='amd64'
|
||||||
|
;;
|
||||||
|
('i386'|'i486'|'i686'|'i786'|'x86')
|
||||||
|
cpu='386'
|
||||||
|
;;
|
||||||
|
('armv5l')
|
||||||
|
cpu='armv5'
|
||||||
|
;;
|
||||||
|
('armv6l')
|
||||||
|
cpu='armv6'
|
||||||
|
;;
|
||||||
|
('armv7l' | 'armv8l')
|
||||||
|
cpu='armv7'
|
||||||
|
;;
|
||||||
|
('aarch64'|'arm64')
|
||||||
|
cpu='arm64'
|
||||||
|
;;
|
||||||
|
('mips'|'mips64')
|
||||||
|
if is_little_endian
|
||||||
|
then
|
||||||
|
cpu="${cpu}le"
|
||||||
|
fi
|
||||||
|
cpu="${cpu}_softfloat"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Validate.
|
||||||
|
case "$cpu"
|
||||||
|
in
|
||||||
|
('amd64'|'386'|'armv5'|'armv6'|'armv7'|'arm64')
|
||||||
|
# All right, go on.
|
||||||
|
;;
|
||||||
|
('mips64le_softfloat'|'mips64_softfloat'|'mipsle_softfloat'|'mips_softfloat')
|
||||||
|
# That's right too.
|
||||||
|
;;
|
||||||
|
(*)
|
||||||
|
error_exit "unsupported cpu type: $cpu"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Log.
|
||||||
|
log "cpu type: $cpu"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function fix_darwin performs some configuration changes for macOS if
|
||||||
|
# needed.
|
||||||
|
fix_darwin() {
|
||||||
|
if ! [ "$os" = 'darwin' ]
|
||||||
|
then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# TODO: Remove when Mac M1 native support is added.
|
||||||
|
if [ "$cpu" = 'arm64' ]
|
||||||
|
then
|
||||||
|
cpu='amd64'
|
||||||
|
log "use $cpu build on Mac M1 until the native ARM support is added."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Set the package extension.
|
||||||
|
pkg_ext='zip'
|
||||||
|
|
||||||
|
# It is important to install AdGuard Home into the /Applications
|
||||||
|
# directory on MacOS. Otherwise, it may not grant enough privileges to
|
||||||
|
# the AdGuard Home.
|
||||||
|
out_dir='/Applications'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function fix_freebsd performs some fixes to make it work on FreeBSD.
|
||||||
|
fix_freebsd() {
|
||||||
|
if ! [ "$os" = 'freebsd' ]
|
||||||
|
then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
readonly rcd='/usr/local/etc/rc.d'
|
||||||
|
if ! [ -d "$rcd" ]
|
||||||
|
then
|
||||||
|
mkdir "$rcd"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function configure sets the script's configuration.
|
||||||
|
configure() {
|
||||||
|
set_channel
|
||||||
|
set_os
|
||||||
|
set_cpu
|
||||||
|
fix_darwin
|
||||||
|
check_out_dir
|
||||||
|
|
||||||
|
readonly pkg_name="AdGuardHome_${os}_${cpu}.${pkg_ext}"
|
||||||
|
readonly url="https://static.adguard.com/adguardhome/${channel}/${pkg_name}"
|
||||||
|
readonly agh_dir="${out_dir}/AdGuardHome"
|
||||||
|
|
||||||
|
log "AdGuard Home will be installed into $agh_dir"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function is_root checks for root privileges to be granted.
|
||||||
|
is_root() {
|
||||||
|
if [ "$( id -u )" = '0' ]
|
||||||
|
then
|
||||||
|
log 'script is executed with root privileges'
|
||||||
|
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if is_command sudo
|
||||||
|
then
|
||||||
|
log 'note that AdGuard Home requires root privileges to install using this script'
|
||||||
|
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
error_exit \
|
||||||
|
'root privileges are required to install AdGuard Home using this script
|
||||||
|
please, restart it with root privileges'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function rerun_with_root downloads the script and tries to run it with root
|
||||||
|
# privileges. It also uses the configuration that already set.
|
||||||
|
#
|
||||||
|
# TODO(e.burkov): Try to avoid restarting.
|
||||||
|
rerun_with_root() {
|
||||||
|
readonly script_url=\
|
||||||
|
'https://raw.githubusercontent.com/AdguardTeam/AdGuardHome/master/scripts/install.sh'
|
||||||
|
|
||||||
|
flags=''
|
||||||
|
if [ "$reinstall" = '1' ]
|
||||||
|
then
|
||||||
|
flags="${flags} -r"
|
||||||
|
fi
|
||||||
|
if [ "$uninstall" = '1' ]
|
||||||
|
then
|
||||||
|
flags="${flags} -u"
|
||||||
|
fi
|
||||||
|
if [ "$verbose" = '1' ]
|
||||||
|
then
|
||||||
|
flags="${flags} -v"
|
||||||
|
fi
|
||||||
|
|
||||||
|
readonly opts="-c $channel -C $cpu -O $os -o $out_dir $flags"
|
||||||
|
|
||||||
|
log 'restarting with root privileges'
|
||||||
|
|
||||||
|
curl -L -S -s "$script_url" | sudo sh -s -- $opts
|
||||||
|
exit $?
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function download downloads the file from the URL and saves it to the
|
||||||
|
# specified filepath.
|
||||||
|
download() {
|
||||||
|
log "downloading package from $url -> $pkg_name"
|
||||||
|
|
||||||
|
if ! curl -s "$url" --output "$pkg_name"
|
||||||
|
then
|
||||||
|
error_exit "cannot download the package from $url into $pkg_name"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function unpack unpacks the passed archive depending on it's extension.
|
||||||
|
unpack() {
|
||||||
|
log "unpacking package from $pkg_name into $out_dir"
|
||||||
|
if ! mkdir -p "$out_dir"
|
||||||
|
then
|
||||||
|
error_exit "cannot create directory at the $out_dir"
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$pkg_ext"
|
||||||
|
in
|
||||||
|
('zip')
|
||||||
|
unzip "$pkg_name" -d "$out_dir"
|
||||||
|
;;
|
||||||
|
('tar.gz')
|
||||||
|
tar -C "$out_dir" -f "$pkg_name" -x -z
|
||||||
|
;;
|
||||||
|
(*)
|
||||||
|
error_exit "unexpected package extension: '$pkg_ext'"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ "$?" != '0' ]
|
||||||
|
then
|
||||||
|
error_exit "cannot unpack the package into $out_dir"
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm "$pkg_name"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function handle_existing detects the existing AGH installation and takes care
|
||||||
|
# of removing it if needed.
|
||||||
|
handle_existing() {
|
||||||
|
if ! [ -d "$agh_dir" ]
|
||||||
|
then
|
||||||
|
log 'no need to uninstall'
|
||||||
|
|
||||||
|
if [ "$uninstall" = '1' ]
|
||||||
|
then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$( ls -1 -A -q $agh_dir )" != '' ]
|
||||||
|
then
|
||||||
|
log 'the existing AdGuard Home installation is detected'
|
||||||
|
|
||||||
|
if [ "$reinstall" != '1' ] && [ "$uninstall" != '1' ]
|
||||||
|
then
|
||||||
|
error_exit \
|
||||||
|
"to reinstall/uninstall the AdGuard Home using\this script specify one of the '-r' or '-u' flags"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ( cd "$agh_dir" && ! ./AdGuardHome -s uninstall )
|
||||||
|
then
|
||||||
|
# It doesn't terminate the script since it is possible
|
||||||
|
# that AGH just not installed as service but appearing
|
||||||
|
# in the directory.
|
||||||
|
log "cannot uninstall AdGuard Home from $agh_dir"
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -r "$agh_dir"
|
||||||
|
|
||||||
|
log 'AdGuard Home was successfully uninstalled'
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$uninstall" = '1' ]
|
||||||
|
then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function install_service tries to install AGH as service.
|
||||||
|
install_service() {
|
||||||
|
# TODO(e.burkov): Think about AGH's output suppressing with no verbose
|
||||||
|
# flag.
|
||||||
|
if ( cd "$agh_dir" && ./AdGuardHome -s install )
|
||||||
|
then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -r "$agh_dir"
|
||||||
|
|
||||||
|
# Some devices detected to have armv7 CPU face the compatibility
|
||||||
|
# issues with actual armv7 builds. We should try to install the
|
||||||
|
# armv5 binary instead.
|
||||||
|
#
|
||||||
|
# See https://github.com/AdguardTeam/AdGuardHome/issues/2542.
|
||||||
|
if [ "$cpu" = 'armv7' ]
|
||||||
|
then
|
||||||
|
cpu='armv5'
|
||||||
|
reinstall='1'
|
||||||
|
|
||||||
|
log "trying to use $cpu cpu"
|
||||||
|
|
||||||
|
rerun_with_root
|
||||||
|
fi
|
||||||
|
|
||||||
|
error_exit 'cannot install AdGuardHome as a service'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Entrypoint
|
||||||
|
|
||||||
|
# Exit the script if a pipeline fails (-e), prevent accidental filename
|
||||||
|
# expansion (-f), and consider undefined variables as errors (-u).
|
||||||
|
set -e -f -u
|
||||||
|
|
||||||
|
# Set default values of configuration variables.
|
||||||
|
channel='release'
|
||||||
|
reinstall='0'
|
||||||
|
uninstall='0'
|
||||||
|
verbose='0'
|
||||||
|
cpu=''
|
||||||
|
os=''
|
||||||
|
out_dir='/opt'
|
||||||
|
pkg_ext='tar.gz'
|
||||||
|
parse_opts $*
|
||||||
|
|
||||||
|
echo 'starting AdGuard Home installation script'
|
||||||
|
|
||||||
|
configure
|
||||||
|
check_required
|
||||||
|
|
||||||
|
if ! is_root
|
||||||
|
then
|
||||||
|
rerun_with_root
|
||||||
|
fi
|
||||||
|
# Needs rights.
|
||||||
|
fix_freebsd
|
||||||
|
|
||||||
|
handle_existing
|
||||||
|
|
||||||
|
download
|
||||||
|
unpack
|
||||||
|
|
||||||
|
install_service
|
||||||
|
|
||||||
|
echo "\
|
||||||
|
AdGuard Home is now installed and running
|
||||||
|
you can control the service status with the following commands:
|
||||||
|
sudo ${agh_dir}/AdGuardHome -s start|stop|restart|status|install|uninstall"
|
||||||
|
|
Loading…
Reference in New Issue