GUI menus to control install and maintenance
MODIFY
main.sh
main.sh
@@ -77,6 +77,17 @@ usage() {
grep '^#/' "${SCRIPTPATH}/${SCRIPTNAME}" | cut -c4-
}
+# # Menu Runner Function
+run_menu() {
+ local MENUSNAME="${1:-}"; shift
+ if [[ -f ${SCRIPTPATH}/scripts/menus/${MENUSNAME}.sh ]]; then
+ source "${SCRIPTPATH}/scripts/menus/${MENUSNAME}.sh"
+ ${MENUSNAME} "$@";
+ else
+ fatal "${SCRIPTPATH}/scripts/menus/${MENUSNAME}.sh not found."
+ fi
+}
+
# # Script Runner Function
run_script() {
local SCRIPTSNAME="${1:-}"; shift
@@ -104,5 +115,6 @@ main() {
run_script 'root_check'
source "${SCRIPTPATH}/scripts/cmdline.sh"
cmdline "${ARGS[@]:-}"
+ run_menu 'menu_main'
}
main

ADD
scripts/menu_app_helper.sh
+#!/bin/bash
+set -euo pipefail
+IFS=$'\n\t'
+
+menu_app_helper() {
+ GetMenuItem() {
+ local APPNAME
+ APPNAME="${1}"
+ local APPENABLED
+ APPENABLED=$(run_script 'env_get' "${APPNAME}_ENABLED")
+ local APPONOFF
+ if [[ ${APPENABLED} == "true" ]]; then
+ APPONOFF="on"
+ else
+ APPONOFF="off"
+ fi
+ case "${APPNAME}" in
+ "BAZARR")
+ SupportedAppDescr+=("Bazarr" "Companion to Sonarr to manage and download subtitles" "${APPONOFF}")
+ ;;
+ "COUCHPOTATO")
+ SupportedAppDescr+=("Couchpotato" "Movies PVR Client" "${APPONOFF}")
+ ;;
+ "DELUGE")
+ SupportedAppDescr+=("Deluge" "Lightweight, Full-featured BitTorrent client" "${APPONOFF}")
+ ;;
+ "DUCKDNS")
+ SupportedAppDescr+=("DuckDNS" "free service which will point a DNS to an IP of your choice" "${APPONOFF}")
+ ;;
+ "DUPLICATI")
+ SupportedAppDescr+=("Duplicati" "Backup software to store backups online with strong encryption" "${APPONOFF}")
+ ;;
+ "EMBY")
+ SupportedAppDescr+=("Emby" "Organize, play, and stream audio and video" "${APPONOFF}")
+ ;;
+ "HEADPHONES")
+ SupportedAppDescr+=("Headphones" "Music PVR Client" "${APPONOFF}")
+ ;;
+ "HOMEASSISTANT")
+ SupportedAppDescr+=("Home Assistant" "Track and control all devices at home and automate control" "${APPONOFF}")
+ ;;
+ "HYDRA2")
+ SupportedAppDescr+=("Hydra2" "Meta search for NZB indexers" "${APPONOFF}")
+ ;;
+ "JACKETT")
+ SupportedAppDescr+=("Jackett" "API Support for your favorite private trackers" "${APPONOFF}")
+ ;;
+ "LAZYLIBRARIAN")
+ SupportedAppDescr+=("Lazylibrarian" "Book PVR Client" "${APPONOFF}")
+ ;;
+ "LETSENCRYPT")
+ SupportedAppDescr+=("Letsencrypt" "Certificate authority that provides free X.509 certificates" "${APPONOFF}")
+ ;;
+ "LIDARR")
+ SupportedAppDescr+=("Lidarr" "Music download manager for Usenet and BitTorrent users" "${APPONOFF}")
+ ;;
+ "LOGARR")
+ SupportedAppDescr+=("Logarr" "Self-hosted, single-page, log consolidation tool" "${APPONOFF}")
+ ;;
+ "MONITORR")
+ SupportedAppDescr+=("Monitorr" "Webfront to live display the status of any webapp or service" "${APPONOFF}")
+ ;;
+ "MUXIMUX")
+ SupportedAppDescr+=("Muximux" "A lightweight way to manage your HTPC" "${APPONOFF}")
+ ;;
+ "NZBGET")
+ SupportedAppDescr+=("NZBGet" "NZB Newsgrabber / Downloader" "${APPONOFF}")
+ ;;
+ "OMBI")
+ SupportedAppDescr+=("Ombi" "Allow your users to Request Movies, TV Shows and Albums" "${APPONOFF}")
+ ;;
+ "ORGANIZR")
+ SupportedAppDescr+=("Organizr" "HTPC/Homelab Services Organizer" "${APPONOFF}")
+ ;;
+ "PLEX")
+ SupportedAppDescr+=("Plex" "Organizes all of your video, music and photo collections" "${APPONOFF}")
+ ;;
+ "PLEXREQUESTS")
+ SupportedAppDescr+=("Plex Requests" "Automated way for users to request new content for Plex" "${APPONOFF}")
+ ;;
+ "PORTAINER")
+ SupportedAppDescr+=("Portainer" "Simple management UI for Docker" "${APPONOFF}")
+ ;;
+ "RADARR")
+ SupportedAppDescr+=("Radarr" "Automatically download movies via Usenet and BitTorrent" "${APPONOFF}")
+ ;;
+ "RUTORRENT")
+ SupportedAppDescr+=("ruTorrent" "Web front-end for rTorrent" "${APPONOFF}")
+ ;;
+ "SABNZBD")
+ SupportedAppDescr+=("SABnzbd" "NZB Newsgrabber / Downloader" "${APPONOFF}")
+ ;;
+ "SICKRAGE")
+ SupportedAppDescr+=("Sickrage" "Automatic Video Library Manager for TV Shows" "${APPONOFF}")
+ ;;
+ "SONARR")
+ SupportedAppDescr+=("Sonarr" "Smart TV show PVR via Usenet and BitTorrent" "${APPONOFF}")
+ ;;
+ "SYNCTHING")
+ SupportedAppDescr+=("Syncthing" "Open-source peer-to-peer file synchronization" "${APPONOFF}")
+ ;;
+ "TAUTULLI")
+ SupportedAppDescr+=("Tautulli" "Monitoring and tracking tool for Plex Media Server" "${APPONOFF}")
+ ;;
+ "TRANSMISSION")
+ SupportedAppDescr+=("Transmission" "Fast, easy, and free BitTorrent client" "${APPONOFF}")
+ ;;
+ "UNIFI")
+ SupportedAppDescr+=("Unifi" "Controller software for wireless networks" "${APPONOFF}")
+ ;;
+ "WATCHTOWER")
+ SupportedAppDescr+=("Watchtower" "Automatically update running Docker containers" "${APPONOFF}")
+ ;;
+ *)
+ warning "WARNING ${APPNAME} APP DESCRIPTION NOT FOUND"
+ SupportedAppDescr+=("${APPNAME}" "Description not found" "${APPONOFF}")
+ ;;
+ esac
+ }
+
+ SupportedAppDescr=()
+ while IFS= read -r line; do
+ local APPNAME
+ APPNAME=${line/_ENABLED=*/}
+ local FILENAME
+ FILENAME=${APPNAME,,}
+ if [[ -d ${SCRIPTPATH}/compose/.apps/${FILENAME}/ ]]; then
+ if [[ -f ${SCRIPTPATH}/compose/.apps/${FILENAME}/${FILENAME}.yml ]]; then
+ if [[ ${ARCH} == "arm64" ]]; then
+ if [[ -f ${SCRIPTPATH}/compose/.apps/${FILENAME}/${FILENAME}.arm64.yml ]]; then
+ GetMenuItem "${APPNAME}"
+ elif [[ -f ${SCRIPTPATH}/compose/.apps/${FILENAME}/${FILENAME}.armhf.yml ]]; then
+ GetMenuItem "${APPNAME}"
+ fi
+ fi
+ if [[ ${ARCH} == "armhf" ]]; then
+ if [[ -f ${SCRIPTPATH}/compose/.apps/${FILENAME}/${FILENAME}.armhf.yml ]]; then
+ GetMenuItem "${APPNAME}"
+ fi
+ fi
+ if [[ ${ARCH} == "amd64" ]]; then
+ GetMenuItem "${APPNAME}"
+ fi
+ fi
+ fi
+ done < <(grep '_ENABLED=' < "${SCRIPTPATH}/compose/.env")
+}

