diff --git a/run-seedbox.sh b/prepare-configs.sh similarity index 94% rename from run-seedbox.sh rename to prepare-configs.sh index c8cc400..c8b7f0f 100755 --- a/run-seedbox.sh +++ b/prepare-configs.sh @@ -5,37 +5,6 @@ set -e # Load common functions source tools/tools.sh -# Check that required tools are installed -check_utilities - -SKIP_PULL=0 -DEBUG=0 - -for i in "$@"; do - case $i in - --no-pull) - SKIP_PULL=1 - ;; - --debug) - DEBUG=1 - ;; - *) - echo "[$0] ❌ ERROR: unknown parameter \"$i\"" - exit 1 - ;; - esac -done - -cleanup_on_exit() { - rm -f rules.props *-vpn.props *-envfile.props config.json - [[ -d env ]] && rm -f env/*.tmp -} -trap cleanup_on_exit EXIT - -echo-debug() { - if [[ ${DEBUG} == "1" ]]; then echo "$@"; fi -} - ############################################################################################### ####################################### Load variables ######################################## ############################################################################################### @@ -58,6 +27,7 @@ if [[ ! -f docker-compose.yaml ]]; then fi # Check if there are obsolete config still in .env but should be moved to .env.custom +echo-debug "[$0] ***** Checking obsolete configs... *****" if [[ $(grep "^MYSQL_.*" .env | wc -l) != 0 || $(grep "^WIREGUARD_.*" .env | wc -l) != 0 || $(grep "^NEXTCLOUD_.*" .env | wc -l) != 0 || $(grep "^PORTAINER_.*" .env | wc -l) != 0 || $(grep "^FLOOD_PASSWORD.*" .env | wc -l) != 0 || $(grep "^CALIBRE_PASSWORD.*" .env | wc -l) != 0 || $(grep "^PAPERLESS_.*" .env | wc -l) != 0 ]]; then echo "/!\ Some obsolete config has been detected in your .env." echo "It should be moved in .env.custom as they apply to specific app (this is new since v2.2 update - see documentation)." @@ -90,6 +60,7 @@ if [[ $(grep "^MYSQL_.*" .env | wc -l) != 0 || $(grep "^WIREGUARD_.*" .env | wc fi # Create/update http_auth file according to values in .env file +echo-debug "[$0] ***** Updating HTTP Auth file... *****" source .env echo "${HTTP_USER}:${HTTP_PASSWORD}" > traefik/http_auth @@ -97,10 +68,14 @@ if [[ ! -d env ]]; then mkdir -p env fi +# Check that required tools are installed +check_utilities + # Sanitize and extract variable (without prefixes) from .env.custom file # Input => $1 = app name (exemple traefik) # Output => env/app_name.env written with correct variables (exemple: env/traefik.env) extract_custom_env_file() { + echo-debug "[$0] Extracting custom env file for $1..." # sed explanation: # 1 => Remove all lines starting with a comment (#) # 2 => Remove all empty lines @@ -110,7 +85,9 @@ extract_custom_env_file() { } ## Traefik Certificate Resolver tweaks +echo-debug "[$0] ***** Updating Traefik Certificate Resolver... *****" if [[ ! -z ${TRAEFIK_CUSTOM_ACME_RESOLVER} ]]; then + echo-debug "[$0] Custom ACME resolver detected. Updating Traefik configuration..." if [[ ! -f .env.custom ]]; then echo "[$0] Error. You need to have a .env.custom in order to use TRAEFIK_CUSTOM_ACME_RESOLVER variable." exit 1 @@ -144,8 +121,14 @@ fi echo "[$0] ***** Checking configuration... *****" -yq eval -o json config.yaml > config.json +{ # try + yq eval -o json config.yaml > config.json +} || { # catch + echo "[$0] ERROR: config.yaml is not a valid YAML file. Please check it and try again." + exit 1 +} +echo-debug "[$0] ***** Checking for outdated config... *****" if [[ "${CHECK_FOR_OUTDATED_CONFIG}" == true ]]; then nb_services=$(cat config.json | jq '.services | length') nb_services_sample=$(yq eval -o json config.sample.yaml | jq '.services | length') @@ -172,17 +155,20 @@ check_result_service() { # Check if a service ($1) has been enabled in the config file is_service_enabled() { + echo-debug "[$0] Checking if service $1 is enabled..." local nb=$(cat config.json | jq --arg service $1 '[.services[] | select(.name==$service and .enabled==true)] | length') check_result_service $1 $nb } # Check if a service ($1) has been enabled AND has vpn enabled in the config file has_vpn_enabled() { + echo-debug "[$0] Checking if service $1 has VPN enabled..." local nb=$(cat config.json | jq --arg service $1 '[.services[] | select(.name==$service and .enabled==true and .vpn==true)] | length') check_result_service $1 $nb } # Check if some services have vpn enabled, that gluetun itself is enabled +echo-debug "[$0] Checking if gluetun is enabled when VPN is enabled for some services..." nb_vpn=$(cat config.json | jq '[.services[] | select(.enabled==true and .vpn==true)] | length') if [[ ${nb_vpn} -gt 0 ]] && ! is_service_enabled gluetun; then echo "[$0] ERROR. ${nb_vpn} VPN-enabled services have been enabled BUT gluetun has not been enabled. Please check your config.yaml file." @@ -193,6 +179,7 @@ fi # => If deluge vpn is enabled => gluetun # => If deluge vpn is disabled => deluge if is_service_enabled flood; then + echo "[$0] Flood is enabled. Checking Deluge status..." # Check that if flood is enabled, deluge should also be enabled if ! is_service_enabled deluge; then echo "[$0] ERROR. Flood is enabled but Deluge is not. Please either enable Deluge or disable Flood as Flood depends on Deluge." @@ -207,18 +194,21 @@ if is_service_enabled flood; then fi # Check that if calibre-web is enabled, calibre should also be enabled +echo-debug "[$0] Checking Calibre and Calibre-web status..." if is_service_enabled calibre-web && ! is_service_enabled calibre; then echo "[$0] ERROR. Calibre-web is enabled but Calibre is not. Please either enable Calibre or disable Calibre-web as Calibre-web depends on Calibre." exit 1 fi # Check that if nextcloud is enabled, mariadb should also be enabled +echo-debug "[$0] Checking Nextcloud and MariaDB status..." if is_service_enabled nextcloud && ! is_service_enabled mariadb; then echo "[$0] ERROR. Nextcloud is enabled but MariaDB is not. Please either enable MariaDB or disable Nextcloud as Nextcloud depends on MariaDB." exit 1 fi # Apply other arbitrary custom Traefik config files +echo-debug "[$0] Applying custom Traefik config files..." rm -f $f traefik/custom/custom-* for f in `find samples/custom-traefik -maxdepth 1 -mindepth 1 -type f | grep -E "\.yml$|\.yaml$" | sort`; do echo "[$0] Applying custom Traefik config $f..." @@ -226,6 +216,7 @@ for f in `find samples/custom-traefik -maxdepth 1 -mindepth 1 -type f | grep -E done # Detect Synology devices for Netdata compatibility +echo-debug "[$0] Detecting Synology devices for Netdata compatibility..." if is_service_enabled netdata; then if [[ $(uname -a | { grep synology || true; } | wc -l) -eq 1 ]]; then export OS_RELEASE_FILEPATH="/etc/VERSION" @@ -249,6 +240,7 @@ ALL_SERVICES="-f docker-compose.yaml" GLOBAL_ENV_FILE=".env" # Parse the config.yaml master configuration file +echo-debug "[$0] ***** Parsing the config.yaml master configuration file ... *****" for json in $(yq eval -o json config.yaml | jq -c ".services[]"); do name=$(echo $json | jq -r .name) enabled=$(echo $json | jq -r .enabled) @@ -488,19 +480,3 @@ echo-debug "[$0] Here is the list of all files which are going to be processed: echo "[$0] ***** Config OK. Launching services... *****" -if [[ "${SKIP_PULL}" != "1" ]]; then - echo "[$0] ***** Pulling all images... *****" - ${DOCKER_COMPOSE_BINARY} ${ALL_SERVICES} pull -fi - -echo "[$0] ***** Recreating containers if required... *****" -${DOCKER_COMPOSE_BINARY} --env-file ${GLOBAL_ENV_FILE} ${ALL_SERVICES} up -d --remove-orphans -echo "[$0] ***** Done updating containers *****" -rm -f .env.concat - -echo "[$0] ***** Clean unused images and volumes... *****" -docker image prune -af -docker volume prune -f - -echo "[$0] ***** Done! *****" -exit 0 \ No newline at end of file diff --git a/seedbox.sh b/seedbox.sh new file mode 100755 index 0000000..3b76dfd --- /dev/null +++ b/seedbox.sh @@ -0,0 +1,95 @@ +#!/bin/bash + +run_seedbox() { + + SKIP_PULL=0 + + for i in "$@"; do + case $i in + --no-pull) + SKIP_PULL=1 + ;; + --prune) + PRUNE=1 + ;; + -h|--help) + echo "[$0] Usage: $0 run [--no-pull|--prune]" + exit 0 + ;; + esac + done + + if [[ "${SKIP_PULL}" != "1" ]]; then + echo "[$0] ***** Pulling all images... *****" + ${DOCKER_COMPOSE_BINARY} ${ALL_SERVICES} pull + fi + + echo "[$0] ***** Recreating containers if required... *****" + ${DOCKER_COMPOSE_BINARY} --env-file ${GLOBAL_ENV_FILE} ${ALL_SERVICES} up -d --remove-orphans + echo "[$0] ***** Done updating containers *****" + rm -f .env.concat + + echo "[$0] ***** Clean unused images and volumes... *****" + if [[ "${PRUNE}" == "1" ]]; then + docker image prune -af + docker volume prune -f + fi + + echo "[$0] ***** Done! *****" + exit 0 +} + +stop_seedbox() { + + for i in "$@"; do + case $i in + --prune) + PRUNE=1 + ;; + -h|--help) + echo "[$0] Usage: $0 run [--prune]" + exit 0 + ;; + esac + done + + echo "[$0] ***** Stopping containers... *****" + ${DOCKER_COMPOSE_BINARY} --env-file ${GLOBAL_ENV_FILE} ${ALL_SERVICES} down + rm -f .env.concat + + if [[ "${PRUNE}" == "1" ]]; then + echo "[$0] ***** Clean unused images and volumes... *****" + docker image prune -af + docker volume prune -f + fi + + echo "[$0] ***** Done! *****" + exit 0 +} + +DEBUG=0 + +for i in "$@"; do + case $i in + --debug) + DEBUG=1 + ;; + esac +done + +source prepare-configs.sh + +case $1 in + run) + run_seedbox + ;; + stop) + stop_seedbox + ;; + *) + echo "[$0] ❌ ERROR: unknown parameter \"$1\"" + echo "[$0] Usage: $0 {run|stop}" + exit 1 + ;; +esac + diff --git a/tools/tools.sh b/tools/tools.sh index a87b794..a74c36e 100755 --- a/tools/tools.sh +++ b/tools/tools.sh @@ -4,20 +4,49 @@ ############################### UTIL FUNCTIONS ############################### ############################################################################## +cleanup_on_exit() { + rm -f rules.props *-vpn.props *-envfile.props config.json + [[ -d env ]] && rm -f env/*.tmp +} +trap cleanup_on_exit EXIT + +echo-debug() { + if [[ ${DEBUG} == "1" ]]; then echo "$@"; fi +} + check_utilities () { - # Check that jq is installed - if ! which jq >/dev/null; then - echo "[$0] jq does not exist. Install it from here: https://stedolan.github.io/jq/download/" - echo "[$0] Please install jq version 1.5 or above." - echo "[$0] Also, please make sure it is in the PATH." - exit 1 - fi - - # Check that yq is installed - if ! which yq >/dev/null; then - echo "[$0] yq does not exist. Install it from here: https://github.com/mikefarah/yq/releases" - echo "[$0] Please install yq version 4 or above." - echo "[$0] Also, please make sure it is in the PATH." - exit 1 - fi + echo "[$0] ***** Checking required tools... *****" + + # Check if versions of required tools are correct + check_version() { + local tool=$1 + local required_version=$2 + + local required_major_version=$(echo $required_version | cut -d'.' -f1) + local required_minor_version=$(echo $required_version | cut -d'.' -f2) + + local current_version=$($tool --version | grep -oP '\d+\.\d+') + local current_major_version=$(echo $current_version | cut -d'.' -f1) + local current_minor_version=$(echo $current_version | cut -d'.' -f2) + + if [[ $current_major_version -lt $required_major_version ]]; then + echo "[$0] ERROR: $tool version $required_version or higher is required. Current version is $current_version." + exit 1 + fi + + if [[ $current_major_version -eq $required_major_version && $current_minor_version -lt $required_minor_version ]]; then + echo "[$0] ERROR: $tool version $required_version or higher is required. Current version is $current_version." + exit 1 + fi + } + + # Define required versions for each tool + declare -A REQUIRED_VERSIONS + REQUIRED_VERSIONS=( ["docker"]="20.10" [$DOCKER_COMPOSE_BINARY]="2.27" ["yq"]="4.0" ["jq"]="1.5" ) + + # Check versions + echo "[$0] ***** Checking version of required tools... *****" + for tool in "${!REQUIRED_VERSIONS[@]}"; do + check_version $tool ${REQUIRED_VERSIONS[$tool]} + done } \ No newline at end of file