#!/usr/bin/env bash # shellcheck disable=SC2145,SC2178,SC2120,SC2162 PODMAN_MODE=0 # Docker and Docker Compose aliases d() { if [[ $PODMAN_MODE -ne 0 ]]; then podman "$@" else docker "$@" fi } dc() { if [[ $PODMAN_MODE -ne 0 ]]; then podman-compose "$@" else if [[ $(docker compose version) ]]; then docker compose "$@" else docker-compose "$@" fi fi } # 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 else if ask "Your current release channel is locked to a stable release, version '${OLD_RELEASE_CHANNEL}'. Switch to the 'Stable' release channel?" N; then AZURACAST_VERSION="stable" 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=$(dc -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 dc -p azuracast_installer -f docker-compose.installer.yml pull dc -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 [[ $PODMAN_MODE -ne 0 ]]; then echo "Podman was detected and will be used instead of Docker..." if [[ $(command -v podman-compose) ]]; then echo "Podman-compose is installed!" else echo "Podman mode is active, but podman-compose is not found." echo "Install it by following the instructions on this page:" echo "https://github.com/containers/podman-compose" exit 1 fi else 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 [[ $(docker compose version) ]]; then echo "Docker Compose v2 is already installed. Continuing..." else 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 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 if [[ $PODMAN_MODE -ne 0 ]]; then .env --file .env set AZURACAST_PODMAN_MODE=true fi dc pull dc run --rm web -- azuracast_install "$@" dc 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 [[ $(docker compose version) ]]; then echo "Docker Compose v2 is already installed. Continuing..." else 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 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 if [[ $PODMAN_MODE -ne 0 ]]; then .env --file .env set AZURACAST_PODMAN_MODE=true fi dc build dc run --rm web -- azuracast_dev_install "$@" dc 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 # Check Docker version. if [[ $PODMAN_MODE -eq 0 ]]; then DOCKER_VERSION=$(docker version -f "{{.Server.Version}}") DOCKER_VERSION_MAJOR=$(echo "$DOCKER_VERSION"| cut -d'.' -f 1) if [ "${DOCKER_VERSION_MAJOR}" -ge 20 ]; then echo "Docker server (version ${DOCKER_VERSION}) meets minimum version requirements." else if ask "Docker is out of date on this server. Attempt automatic upgrade?" Y; then install-docker install-docker-compose fi fi 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 dc -f docker-compose.new.yml pull dc down --timeout 60 cp docker-compose.yml docker-compose.backup.yml mv docker-compose.new.yml docker-compose.yml else rm docker-compose.new.yml dc pull dc down --timeout 60 fi dc run --rm web -- azuracast_update "$@" dc up -d if ask "Clean up all stopped Docker containers and images to save space?" Y; then d 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 -H 'Cache-Control: no-cache, no-store' -fsSL \ https://raw.githubusercontent.com/AzuraCast/AzuraCast/$AZURACAST_RELEASE_BRANCH/docker.sh?$(date +%s) \ -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() { dc exec --user="azuracast" web azuracast_cli "$@" exit } # # Enter the bash terminal of the running web container. # Usage: ./docker.sh bash # bash() { dc exec --user="azuracast" web bash exit } # # Enter the MariaDB database management terminal with the correct credentials. # db() { dc exec web azuracast_db 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 dc exec --user="azuracast" web azuracast_cli azuracast:backup "/var/azuracast/backups/${BACKUP_FILENAME}" "$@" # Move from Docker volume to local filesystem d run --rm -v "azuracast_backups:/backup_src" \ -v "$BACKUP_DIR:/backup_dest" \ busybox mv "/backup_src/${BACKUP_FILENAME}" "/backup_dest/${BACKUP_FILENAME}" echo "Backup completed." exit } # # 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 dc down # Remove most AzuraCast volumes but preserve some essential ones. d volume rm -f $(d volume ls | grep 'azuracast' | grep -v 'station\|install' | awk 'NR>1 {print $2}') d volume create azuracast_backups # Move from local filesystem to Docker volume d 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 dc run --rm web -- azuracast_restore "/var/azuracast/backups/${BACKUP_FILENAME}" "$@" # Move file back from volume to local filesystem d run --rm -v "azuracast_backups:/backup_src" \ -v "$BACKUP_DIR:/backup_dest" \ busybox mv "/backup_src/${BACKUP_FILENAME}" "/backup_dest/${BACKUP_FILENAME}" dc down --timeout 30 dc up -d else dc down # Remove most AzuraCast volumes but preserve some essential ones. d volume rm -f $(d volume ls | grep 'azuracast' | grep -v 'station\|backups\|install' | awk 'NR>1 {print $2}') dc run --rm web -- azuracast_restore "$@" dc down --timeout 30 dc 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 dc down --timeout 30 d volume rm azuracast_db_data azuracast_station_data d volume create azuracast_db_data d volume create azuracast_station_data d run --rm -v "$BACKUP_DIR:/backup" \ -v azuracast_db_data:/azuracast/db \ -v azuracast_station_data:/azuracast/stations \ busybox tar zxvf "/backup/$BACKUP_FILENAME" dc up -d else echo "File $BACKUP_PATH does not exist in this directory. Nothing to restore." exit 1 fi 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 dc down -v dc rm -f d 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 } # # Roll back to a specific stable release version. # rollback() { local AZURACAST_ROLLBACK_VERSION AZURACAST_ROLLBACK_VERSION="$1" if [[ -z "$AZURACAST_ROLLBACK_VERSION" ]]; then echo "No version specified. Specify a version, like 0.19.0." exit 1 fi 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 rollback?" Y; then dc exec --user="azuracast" web azuracast_cli azuracast:setup:rollback "${AZURACAST_ROLLBACK_VERSION}" dc down --timeout 60 .env --file .env set AZURACAST_VERSION=${AZURACAST_ROLLBACK_VERSION} dc pull dc run --rm web -- azuracast_update dc up -d if ask "Clean up all stopped Docker containers and images to save space?" Y; then d system prune -f fi echo "Rollback complete. Your installation has been returned to stable version '${AZURACAST_ROLLBACK_VERSION}'." echo "To return to the regular update channels, run:" echo " ./docker.sh setup-release" echo " " fi exit } # # LetsEncrypt: Now managed via the Web UI. # setup-letsencrypt() { echo "LetsEncrypt is now managed from within the web interface." echo "You can manage it via the 'Administration' panel, then 'System Settings'." echo "Under 'Services' you will find the LetsEncrypt settings." } letsencrypt-create() { setup-letsencrypt exit } # # Utility script to facilitate switching ports. # Usage: ./docker.sh change-ports # change-ports() { setup-ports dc down --timeout 60 dc up -d } # # Helper scripts for basic Docker Compose functions # up() { echo "Starting up AzuraCast services..." dc up -d } down() { echo "Shutting down AzuraCast services..." dc down --timeout 60 } restart() { down up } # Ensure we're in the same directory as this script. cd "$( dirname "${BASH_SOURCE[0]}" )" || exit # Podman support if [[ $(command -v podman) ]]; then PODMAN_MODE=1 fi "$@"