ADD
scripts/menus/application_selector.sh
+#!/bin/bash
+set -euo pipefail
+IFS=$'\n\t'
+
+application_selector() {
+ SupportedAppDescr=()
+ run_script 'menu_app_helper'
+
+ # Might need to be adjusted if more applications are added
+ local LINES
+ LINES=$(stty size | cut '-d ' -f1)
+ LINES=$((LINES<27?LINES:27))
+
+ local COLUMNS
+ COLUMNS=$(stty size | cut '-d ' -f2)
+ COLUMNS=$((COLUMNS<92?COLUMNS:92))
+
+ local NETLINES
+ NETLINES=$((LINES-10))
+
+ local tempfile
+ tempfile=$(mktemp)
+
+ if [[ ${CI:-} != true ]] && [[ ${TRAVIS:-} != true ]]; then
+ whiptail --title "Application Selector" --fb --checklist --separate-output "Choose which apps you would like to install:" --fb ${LINES} ${COLUMNS} ${NETLINES} "${SupportedAppDescr[@]}" 2>"${tempfile}"
+ fi
+ #TODO - Ask if the user wants the disable the other apps in .env
+
+ while read -r choice; do
+ run_script 'env_set' "$(echo "${choice^^}" | tr -d ' ')_ENABLED" 'true'
+ done < "${tempfile}"
+
+ rm -f "${tempfile}"
+}

