2018-04-24 03:37:15 +00:00
|
|
|
#!/usr/bin/env bash
|
2020-05-19 05:01:13 +00:00
|
|
|
# shellcheck disable=SC2145,SC2178,SC2120,SC2162
|
|
|
|
|
|
|
|
# Functions to manage .env files
|
|
|
|
__dotenv=
|
|
|
|
__dotenv_file=
|
|
|
|
__dotenv_cmd=.env
|
|
|
|
|
|
|
|
.env() {
|
|
|
|
REPLY=()
|
|
|
|
[[ $__dotenv_file || ${1-} == -* ]] || .env.--file .env || return
|
|
|
|
if declare -F -- ".env.${1-}" >/dev/null; then
|
|
|
|
.env."$@"
|
|
|
|
return
|
|
|
|
fi
|
|
|
|
.env --help >&2
|
|
|
|
return 64
|
|
|
|
}
|
|
|
|
|
|
|
|
.env.-f() { .env.--file "$@"; }
|
|
|
|
|
|
|
|
.env.get() {
|
|
|
|
.env::arg "get requires a key" "$@" &&
|
|
|
|
[[ "$__dotenv" =~ ^(.*(^|$'\n'))([ ]*)"$1="(.*)$ ]] &&
|
|
|
|
REPLY=${BASH_REMATCH[4]%%$'\n'*} && REPLY=${REPLY%"${REPLY##*[![:space:]]}"}
|
|
|
|
}
|
|
|
|
|
|
|
|
.env.parse() {
|
|
|
|
local line key
|
|
|
|
while IFS= read -r line; do
|
|
|
|
line=${line#"${line%%[![:space:]]*}"} # trim leading whitespace
|
|
|
|
line=${line%"${line##*[![:space:]]}"} # trim trailing whitespace
|
|
|
|
if [[ ! "$line" || "$line" == '#'* ]]; then continue; fi
|
|
|
|
if (($#)); then
|
|
|
|
for key; do
|
|
|
|
if [[ $key == "${line%%=*}" ]]; then
|
|
|
|
REPLY+=("$line")
|
|
|
|
break
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
else
|
|
|
|
REPLY+=("$line")
|
|
|
|
fi
|
|
|
|
done <<<"$__dotenv"
|
|
|
|
((${#REPLY[@]}))
|
|
|
|
}
|
|
|
|
|
|
|
|
.env.export() { ! .env.parse "$@" || export "${REPLY[@]}"; }
|
|
|
|
|
|
|
|
.env.set() {
|
|
|
|
.env::file load || return
|
|
|
|
local key saved=$__dotenv
|
|
|
|
while (($#)); do
|
|
|
|
key=${1#+}
|
|
|
|
key=${key%%=*}
|
|
|
|
if .env.get "$key"; then
|
|
|
|
REPLY=()
|
|
|
|
if [[ $1 == +* ]]; then
|
|
|
|
shift
|
|
|
|
continue # skip if already found
|
|
|
|
elif [[ $1 == *=* ]]; then
|
|
|
|
__dotenv=${BASH_REMATCH[1]}${BASH_REMATCH[3]}$1$'\n'${BASH_REMATCH[4]#*$'\n'}
|
|
|
|
else
|
|
|
|
__dotenv=${BASH_REMATCH[1]}${BASH_REMATCH[4]#*$'\n'}
|
|
|
|
continue # delete all occurrences
|
|
|
|
fi
|
|
|
|
elif [[ $1 == *=* ]]; then
|
|
|
|
__dotenv+="${1#+}"$'\n'
|
|
|
|
fi
|
|
|
|
shift
|
|
|
|
done
|
|
|
|
[[ $__dotenv == "$saved" ]] || .env::file save
|
|
|
|
}
|
|
|
|
|
|
|
|
.env.puts() { echo "${1-}" >>"$__dotenv_file" && __dotenv+="$1"$'\n'; }
|
|
|
|
|
|
|
|
.env.generate() {
|
|
|
|
.env::arg "key required for generate" "$@" || return
|
|
|
|
.env.get "$1" && return || REPLY=$("${@:2}") || return
|
|
|
|
.env::one "generate: ouptut of '${*:2}' has more than one line" "$REPLY" || return
|
|
|
|
.env.puts "$1=$REPLY"
|
|
|
|
}
|
|
|
|
|
|
|
|
.env.--file() {
|
|
|
|
.env::arg "filename required for --file" "$@" || return
|
|
|
|
__dotenv_file=$1
|
|
|
|
.env::file load || return
|
|
|
|
(($# < 2)) || .env "${@:2}"
|
|
|
|
}
|
|
|
|
|
|
|
|
.env::arg() { [[ "${2-}" ]] || {
|
|
|
|
echo "$__dotenv_cmd: $1" >&2
|
|
|
|
return 64
|
|
|
|
}; }
|
|
|
|
|
|
|
|
.env::one() { [[ "$2" != *$'\n'* ]] || .env::arg "$1"; }
|
|
|
|
|
|
|
|
.env::file() {
|
|
|
|
local REPLY=$__dotenv_file
|
|
|
|
case "$1" in
|
|
|
|
load)
|
|
|
|
__dotenv=
|
|
|
|
! [[ -f "$REPLY" ]] || __dotenv="$(<"$REPLY")"$'\n' || return
|
|
|
|
;;
|
|
|
|
save)
|
|
|
|
if [[ -L "$REPLY" ]] && declare -F -- realpath.resolved >/dev/null; then
|
|
|
|
realpath.resolved "$REPLY"
|
|
|
|
fi
|
|
|
|
{ [[ ! -f "$REPLY" ]] || cp -p "$REPLY" "$REPLY.bak"; } &&
|
|
|
|
printf %s "$__dotenv" >"$REPLY.bak" && mv "$REPLY.bak" "$REPLY"
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
}
|
|
|
|
.env.-h() { .env.--help "$@"; }
|
|
|
|
.env.--help() {
|
|
|
|
echo "Usage:
|
|
|
|
$__dotenv_cmd [-f|--file FILE] COMMAND [ARGS...]
|
|
|
|
$__dotenv_cmd -h|--help
|
|
|
|
|
|
|
|
Options:
|
|
|
|
-f, --file FILE Use a file other than .env
|
|
|
|
|
|
|
|
Read Commands:
|
|
|
|
get KEY Get raw value of KEY (or fail)
|
|
|
|
parse [KEY...] Get trimmed KEY=VALUE lines for named keys (or all)
|
|
|
|
export [KEY...] Export the named keys (or all) in shell format
|
|
|
|
|
|
|
|
Write Commands:
|
|
|
|
set [+]KEY[=VALUE]... Set or unset values (in-place w/.bak); + sets default
|
|
|
|
puts STRING Append STRING to the end of the file
|
|
|
|
generate KEY [CMD...] Set KEY to the output of CMD unless it already exists;
|
|
|
|
return the new or existing value."
|
|
|
|
}
|
|
|
|
|
|
|
|
__dotenv() {
|
|
|
|
set -eu
|
|
|
|
__dotenv_cmd=${0##*/}
|
|
|
|
.env.export() {
|
|
|
|
.env.parse "$@" || return 0
|
|
|
|
printf 'export %q\n' "${REPLY[@]}"
|
|
|
|
REPLY=()
|
|
|
|
}
|
|
|
|
.env "$@" || return $?
|
|
|
|
${REPLY[@]+printf '%s\n' "${REPLY[@]}"}
|
|
|
|
}
|
2018-04-24 03:37:15 +00:00
|
|
|
|
|
|
|
# This is a general-purpose function to ask Yes/No questions in Bash, either
|
|
|
|
# with or without a default answer. It keeps repeating the question until it
|
|
|
|
# gets a valid answer.
|
|
|
|
ask() {
|
|
|
|
# https://djm.me/ask
|
|
|
|
local prompt default reply
|
|
|
|
|
|
|
|
while true; do
|
|
|
|
|
2020-04-02 21:07:10 +00:00
|
|
|
if [[ "${2:-}" == "Y" ]]; then
|
2018-04-24 03:37:15 +00:00
|
|
|
prompt="Y/n"
|
|
|
|
default=Y
|
2020-04-02 21:07:10 +00:00
|
|
|
elif [[ "${2:-}" == "N" ]]; then
|
2018-04-24 03:37:15 +00:00
|
|
|
prompt="y/N"
|
|
|
|
default=N
|
|
|
|
else
|
|
|
|
prompt="y/n"
|
|
|
|
default=
|
|
|
|
fi
|
|
|
|
|
|
|
|
# Ask the question (not using "read -p" as it uses stderr not stdout)
|
|
|
|
echo -n "$1 [$prompt] "
|
|
|
|
|
2018-11-02 07:22:03 +00:00
|
|
|
read reply
|
2018-04-24 03:37:15 +00:00
|
|
|
|
|
|
|
# Default?
|
2018-11-19 16:26:22 +00:00
|
|
|
if [[ -z "$reply" ]]; then
|
|
|
|
reply=${default}
|
2018-04-24 03:37:15 +00:00
|
|
|
fi
|
|
|
|
|
|
|
|
# Check if the reply is valid
|
|
|
|
case "$reply" in
|
2020-04-02 21:07:10 +00:00
|
|
|
Y* | y*) return 0 ;;
|
|
|
|
N* | n*) return 1 ;;
|
2018-04-24 03:37:15 +00:00
|
|
|
esac
|
|
|
|
|
|
|
|
done
|
|
|
|
}
|
|
|
|
|
2020-05-19 05:01:13 +00:00
|
|
|
#
|
|
|
|
# Configure the ports used by AzuraCast.
|
|
|
|
# Usage: ./docker.sh setup_ports
|
|
|
|
#
|
|
|
|
setup_ports() {
|
|
|
|
AZURACAST_HTTP_PORT=80
|
|
|
|
read -p "Port to use for HTTP connections? [80]:" INPUT
|
|
|
|
AZURACAST_HTTP_PORT="${INPUT:-$AZURACAST_HTTP_PORT}"
|
|
|
|
|
|
|
|
AZURACAST_HTTPS_PORT=443
|
|
|
|
read -p "Port to use for HTTPS connections? [443]:" INPUT
|
|
|
|
AZURACAST_HTTPS_PORT="${INPUT:-$AZURACAST_HTTPS_PORT}"
|
|
|
|
|
|
|
|
AZURACAST_SFTP_PORT=2022
|
|
|
|
read -p "Port to use for SFTP connections? [2022]:" INPUT
|
|
|
|
AZURACAST_SFTP_PORT="${INPUT:-$AZURACAST_SFTP_PORT}"
|
|
|
|
|
|
|
|
.env --file .env put AZURACAST_HTTP_PORT="${AZURACAST_HTTP_PORT}" \
|
|
|
|
AZURACAST_HTTPS_PORT="${AZURACAST_HTTPS_PORT}" \
|
|
|
|
AZURACAST_SFTP_PORT="${AZURACAST_SFTP_PORT}"
|
|
|
|
}
|
|
|
|
|
|
|
|
#
|
|
|
|
# Configure the settings used by LetsEncrypt.
|
|
|
|
#
|
|
|
|
setup_letsencrypt() {
|
|
|
|
read -p "Domain name (example.com) or names (example.com,foo.bar) to use with LetsEncrypt:" INPUT
|
|
|
|
LETSENCRYPT_HOST="${INPUT:-""}"
|
|
|
|
|
|
|
|
read -p "Optional e-mail address for expiration updates:" INPUT
|
|
|
|
LETSENCRYPT_EMAIL="${INPUT:-""}"
|
|
|
|
|
|
|
|
.env --file .env put LETSENCRYPT_HOST="${LETSENCRYPT_HOST}" \
|
|
|
|
LETSENCRYPT_EMAIL="${LETSENCRYPT_EMAIL}"
|
|
|
|
}
|
|
|
|
|
2018-04-24 03:37:15 +00:00
|
|
|
#
|
2018-04-27 00:21:33 +00:00
|
|
|
# Run the initial installer of Docker and AzuraCast.
|
2018-04-24 03:37:15 +00:00
|
|
|
# Usage: ./docker.sh install
|
|
|
|
#
|
|
|
|
install() {
|
2020-01-26 00:11:31 +00:00
|
|
|
if [[ ! $(command -v curl) ]]; then
|
2019-07-14 16:18:15 +00:00
|
|
|
echo "cURL does not appear to be installed."
|
|
|
|
echo "Install curl using your host's package manager,"
|
|
|
|
echo "then continue installing using this script."
|
|
|
|
exit 1
|
|
|
|
fi
|
2020-01-12 19:02:43 +00:00
|
|
|
|
2020-01-26 00:11:31 +00:00
|
|
|
if [[ $(command -v docker) && $(docker --version) ]]; then
|
2018-04-24 03:37:15 +00:00
|
|
|
echo "Docker is already installed! Continuing..."
|
|
|
|
else
|
|
|
|
if ask "Docker does not appear to be installed. Install Docker now?" Y; then
|
|
|
|
curl -fsSL get.docker.com -o get-docker.sh
|
|
|
|
sh get-docker.sh
|
|
|
|
rm get-docker.sh
|
|
|
|
|
|
|
|
if [[ $EUID -ne 0 ]]; then
|
2020-04-02 21:07:10 +00:00
|
|
|
sudo usermod -aG docker "$(whoami)"
|
2018-04-24 03:37:15 +00:00
|
|
|
|
|
|
|
echo "You must log out or restart to apply necessary Docker permissions changes."
|
|
|
|
echo "Restart, then continue installing using this script."
|
|
|
|
exit
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
|
2020-01-26 00:11:31 +00:00
|
|
|
if [[ $(command -v docker-compose) && $(docker-compose --version) ]]; then
|
2018-04-24 03:37:15 +00:00
|
|
|
echo "Docker Compose is already installed! Continuing..."
|
|
|
|
else
|
|
|
|
if ask "Docker Compose does not appear to be installed. Install Docker Compose now?" Y; then
|
2020-01-26 00:11:31 +00:00
|
|
|
COMPOSE_VERSION=1.25.3
|
2019-06-26 02:35:39 +00:00
|
|
|
|
|
|
|
if [[ $EUID -ne 0 ]]; then
|
2020-01-26 00:11:31 +00:00
|
|
|
if [[ ! $(command -v sudo) ]]; then
|
2019-06-26 02:35:39 +00:00
|
|
|
echo "Sudo does not appear to be installed."
|
|
|
|
echo "Install sudo using your host's package manager,"
|
|
|
|
echo "then continue installing using this script."
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
2020-04-02 21:07:10 +00:00
|
|
|
sudo sh -c "curl -fsSL https://github.com/docker/compose/releases/download/${COMPOSE_VERSION}/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose"
|
2019-06-26 02:35:39 +00:00
|
|
|
sudo chmod +x /usr/local/bin/docker-compose
|
2019-07-14 16:18:15 +00:00
|
|
|
sudo sh -c "curl -fsSL https://raw.githubusercontent.com/docker/compose/${COMPOSE_VERSION}/contrib/completion/bash/docker-compose -o /etc/bash_completion.d/docker-compose"
|
2019-06-26 02:35:39 +00:00
|
|
|
else
|
2020-04-02 21:07:10 +00:00
|
|
|
curl -fsSL https://github.com/docker/compose/releases/download/${COMPOSE_VERSION}/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
|
2019-06-26 02:35:39 +00:00
|
|
|
chmod +x /usr/local/bin/docker-compose
|
2019-07-14 16:18:15 +00:00
|
|
|
curl -fsSL https://raw.githubusercontent.com/docker/compose/${COMPOSE_VERSION}/contrib/completion/bash/docker-compose -o /etc/bash_completion.d/docker-compose
|
2019-06-26 02:35:39 +00:00
|
|
|
fi
|
2018-04-24 03:37:15 +00:00
|
|
|
fi
|
|
|
|
fi
|
|
|
|
|
2018-11-19 16:26:22 +00:00
|
|
|
if [[ ! -f .env ]]; then
|
2018-04-24 03:37:15 +00:00
|
|
|
echo "Writing default .env file..."
|
2020-05-19 05:01:13 +00:00
|
|
|
curl -fsSL https://raw.githubusercontent.com/AzuraCast/AzuraCast/master/sample.env -o .env
|
2018-04-24 03:37:15 +00:00
|
|
|
fi
|
|
|
|
|
2018-11-19 16:26:22 +00:00
|
|
|
if [[ ! -f azuracast.env ]]; then
|
2018-10-19 04:27:30 +00:00
|
|
|
echo "Creating default AzuraCast settings file..."
|
2019-07-14 16:18:15 +00:00
|
|
|
curl -fsSL https://raw.githubusercontent.com/AzuraCast/AzuraCast/master/azuracast.sample.env -o azuracast.env
|
2020-05-10 07:17:08 +00:00
|
|
|
|
|
|
|
# Generate a random password and replace the MariaDB password with it.
|
2020-05-19 05:01:13 +00:00
|
|
|
NEW_PASSWORD=$(
|
|
|
|
tr </dev/urandom -dc _A-Z-a-z-0-9 | head -c"${1:-32}"
|
|
|
|
echo
|
|
|
|
)
|
2020-05-10 07:17:08 +00:00
|
|
|
sed -i "s/azur4c457/${NEW_PASSWORD}/g" azuracast.env
|
2018-10-19 04:27:30 +00:00
|
|
|
fi
|
|
|
|
|
2018-11-19 16:26:22 +00:00
|
|
|
if [[ ! -f docker-compose.yml ]]; then
|
2018-04-24 03:37:15 +00:00
|
|
|
echo "Retrieving default docker-compose.yml file..."
|
2019-07-14 16:18:15 +00:00
|
|
|
curl -fsSL https://raw.githubusercontent.com/AzuraCast/AzuraCast/master/docker-compose.sample.yml -o docker-compose.yml
|
2018-04-24 03:37:15 +00:00
|
|
|
fi
|
|
|
|
|
2020-05-19 05:01:13 +00:00
|
|
|
if ask "Customize AzuraCast ports?" N; then
|
|
|
|
setup_ports
|
|
|
|
fi
|
|
|
|
|
|
|
|
if ask "Set up LetsEncrypt?" N; then
|
|
|
|
setup_letsencrypt
|
|
|
|
fi
|
|
|
|
|
2018-04-24 03:37:15 +00:00
|
|
|
docker-compose pull
|
2020-05-19 05:01:13 +00:00
|
|
|
docker-compose run --user="azuracast" --rm web azuracast_install "$@"
|
2018-04-24 03:37:15 +00:00
|
|
|
docker-compose up -d
|
2019-06-26 02:41:09 +00:00
|
|
|
exit
|
2018-04-24 03:37:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#
|
2018-04-27 00:21:33 +00:00
|
|
|
# Update the Docker images and codebase.
|
2018-04-24 03:37:15 +00:00
|
|
|
# Usage: ./docker.sh update
|
|
|
|
#
|
|
|
|
update() {
|
|
|
|
|
2019-07-21 17:45:36 +00:00
|
|
|
curl -fsSL https://raw.githubusercontent.com/AzuraCast/AzuraCast/master/docker-compose.sample.yml -o docker-compose.new.yml
|
2018-04-24 03:37:15 +00:00
|
|
|
|
2020-04-02 21:07:10 +00:00
|
|
|
FILES_MATCH="$(
|
|
|
|
cmp --silent docker-compose.yml docker-compose.new.yml
|
|
|
|
echo $?
|
|
|
|
)"
|
2019-07-21 17:45:36 +00:00
|
|
|
UPDATE_NEW=0
|
2018-04-24 03:37:15 +00:00
|
|
|
|
2019-07-21 17:45:36 +00:00
|
|
|
if [[ ${FILES_MATCH} -ne 0 ]]; then
|
|
|
|
if ask "The docker-compose.yml file has changed since your version. Overwrite? This will overwrite any customizations you made to this file?" Y; then
|
|
|
|
UPDATE_NEW=1
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
|
|
|
|
if [[ ${UPDATE_NEW} -ne 0 ]]; then
|
|
|
|
docker-compose -f docker-compose.new.yml pull
|
|
|
|
docker-compose down
|
2018-04-24 03:37:15 +00:00
|
|
|
|
2019-07-21 17:45:36 +00:00
|
|
|
cp docker-compose.yml docker-compose.backup.yml
|
|
|
|
mv docker-compose.new.yml docker-compose.yml
|
|
|
|
else
|
|
|
|
rm docker-compose.new.yml
|
|
|
|
|
|
|
|
docker-compose pull
|
|
|
|
docker-compose down
|
2018-10-21 03:35:28 +00:00
|
|
|
fi
|
|
|
|
|
2018-11-19 16:26:22 +00:00
|
|
|
if [[ ! -f azuracast.env ]]; then
|
2019-07-14 16:18:15 +00:00
|
|
|
curl -fsSL https://raw.githubusercontent.com/AzuraCast/AzuraCast/master/azuracast.sample.env -o azuracast.env
|
2018-10-19 04:27:30 +00:00
|
|
|
echo "Default environment file loaded."
|
2018-04-24 03:37:15 +00:00
|
|
|
fi
|
|
|
|
|
2018-11-09 18:25:37 +00:00
|
|
|
docker volume rm azuracast_www_data
|
|
|
|
docker volume rm azuracast_tmp_data
|
2020-04-11 20:00:25 +00:00
|
|
|
docker volume rm azuracast_redis_data
|
2018-11-09 18:25:37 +00:00
|
|
|
|
2020-05-19 05:01:13 +00:00
|
|
|
docker-compose run --user="azuracast" --rm web azuracast_update "$@"
|
2018-04-24 03:37:15 +00:00
|
|
|
docker-compose up -d
|
|
|
|
|
2020-05-19 05:01:13 +00:00
|
|
|
docker rmi "$(docker images | grep "none" | awk '/ / { print $3 }')" 2>/dev/null
|
2018-12-01 16:50:23 +00:00
|
|
|
|
|
|
|
echo "Update complete!"
|
2019-06-26 02:41:09 +00:00
|
|
|
exit
|
2018-04-24 03:37:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#
|
2018-04-27 00:21:33 +00:00
|
|
|
# Update this Docker utility script.
|
|
|
|
# Usage: ./docker.sh update-self
|
|
|
|
#
|
|
|
|
update-self() {
|
2019-07-14 16:18:15 +00:00
|
|
|
curl -fsSL https://raw.githubusercontent.com/AzuraCast/AzuraCast/master/docker.sh -o docker.sh
|
2018-04-27 00:21:33 +00:00
|
|
|
chmod a+x docker.sh
|
|
|
|
|
|
|
|
echo "New Docker utility script downloaded."
|
2019-06-26 02:41:09 +00:00
|
|
|
exit
|
2018-04-27 00:21:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#
|
|
|
|
# Run a CLI command inside the Docker container.
|
|
|
|
# Usage: ./docker.sh cli [command]
|
|
|
|
#
|
|
|
|
cli() {
|
2020-04-02 21:07:10 +00:00
|
|
|
docker-compose run --user="azuracast" --rm web azuracast_cli "$@"
|
2019-06-26 02:41:09 +00:00
|
|
|
exit
|
2019-01-17 13:10:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#
|
|
|
|
# Enter the bash terminal of the running web container.
|
|
|
|
# Usage: ./docker.sh bash
|
|
|
|
#
|
|
|
|
bash() {
|
|
|
|
docker-compose exec --user="azuracast" web bash
|
2019-06-26 02:41:09 +00:00
|
|
|
exit
|
2018-04-27 00:21:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#
|
|
|
|
# Back up the Docker volumes to a .tar.gz file.
|
2018-04-24 03:37:15 +00:00
|
|
|
# Usage:
|
2019-05-24 14:58:33 +00:00
|
|
|
# ./docker.sh backup [/custom/backup/dir/custombackupname.zip]
|
2018-04-24 03:37:15 +00:00
|
|
|
#
|
|
|
|
backup() {
|
|
|
|
BACKUP_PATH=${1:-"./backup.tar.gz"}
|
2019-07-03 23:06:25 +00:00
|
|
|
BACKUP_FILENAME=$(basename -- "$BACKUP_PATH")
|
|
|
|
BACKUP_EXT="${BACKUP_FILENAME##*.}"
|
2019-05-23 15:29:22 +00:00
|
|
|
shift
|
2018-04-24 03:37:15 +00:00
|
|
|
|
2020-05-19 05:01:13 +00:00
|
|
|
MSYS_NO_PATHCONV=1 docker exec --user="azuracast" azuracast_web azuracast_cli azuracast:backup "/tmp/cli_backup.${BACKUP_EXT}" "$@"
|
|
|
|
docker cp "azuracast_web:tmp/cli_backup.${BACKUP_EXT}" "${BACKUP_PATH}"
|
|
|
|
MSYS_NO_PATHCONV=1 docker exec --user="azuracast" azuracast_web rm -f "/tmp/cli_backup.${BACKUP_EXT}"
|
2019-06-26 02:41:09 +00:00
|
|
|
exit
|
2019-05-23 15:29:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#
|
|
|
|
# Restore an AzuraCast backup into Docker.
|
|
|
|
# Usage:
|
2019-05-24 14:58:33 +00:00
|
|
|
# ./docker.sh restore [/custom/backup/dir/custombackupname.zip]
|
2019-05-23 15:29:22 +00:00
|
|
|
#
|
|
|
|
restore() {
|
|
|
|
BACKUP_PATH=${1:-"./backup.tar.gz"}
|
2019-07-03 23:06:25 +00:00
|
|
|
BACKUP_FILENAME=$(basename -- "$BACKUP_PATH")
|
|
|
|
BACKUP_EXT="${BACKUP_FILENAME##*.}"
|
2019-05-23 15:29:22 +00:00
|
|
|
shift
|
2018-04-24 03:37:15 +00:00
|
|
|
|
2019-07-03 23:06:25 +00:00
|
|
|
if [[ ! -f .env ]] || [[ ! -f azuracast.env ]]; then
|
|
|
|
echo "AzuraCast hasn't been installed yet on this server."
|
|
|
|
echo "You should run './docker.sh install' first before restoring."
|
|
|
|
exit 1
|
|
|
|
fi
|
2019-05-23 15:29:22 +00:00
|
|
|
|
2019-07-03 23:06:25 +00:00
|
|
|
if [[ ! -f ${BACKUP_PATH} ]]; then
|
|
|
|
echo "File '${BACKUP_PATH}' does not exist. Nothing to restore."
|
|
|
|
exit 1
|
2019-05-23 15:29:22 +00:00
|
|
|
fi
|
|
|
|
|
2019-07-03 23:06:25 +00:00
|
|
|
if ask "Restoring will remove any existing AzuraCast installation data, replacing it with your backup. Continue?" Y; then
|
|
|
|
docker-compose down -v
|
2019-08-28 17:25:54 +00:00
|
|
|
docker-compose pull
|
2019-07-03 23:06:25 +00:00
|
|
|
docker-compose up -d web
|
2020-05-19 05:01:13 +00:00
|
|
|
docker cp "${BACKUP_PATH}" "azuracast_web:tmp/cli_backup.${BACKUP_EXT}"
|
|
|
|
MSYS_NO_PATHCONV=1 docker exec --user="azuracast" azuracast_web azuracast_restore "/tmp/cli_backup.${BACKUP_EXT}" "$@"
|
2019-05-23 15:29:22 +00:00
|
|
|
|
2019-07-03 23:06:25 +00:00
|
|
|
docker-compose down
|
2019-05-23 15:29:22 +00:00
|
|
|
docker-compose up -d
|
|
|
|
fi
|
2020-05-19 05:01:13 +00:00
|
|
|
|
2019-06-26 02:41:09 +00:00
|
|
|
exit
|
2018-04-24 03:37:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#
|
2019-05-23 15:29:22 +00:00
|
|
|
# Restore the Docker volumes from a legacy backup format .tar.gz file.
|
2018-04-24 03:37:15 +00:00
|
|
|
# Usage:
|
|
|
|
# ./docker.sh restore [/custom/backup/dir/custombackupname.tar.gz]
|
|
|
|
#
|
2019-05-23 15:29:22 +00:00
|
|
|
restore-legacy() {
|
2018-04-24 03:37:15 +00:00
|
|
|
APP_BASE_DIR=$(pwd)
|
|
|
|
|
|
|
|
BACKUP_PATH=${1:-"./backup.tar.gz"}
|
2020-05-19 05:01:13 +00:00
|
|
|
BACKUP_DIR=$(cd "$(dirname "$BACKUP_PATH")" && pwd)
|
2020-04-02 21:07:10 +00:00
|
|
|
BACKUP_FILENAME=$(basename "$BACKUP_PATH")
|
2018-04-24 03:37:15 +00:00
|
|
|
|
2020-05-19 05:01:13 +00:00
|
|
|
cd "$APP_BASE_DIR"
|
2018-04-24 03:37:15 +00:00
|
|
|
|
2020-05-19 05:01:13 +00:00
|
|
|
if [ -f "$BACKUP_PATH" ]; then
|
2018-04-27 00:21:33 +00:00
|
|
|
docker-compose down
|
2018-04-24 03:37:15 +00:00
|
|
|
|
|
|
|
docker volume rm azuracast_db_data azuracast_influx_data azuracast_station_data
|
|
|
|
docker volume create azuracast_db_data
|
|
|
|
docker volume create azuracast_influx_data
|
|
|
|
docker volume create azuracast_station_data
|
|
|
|
|
2020-05-19 05:01:13 +00:00
|
|
|
docker run --rm -v "$BACKUP_DIR:/backup" \
|
2018-04-24 03:37:15 +00:00
|
|
|
-v azuracast_db_data:/azuracast/db \
|
|
|
|
-v azuracast_influx_data:/azuracast/influx \
|
|
|
|
-v azuracast_station_data:/azuracast/stations \
|
2020-05-19 05:01:13 +00:00
|
|
|
busybox tar zxvf "/backup/$BACKUP_FILENAME"
|
2018-04-24 03:37:15 +00:00
|
|
|
|
|
|
|
docker-compose up -d
|
|
|
|
else
|
|
|
|
echo "File $BACKUP_PATH does not exist in this directory. Nothing to restore."
|
|
|
|
exit 1
|
|
|
|
fi
|
2019-06-26 02:41:09 +00:00
|
|
|
|
|
|
|
exit
|
2018-04-24 03:37:15 +00:00
|
|
|
}
|
|
|
|
|
2019-01-29 21:23:38 +00:00
|
|
|
#
|
2019-01-31 03:36:07 +00:00
|
|
|
# DEVELOPER TOOL:
|
2019-01-29 21:23:38 +00:00
|
|
|
# Access the static console as a developer.
|
|
|
|
# Usage: ./docker.sh static [static_container_command]
|
|
|
|
#
|
|
|
|
static() {
|
2020-01-12 19:02:43 +00:00
|
|
|
cd frontend
|
|
|
|
docker-compose build
|
2020-04-02 21:07:10 +00:00
|
|
|
docker-compose run --rm frontend "$@"
|
2019-06-26 02:41:09 +00:00
|
|
|
exit
|
2019-01-29 21:23:38 +00:00
|
|
|
}
|
|
|
|
|
2019-01-31 03:36:07 +00:00
|
|
|
#
|
|
|
|
# DEVELOPER TOOL:
|
2019-01-31 20:29:45 +00:00
|
|
|
# Run the full test suite.
|
2019-01-31 03:36:07 +00:00
|
|
|
#
|
2019-01-31 20:29:45 +00:00
|
|
|
dev-tests() {
|
|
|
|
dev-lint
|
|
|
|
dev-phpstan
|
|
|
|
dev-codeception
|
2019-06-26 02:41:09 +00:00
|
|
|
exit
|
2019-01-31 20:29:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#
|
|
|
|
# DEVELOPER TOOL:
|
|
|
|
# Run linter across all PHP code in the app.
|
|
|
|
#
|
|
|
|
dev-lint() {
|
2020-04-02 21:07:10 +00:00
|
|
|
docker-compose exec --user="azuracast" web composer phplint -- "$@"
|
2019-01-31 20:29:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#
|
|
|
|
# DEVELOPER TOOL:
|
|
|
|
# Run PHPStan for static analysis.
|
2019-01-31 03:36:07 +00:00
|
|
|
#
|
|
|
|
dev-phpstan() {
|
2020-04-02 21:07:10 +00:00
|
|
|
docker-compose exec --user="azuracast" web composer phpstan -- "$@"
|
2019-01-31 03:36:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#
|
|
|
|
# DEVELOPER TOOL:
|
|
|
|
# Run codeception for unit testing.
|
|
|
|
#
|
|
|
|
dev-codeception() {
|
|
|
|
docker-compose -f docker-compose.sample.yml -f docker-compose.testing.yml build web
|
2020-05-19 05:01:13 +00:00
|
|
|
docker-compose -f docker-compose.sample.yml -f docker-compose.testing.yml run --user="azuracast" --rm web composer codeception -- "$@"
|
2019-01-31 03:36:07 +00:00
|
|
|
}
|
|
|
|
|
2018-04-24 03:37:15 +00:00
|
|
|
#
|
2018-04-27 00:21:33 +00:00
|
|
|
# Stop all Docker containers and remove related volumes.
|
2018-04-24 03:37:15 +00:00
|
|
|
# Usage: ./docker.sh uninstall
|
|
|
|
#
|
|
|
|
uninstall() {
|
|
|
|
if ask "This operation is destructive and will wipe your existing Docker containers. Continue? [y/N] " N; then
|
|
|
|
|
|
|
|
docker-compose down -v
|
2018-04-27 00:21:33 +00:00
|
|
|
docker-compose rm -f
|
2018-04-24 03:37:15 +00:00
|
|
|
docker volume prune -f
|
|
|
|
|
2018-04-27 00:23:28 +00:00
|
|
|
echo "All AzuraCast Docker containers and volumes were removed."
|
|
|
|
echo "To remove *all* Docker containers and volumes, run:"
|
|
|
|
echo " docker stop \$(docker ps -a -q)"
|
|
|
|
echo " docker rm \$(docker ps -a -q)"
|
|
|
|
echo " docker volume prune -f"
|
|
|
|
echo ""
|
2018-04-24 03:37:15 +00:00
|
|
|
fi
|
2019-06-26 02:41:09 +00:00
|
|
|
|
|
|
|
exit
|
2018-04-24 03:37:15 +00:00
|
|
|
}
|
|
|
|
|
2018-05-07 14:40:45 +00:00
|
|
|
#
|
|
|
|
# Create and link a LetsEncrypt SSL certificate.
|
2020-05-19 05:01:13 +00:00
|
|
|
# Usage: ./docker.sh letsencrypt-create
|
2018-05-07 14:40:45 +00:00
|
|
|
#
|
2018-05-07 06:17:03 +00:00
|
|
|
letsencrypt-create() {
|
2020-05-19 05:01:13 +00:00
|
|
|
setup_letsencrypt
|
2018-05-07 06:17:03 +00:00
|
|
|
|
2020-05-19 05:01:13 +00:00
|
|
|
docker-compose stop web
|
|
|
|
docker-compose rm web
|
|
|
|
docker-compose up -d
|
2019-06-26 02:41:09 +00:00
|
|
|
exit
|
2018-05-07 06:17:03 +00:00
|
|
|
}
|
|
|
|
|
2020-04-02 21:07:10 +00:00
|
|
|
"$@"
|