From 7b058cfe47b70dd35a7dd09af68af93070aa5cbc Mon Sep 17 00:00:00 2001 From: Jerry Vonau Date: Mon, 29 Aug 2022 11:47:22 -0500 Subject: [PATCH] upstream docker.sh as of Aug 22, 2022 https://raw.githubusercontent.com/AzuraCast/AzuraCast/stable/docker.sh --- roles/azuracast/upstream/docker.sh | 840 +++++++++++++++++++++++++++++ 1 file changed, 840 insertions(+) create mode 100755 roles/azuracast/upstream/docker.sh diff --git a/roles/azuracast/upstream/docker.sh b/roles/azuracast/upstream/docker.sh new file mode 100755 index 000000000..dfa1c2b81 --- /dev/null +++ b/roles/azuracast/upstream/docker.sh @@ -0,0 +1,840 @@ +#!/usr/bin/env bash +# 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 + 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 +} + +# Shortcut to convert semver version (x.yyy.zzz) into a comparable number. +version-number() { + echo "$@" | awk -F. '{ printf("%03d%03d%03d\n", $1,$2,$3); }' +} + +# Get the current release channel for AzuraCast +get-release-channel() { + local AZURACAST_VERSION="latest" + if [[ -f .env ]]; then + .env --file .env get AZURACAST_VERSION + AZURACAST_VERSION="${REPLY:-latest}" + fi + + echo "$AZURACAST_VERSION" +} + +get-release-branch-name() { + if [[ $(get-release-channel) == "stable" ]]; then + echo "stable" + else + echo "main" + fi +} + +# 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 + + if [[ "${2:-}" == "Y" ]]; then + prompt="Y/n" + default=Y + elif [[ "${2:-}" == "N" ]]; then + 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] " + + read reply + + # Default? + if [[ -z "$reply" ]]; then + reply=${default} + fi + + # Check if the reply is valid + case "$reply" in + Y* | y*) return 0 ;; + N* | n*) return 1 ;; + esac + + done +} + +# Generate a prompt to set an environment file value. +envfile-set() { + local VALUE INPUT + + .env --file .env + + .env get "$1" + VALUE=${REPLY:-$2} + + echo -n "$3 [$VALUE]: " + read INPUT + + VALUE=${INPUT:-$VALUE} + + .env set "${1}=${VALUE}" +} + +# +# Configure the ports used by AzuraCast. +# +setup-ports() { + envfile-set "AZURACAST_HTTP_PORT" "80" "Port to use for HTTP connections" + envfile-set "AZURACAST_HTTPS_PORT" "443" "Port to use for HTTPS connections" + envfile-set "AZURACAST_SFTP_PORT" "2022" "Port to use for SFTP connections" +} + +# +# Configure release mode settings. +# +setup-release() { + if [[ ! -f .env ]]; then + curl -fsSL https://raw.githubusercontent.com/AzuraCast/AzuraCast/main/sample.env -o .env + fi + + local OLD_RELEASE_CHANNEL + .env --file .env get AZURACAST_VERSION + OLD_RELEASE_CHANNEL="${REPLY:-latest}" + + local AZURACAST_VERSION="${OLD_RELEASE_CHANNEL}" + + if [[ $AZURACAST_VERSION == "latest" ]]; then + if ask "Your current release channel is 'Rolling Release'. Switch to 'Stable' release channel?" N; then + AZURACAST_VERSION="stable" + fi + elif [[ $AZURACAST_VERSION == "stable" ]]; then + if ask "Your current release channel is 'Stable'. Switch to 'Rolling Release' release channel?" N; then + AZURACAST_VERSION="latest" + fi + fi + + .env --file .env set AZURACAST_VERSION=${AZURACAST_VERSION} + + if [[ $AZURACAST_VERSION != $OLD_RELEASE_CHANNEL ]]; then + if ask "You should update the Docker Utility Script after changing release channels. Automatically update it now?" Y; then + update-self + fi + fi +} + +check-install-requirements() { + local CURRENT_OS CURRENT_ARCH REQUIRED_COMMANDS SCRIPT_DIR + + set -e + + echo "Checking installation requirements for AzuraCast..." + + CURRENT_OS=$(uname -s) + if [[ $CURRENT_OS == "Linux" ]]; then + echo -en "\e[32m[PASS]\e[0m Operating System: ${CURRENT_OS}\n" + else + echo -en "\e[41m[FAIL]\e[0m Operating System: ${CURRENT_OS}\n" + + echo " You are running an unsupported operating system." + echo " Automated AzuraCast installation is not currently supported on this" + echo " operating system." + exit 1 + fi + + CURRENT_ARCH=$(uname -m) + if [[ $CURRENT_ARCH == "x86_64" ]]; then + echo -en "\e[32m[PASS]\e[0m Architecture: ${CURRENT_ARCH}\n" + elif [[ $CURRENT_ARCH == "aarch64" ]]; then + echo -en "\e[32m[PASS]\e[0m Architecture: ${CURRENT_ARCH}\n" + else + echo -en "\e[41m[FAIL]\e[0m Architecture: ${CURRENT_ARCH}\n" + + echo " You are running an unsupported processor architecture." + echo " Automated AzuraCast installation is not currently supported on this " + echo " operating system." + exit 1 + fi + + REQUIRED_COMMANDS=(curl awk) + for COMMAND in "${REQUIRED_COMMANDS[@]}" ; do + if [[ $(command -v "$COMMAND") ]]; then + echo -en "\e[32m[PASS]\e[0m Command Present: ${COMMAND}\n" + else + echo -en "\e[41m[FAIL]\e[0m Command Present: ${COMMAND}\n" + + echo " ${COMMAND} does not appear to be installed." + echo " Install ${COMMAND} using your host's package manager," + echo " then continue installing using this script." + exit 1 + fi + done + + if [[ $EUID -ne 0 ]]; then + if [[ $(command -v sudo) ]]; then + echo -en "\e[32m[PASS]\e[0m User Permissions\n" + else + echo -en "\e[41m[FAIL]\e[0m User Permissions\n" + + echo " You are not currently the root user, and " + 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 + else + echo -en "\e[32m[PASS]\e[0m User Permissions\n" + fi + + SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" + if [[ $SCRIPT_DIR == "/var/azuracast" ]]; then + echo -en "\e[32m[PASS]\e[0m Installation Directory\n" + else + echo -en "\e[93m[WARN]\e[0m Installation Directory\n" + echo " AzuraCast is not installed in /var/azuracast, as is recommended" + echo " for most installations. This will not prevent AzuraCast from" + echo " working, but you will need to update any instructions in our" + echo " documentation to reflect your current directory:" + echo " $SCRIPT_DIR" + fi + + echo -en "\e[32m[PASS]\e[0m All requirements met!\n" + + set +e +} + +install-docker() { + set -e + + curl -fsSL get.docker.com -o get-docker.sh + sh get-docker.sh + rm get-docker.sh + + if [[ $EUID -ne 0 ]]; then + sudo usermod -aG docker "$(whoami)" + + echo "You must log out or restart to apply necessary Docker permissions changes." + echo "Restart, then continue installing using this script." + exit 1 + fi + + set +e +} + +install-docker-compose() { + set -e + echo "Installing Docker Compose..." + + curl -fsSL -o docker-compose https://github.com/docker/compose/releases/download/v2.4.1/docker-compose-linux-$(uname -m) + + ARCHITECTURE=amd64 + if [ "$(uname -m)" = "aarch64" ]; then + ARCHITECTURE=arm64 + fi + curl -fsSL -o docker-compose-switch https://github.com/docker/compose-switch/releases/download/v1.0.4/docker-compose-linux-${ARCHITECTURE} + + if [[ $EUID -ne 0 ]]; then + sudo chmod a+x ./docker-compose + sudo chmod a+x ./docker-compose-switch + + sudo mv ./docker-compose /usr/libexec/docker/cli-plugins/docker-compose + sudo mv ./docker-compose-switch /usr/local/bin/docker-compose + else + chmod a+x ./docker-compose + chmod a+x ./docker-compose-switch + + mv ./docker-compose /usr/libexec/docker/cli-plugins/docker-compose + mv ./docker-compose-switch /usr/local/bin/docker-compose + fi + + echo "Docker Compose updated!" + set +e +} + +run-installer() { + local AZURACAST_RELEASE_BRANCH + AZURACAST_RELEASE_BRANCH=$(get-release-branch-name) + + if [[ ! -f .env ]]; then + curl -fsSL https://raw.githubusercontent.com/AzuraCast/AzuraCast/$AZURACAST_RELEASE_BRANCH/sample.env -o .env + fi + if [[ ! -f azuracast.env ]]; then + curl -fsSL https://raw.githubusercontent.com/AzuraCast/AzuraCast/$AZURACAST_RELEASE_BRANCH/azuracast.sample.env -o azuracast.env + fi + if [[ ! -f docker-compose.yml ]]; then + curl -fsSL https://raw.githubusercontent.com/AzuraCast/AzuraCast/$AZURACAST_RELEASE_BRANCH/docker-compose.sample.yml -o docker-compose.yml + fi + + touch docker-compose.new.yml + + local dc_config_test=$(docker-compose -f docker-compose.new.yml config 2>/dev/null) + if [ $? -ne 0 ]; then + if ask "Docker Compose needs to be updated to continue. Update to latest version?" Y; then + install-docker-compose + fi + fi + + curl -fsSL https://raw.githubusercontent.com/AzuraCast/AzuraCast/$AZURACAST_RELEASE_BRANCH/docker-compose.installer.yml -o docker-compose.installer.yml + + docker-compose -p azuracast_installer -f docker-compose.installer.yml pull + docker-compose -p azuracast_installer -f docker-compose.installer.yml run --rm installer install "$@" + + rm docker-compose.installer.yml +} + +# +# Run the initial installer of Docker and AzuraCast. +# Usage: ./docker.sh install +# +install() { + check-install-requirements + + if [[ $(command -v docker) && $(docker --version) ]]; then + echo "Docker is already installed! Continuing..." + else + if ask "Docker does not appear to be installed. Install Docker now?" Y; then + install-docker + fi + fi + + if [[ $(command -v docker-compose) ]]; then + echo "Docker Compose is already installed. Continuing..." + else + if ask "Docker Compose does not appear to be installed. Install Docker Compose now?" Y; then + install-docker-compose + fi + fi + + setup-release + + run-installer "$@" + + # Installer creates a file at docker-compose.new.yml; copy it to the main spot. + if [[ -s docker-compose.new.yml ]]; then + if [[ -f docker-compose.yml ]]; then + rm docker-compose.yml + fi + + mv docker-compose.new.yml docker-compose.yml + fi + + # If this script is running as a non-root user, set the PUID/PGID in the environment vars appropriately. + if [[ $EUID -ne 0 ]]; then + .env --file .env set AZURACAST_PUID="$(id -u)" + .env --file .env set AZURACAST_PGID="$(id -g)" + fi + + docker-compose pull + + docker-compose run --rm web -- azuracast_install "$@" + docker-compose up -d + exit +} + +install-dev() { + if [[ $(command -v docker) && $(docker --version) ]]; then + echo "Docker is already installed! Continuing..." + else + if ask "Docker does not appear to be installed. Install Docker now?" Y; then + install-docker + fi + fi + + if [[ $(command -v docker-compose) ]]; then + echo "Docker Compose is already installed. Continuing..." + else + if ask "Docker Compose does not appear to be installed. Install Docker Compose now?" Y; then + install-docker-compose + fi + fi + + if [[ ! -f docker-compose.yml ]]; then + cp docker-compose.sample.yml docker-compose.yml + fi + if [[ ! -f docker-compose.override.yml ]]; then + cp docker-compose.dev.yml docker-compose.override.yml + fi + if [[ ! -f .env ]]; then + cp dev.env .env + fi + if [[ ! -f azuracast.env ]]; then + cp azuracast.dev.env azuracast.env + + echo "Customize azuracast.env file now before continuing. Re-run this command to continue installation." + exit + fi + + # If this script is running as a non-root user, set the PUID/PGID in the environment vars appropriately. + if [[ $EUID -ne 0 ]]; then + .env --file .env set AZURACAST_PUID="$(id -u)" + .env --file .env set AZURACAST_PGID="$(id -g)" + fi + + chmod 777 ./frontend/ ./web/ ./vendor/ \ + ./web/static/ ./web/static/api/ \ + ./web/static/dist/ ./web/static/img/ + + docker-compose build + docker-compose run --rm web -- azuracast_install "$@" + + docker-compose -p azuracast_frontend -f docker-compose.frontend.yml build + docker-compose -p azuracast_frontend -f docker-compose.frontend.yml run --rm frontend npm run build + + docker-compose up -d + exit +} + +# +# Update the Docker images and codebase. +# Usage: ./docker.sh update +# +update() { + echo "[NOTICE] Before you continue, please make sure you have a recent snapshot of your system and or backed it up." + if ask "Are you ready to continue with the update?" Y; then + + # Check for a new Docker Utility Script. + local AZURACAST_RELEASE_BRANCH + AZURACAST_RELEASE_BRANCH=$(get-release-branch-name) + + curl -fsSL https://raw.githubusercontent.com/AzuraCast/AzuraCast/$AZURACAST_RELEASE_BRANCH/docker.sh -o docker.new.sh + + local UTILITY_FILES_MATCH + UTILITY_FILES_MATCH="$( + cmp --silent docker.sh docker.new.sh + echo $? + )" + + local UPDATE_UTILITY=0 + if [[ ${UTILITY_FILES_MATCH} -ne 0 ]]; then + if ask "The Docker Utility Script has changed since your version. Update to latest version?" Y; then + UPDATE_UTILITY=1 + fi + fi + + if [[ ${UPDATE_UTILITY} -ne 0 ]]; then + mv docker.new.sh docker.sh + chmod a+x docker.sh + + echo "A new Docker Utility Script has been downloaded." + echo "Please re-run the update process to continue." + exit + else + rm docker.new.sh + fi + + run-installer --update "$@" + + # Check for updated Docker Compose config. + local COMPOSE_FILES_MATCH + + if [[ ! -s docker-compose.new.yml ]]; then + curl -fsSL https://raw.githubusercontent.com/AzuraCast/AzuraCast/$AZURACAST_RELEASE_BRANCH/docker-compose.sample.yml -o docker-compose.new.yml + fi + + COMPOSE_FILES_MATCH="$( + cmp --silent docker-compose.yml docker-compose.new.yml + echo $? + )" + + if [[ ${COMPOSE_FILES_MATCH} -ne 0 ]]; then + docker-compose -f docker-compose.new.yml pull + docker-compose down + + 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 + fi + + docker-compose run --rm web -- azuracast_update "$@" + docker-compose up -d + + if ask "Clean up all stopped Docker containers and images to save space?" Y; then + docker system prune -f + fi + + echo "Update complete!" + fi + exit +} + +# +# Update this Docker utility script. +# Usage: ./docker.sh update-self +# +update-self() { + local AZURACAST_RELEASE_BRANCH + AZURACAST_RELEASE_BRANCH=$(get-release-branch-name) + + curl -fsSL https://raw.githubusercontent.com/AzuraCast/AzuraCast/$AZURACAST_RELEASE_BRANCH/docker.sh -o docker.sh + chmod a+x docker.sh + + echo "New Docker utility script downloaded." + exit +} + +# +# Run a CLI command inside the Docker container. +# Usage: ./docker.sh cli [command] +# +cli() { + docker-compose exec --user="azuracast" web azuracast_cli "$@" + exit +} + +# +# Enter the bash terminal of the running web container. +# Usage: ./docker.sh bash +# +bash() { + docker-compose exec --user="azuracast" web bash + exit +} + +# +# Enter the MariaDB database management terminal with the correct credentials. +# +db() { + local MYSQL_HOST MYSQL_PORT MYSQL_USER MYSQL_PASSWORD MYSQL_DATABASE + + .env --file azuracast.env get MYSQL_HOST + MYSQL_HOST="${REPLY:-localhost}" + + .env --file azuracast.env get MYSQL_PORT + MYSQL_PORT="${REPLY:-3306}" + + .env --file azuracast.env get MYSQL_USER + MYSQL_USER="${REPLY:-azuracast}" + + .env --file azuracast.env get MYSQL_PASSWORD + MYSQL_PASSWORD="${REPLY:-azur4c457}" + + .env --file azuracast.env get MYSQL_DATABASE + MYSQL_DATABASE="${REPLY:-azuracast}" + + docker-compose exec --user="mysql" web mysql --user=${MYSQL_USER} --password=${MYSQL_PASSWORD} \ + --host=${MYSQL_HOST} --port=${MYSQL_PORT} --database=${MYSQL_DATABASE} + + exit +} + +# +# Back up the Docker volumes to a .tar.gz file. +# Usage: +# ./docker.sh backup [/custom/backup/dir/custombackupname.zip] +# +backup() { + local BACKUP_PATH BACKUP_DIR BACKUP_FILENAME BACKUP_EXT + BACKUP_PATH=$(readlink -f ${1:-"./backup.tar.gz"}) + BACKUP_DIR=$(dirname -- "$BACKUP_PATH") + BACKUP_FILENAME=$(basename -- "$BACKUP_PATH") + BACKUP_EXT="${BACKUP_FILENAME##*.}" + shift + + # Prepare permissions + if [[ $EUID -ne 0 ]]; then + .env --file .env set AZURACAST_PUID="$(id -u)" + .env --file .env set AZURACAST_PGID="$(id -g)" + fi + + docker-compose exec --user="azuracast" web azuracast_cli azuracast:backup "/var/azuracast/backups/${BACKUP_FILENAME}" "$@" + + # Move from Docker volume to local filesystem + docker run --rm -v "azuracast_backups:/backup_src" \ + -v "$BACKUP_DIR:/backup_dest" \ + busybox mv "/backup_src/${BACKUP_FILENAME}" "/backup_dest/${BACKUP_FILENAME}" +} + +# +# Restore an AzuraCast backup into Docker. +# Usage: +# ./docker.sh restore [/custom/backup/dir/custombackupname.zip] +# +restore() { + 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 + + if ask "Restoring will remove any existing AzuraCast installation data, replacing it with your backup. Continue?" Y; then + if [[ $1 != "" ]]; then + local BACKUP_PATH BACKUP_DIR BACKUP_FILENAME BACKUP_EXT + BACKUP_PATH=$(readlink -f ${1:-"./backup.tar.gz"}) + BACKUP_DIR=$(dirname -- "$BACKUP_PATH") + BACKUP_FILENAME=$(basename -- "$BACKUP_PATH") + BACKUP_EXT="${BACKUP_FILENAME##*.}" + shift + + if [[ ! -f ${BACKUP_PATH} ]]; then + echo "File '${BACKUP_PATH}' does not exist. Nothing to restore." + exit 1 + fi + + docker-compose down -v + docker volume create azuracast_backups + + # Move from local filesystem to Docker volume + docker run --rm -v "$BACKUP_DIR:/backup_src" \ + -v "azuracast_backups:/backup_dest" \ + busybox mv "/backup_src/${BACKUP_FILENAME}" "/backup_dest/${BACKUP_FILENAME}" + + # Prepare permissions + if [[ $EUID -ne 0 ]]; then + .env --file .env set AZURACAST_PUID="$(id -u)" + .env --file .env set AZURACAST_PGID="$(id -g)" + fi + + docker-compose run --rm web -- azuracast_restore "/var/azuracast/backups/${BACKUP_FILENAME}" "$@" + + # Move file back from volume to local filesystem + docker run --rm -v "azuracast_backups:/backup_src" \ + -v "$BACKUP_DIR:/backup_dest" \ + busybox mv "/backup_src/${BACKUP_FILENAME}" "/backup_dest/${BACKUP_FILENAME}" + + docker-compose down + docker-compose up -d + else + docker-compose down + + # Remove all volumes except the backup volume. + docker volume rm -f $(docker volume ls | grep -v "azuracast_backups" | awk 'NR>1 {print $2}') + + docker-compose run --rm web -- azuracast_restore "$@" + + docker-compose down + docker-compose up -d + fi + fi + exit +} + +# +# Restore the Docker volumes from a legacy backup format .tar.gz file. +# Usage: +# ./docker.sh restore [/custom/backup/dir/custombackupname.tar.gz] +# +restore-legacy() { + local APP_BASE_DIR BACKUP_PATH BACKUP_DIR BACKUP_FILENAME + + APP_BASE_DIR=$(pwd) + + BACKUP_PATH=${1:-"./backup.tar.gz"} + BACKUP_DIR=$(cd "$(dirname "$BACKUP_PATH")" && pwd) + BACKUP_FILENAME=$(basename "$BACKUP_PATH") + + cd "$APP_BASE_DIR" || exit + + if [ -f "$BACKUP_PATH" ]; then + docker-compose down + + docker volume rm azuracast_db_data azuracast_station_data + docker volume create azuracast_db_data + docker volume create azuracast_station_data + + docker run --rm -v "$BACKUP_DIR:/backup" \ + -v azuracast_db_data:/azuracast/db \ + -v azuracast_station_data:/azuracast/stations \ + busybox tar zxvf "/backup/$BACKUP_FILENAME" + + docker-compose up -d + else + echo "File $BACKUP_PATH does not exist in this directory. Nothing to restore." + exit 1 + fi + + exit +} + +# +# DEVELOPER TOOL: +# Access the static console as a developer. +# Usage: ./docker.sh static [static_container_command] +# +static() { + docker-compose -f docker-compose.frontend.yml down -v + docker-compose -f docker-compose.frontend.yml build + docker-compose --env-file=.env -f docker-compose.frontend.yml run --rm frontend "$@" + exit +} + +# +# Stop all Docker containers and remove related volumes. +# Usage: ./docker.sh uninstall +# +uninstall() { + if ask "This operation is destructive and will wipe your existing Docker containers. Continue?" N; then + + docker-compose down -v + docker-compose rm -f + docker volume prune -f + + 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 "" + fi + + exit +} + +# +# LetsEncrypt: Now managed via the Web UI. +# +setup-letsencrypt() { + echo "LetsEncrypt is now managed from within the web interface." +} + +letsencrypt-create() { + setup-letsencrypt + exit +} + +# +# Utility script to facilitate switching ports. +# Usage: ./docker.sh change-ports +# +change-ports() { + setup-ports + + docker-compose down + docker-compose up -d +} + +# +# Helper scripts for basic Docker Compose functions +# +up() { + echo "Starting up AzuraCast services..." + docker-compose up -d +} + +down() { + echo "Shutting down AzuraCast services..." + docker-compose down +} + +restart() { + down + up +} + +# Ensure we're in the same directory as this script. +cd "$( dirname "${BASH_SOURCE[0]}" )" || exit + +"$@"