ADD
scripts/menus/config_folder_set.sh
+#!/bin/bash
+set -euo pipefail
+IFS=$'\n\t'
+
+config_folder_set() {
+ if [[ ${CI:-} != true ]] && [[ ${TRAVIS:-} != true ]] && (whiptail --title "Configs Location" --fb --yesno \
+ "The default place for config files is: ${DETECTED_HOMEDIR}/.docker/config\\nThis will be passed into the applications.\\n\\nWould you like to accept this?" 12 78); then
+
+ #TODO - Check if the folder exists?
+ #TODO - Set permissions on the folder?
+ run_script 'env_set' 'DOCKERCONFDIR' "${DETECTED_HOMEDIR}/.docker/config"
+ else
+ run_menu 'input_prompt' 'DOCKERCONFDIR' "${DETECTED_HOMEDIR}/.docker/config"
+ fi
+}

ADD
scripts/menus/download_folder_set.sh
+#!/bin/bash
+set -euo pipefail
+IFS=$'\n\t'
+
+download_folder_set() {
+ if [[ ${CI:-} != true ]] && [[ ${TRAVIS:-} != true ]] && (whiptail --title "Dowloads Location" --fb --yesno \
+ "The default place for download files is: ${DETECTED_HOMEDIR}/Downloads\\nThis will be passed into the applications.\\n\\nWould you like to accept this?" 12 78); then
+
+ #TODO - Should we check if the folder exists?
+ #TODO - Should we set permissions on the folder?
+ run_script 'env_set' 'DOWNLOADSDIR' "${DETECTED_HOMEDIR}/Downloads"
+ else
+ run_menu 'input_prompt' 'DOWNLOADSDIR' "${DETECTED_HOMEDIR}/Downloads"
+ fi
+}

ADD
scripts/menus/input_prompt.sh
+#!/bin/bash
+set -euo pipefail
+IFS=$'\n\t'
+
+input_prompt() {
+ local SET_VAR
+ SET_VAR=${1:-}
+ local NEW_VAL
+ NEW_VAL=${2:-}
+ local INPUT
+ if [[ ${CI:-} != true ]] && [[ ${TRAVIS:-} != true ]]; then
+ INPUT=$(whiptail --inputbox "What would you like to set ${SET_VAR} to?" 12 78 "${NEW_VAL}" --fb --title "Set folder" 3>&1 1>&2 2>&3)
+ else
+ INPUT="${2}"
+ fi
+
+ if [[ -d ${INPUT} ]]; then
+ run_script 'env_set' "${SET_VAR}" "${INPUT}"
+ else
+ whiptail --title "Error" --msgbox "${INPUT} is not a valid path. Please try again." --fb 9 78
+ input_prompt "${SET_VAR}" "${NEW_VAL}"
+ fi
+}

ADD
scripts/menus/media_folders_set.sh
+#!/bin/bash
+set -euo pipefail
+IFS=$'\n\t'
+
+media_folders_set() {
+ if [[ ${CI:-} != true ]] && [[ ${TRAVIS:-} != true ]] && (whiptail --title "Media Locations" --fb --yesno \
+ "The default place for Media files is:\\n${DETECTED_HOMEDIR}/Books\\n${DETECTED_HOMEDIR}/Movies\\n${DETECTED_HOMEDIR}/Music\\n${DETECTED_HOMEDIR}/TV\\n\\nThis will be passed into the applications.\\n\\nWould you like to accept this?" 17 78); then
+
+ #TODO - Should we check if the folder exists?
+ #TODO - Should we set permissions on the folder?
+ run_script 'env_set' 'MEDIADIR_BOOKS' "${DETECTED_HOMEDIR}/Books"
+ run_script 'env_set' 'MEDIADIR_MOVIES' "${DETECTED_HOMEDIR}/Movies"
+ run_script 'env_set' 'MEDIADIR_MUSIC' "${DETECTED_HOMEDIR}/Music"
+ run_script 'env_set' 'MEDIADIR_TV' "${DETECTED_HOMEDIR}/TV"
+ else
+ run_menu 'input_prompt' 'MEDIADIR_BOOKS' "${DETECTED_HOMEDIR}/Books"
+ run_menu 'input_prompt' 'MEDIADIR_MOVIES' "${DETECTED_HOMEDIR}/Movies"
+ run_menu 'input_prompt' 'MEDIADIR_MUSIC' "${DETECTED_HOMEDIR}/Music"
+ run_menu 'input_prompt' 'MEDIADIR_TV' "${DETECTED_HOMEDIR}/TV"
+ fi
+}

ADD
scripts/menus/menu_main.sh
+#!/bin/bash
+set -euo pipefail
+IFS=$'\n\t'
+
+menu_main() {
+ local LINES
+ LINES=$(stty size | cut '-d ' -f1)
+ LINES=$((LINES<14?LINES:14))
+
+ local COLUMNS
+ COLUMNS=$(stty size | cut '-d ' -f2)
+ COLUMNS=$((COLUMNS<70?COLUMNS:70))
+
+ local NETLINES
+ NETLINES=$((LINES<4?LINES:4))
+
+ local MAINCHOICE
+ MAINCHOICE=$(whiptail --title "DockSTARTer" \
+ --menu "What would you like to do?" \
+ --fb --cancel-button "Exit" \
+ ${LINES} ${COLUMNS} ${NETLINES} \
+ "Configure Apps" "Setup and start applications" \
+ "Install Dependencies" "Latest version of Docker and Docker-Compose" \
+ "Update DockStarter" "Get the latest version of DockSTARTer" 3>&1 1>&2 2>&3)
+
+ case "${MAINCHOICE}" in
+ "Configure Apps")
+ run_script 'ui_config'
+ ;;
+ "Install Dependencies")
+ run_script 'ui_install'
+ ;;
+ "Update DockStarter")
+ run_script 'ui_update'
+ ;;
+ *)
+ error "Invalid Option"
+ ;;
+ esac
+}

ADD
scripts/menus/timezone_set.sh
+#!/bin/bash
+set -euo pipefail
+IFS=$'\n\t'
+
+timezone_set() {
+ # Get the current TimeZone and ask if its ok or they want to change it.
+ local CURRENTTIMEZONE
+ CURRENTTIMEZONE="$(cat /etc/timezone)"
+
+ if [[ ${CI:-} == true ]] && [[ ${TRAVIS:-} == true ]]; then
+ run_script 'env_set' 'TZ' "${CURRENTTIMEZONE}"
+ else
+ whiptail --title "Time Zone" --fb --yesno --yes-button "OK" --no-button "Cancel" \
+ "Your Current Time Zone is: ${CURRENTTIMEZONE} \\nThis will be passed into the applications.\\n\\nIf this is incorrect cancel now and change your system time zone!" 12 78
+
+ run_script 'env_set' 'TZ' "${CURRENTTIMEZONE}"
+ fi
+}

ADD
scripts/menus/user_group_set.sh
+#!/bin/bash
+set -euo pipefail
+IFS=$'\n\t'
+
+user_group_set() {
+ if [[ ${CI:-} == true ]] && [[ ${TRAVIS:-} == true ]]; then
+ run_script 'env_set' 'PUID' "${DETECTED_PUID}"
+ run_script 'env_set' 'PGID' "${DETECTED_PGID}"
+ else
+ whiptail --title "User and Group" --fb --yesno --yes-button "OK" --no-button "Cancel" \
+ "The detected User is: ${DETECTED_UNAME}\\nThe detected Group is: ${DETECTED_UGROUP}\\n\\nThis will be passed into the applications.\\n\\nPlease cancel if this is incorrect or adjust .env file manually after." 14 78
+
+ run_script 'env_set' 'PUID' "${DETECTED_PUID}"
+ run_script 'env_set' 'PGID' "${DETECTED_PGID}"
+ fi
+}

MODIFY
scripts/run_apt.sh
scripts/run_apt.sh
@@ -10,7 +10,7 @@ run_apt() {
apt-get -y dist-upgrade > /dev/null 2>&1
fi
info "Installing dependencies."
- apt-get -qq install curl git grep sed apt-transport-https > /dev/null 2>&1
+ apt-get -qq install curl git grep sed apt-transport-https whiptail > /dev/null 2>&1
info "Removing unused packages."
apt-get -y autoremove > /dev/null 2>&1
info "Cleaning up unused packages."

ADD
scripts/ui_config.sh
+#!/bin/bash
+set -euo pipefail
+IFS=$'\n\t'
+
+ui_config() {
+ run_script 'env_create' menu
+ run_menu 'application_selector'
+ run_menu 'timezone_set'
+ run_menu 'user_group_set'
+ run_menu 'config_folder_set'
+ run_menu 'download_folder_set'
+ run_menu 'media_folders_set'
+ run_script 'generate_yml'
+ run_script 'run_compose' menu
+}

ADD
scripts/ui_install.sh
+#!/bin/bash
+set -euo pipefail
+IFS=$'\n\t'
+
+ui_install() {
+ run_script 'run_apt'
+ run_script 'install_yq' force
+ run_script 'install_docker' force
+ run_script 'install_machine_completion'
+ run_script 'install_compose' force
+ run_script 'install_compose_completion'
+ run_script 'setup_docker_group'
+ run_script 'enable_docker_systemd'
+ run_script 'request_reboot' menu
+}

ADD
scripts/ui_update.sh
+#!/bin/bash
+set -euo pipefail
+IFS=$'\n\t'
+
+ui_update() {
+ run_script 'update_self' menu
+ run_script 'run_apt'
+ run_script 'install_yq' force
+ run_script 'install_docker' force
+ run_script 'install_machine_completion'
+ run_script 'install_compose' force
+ run_script 'install_compose_completion'
+}

GUI menus to control install and maintenance (#108)