From 56414871500ed05a13ea7702c1915762e58e7b14 Mon Sep 17 00:00:00 2001 From: PiJARR <60171758+pijarr@users.noreply.github.com> Date: Mon, 1 Jan 2024 16:12:50 +1000 Subject: [PATCH] Update setup.sh Minor permission updates and code cleanup, added qbittorrent-nox install option. --- setup.sh | 340 ++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 246 insertions(+), 94 deletions(-) diff --git a/setup.sh b/setup.sh index 0f814bb..06bf83e 100644 --- a/setup.sh +++ b/setup.sh @@ -4,7 +4,7 @@ clear ### SET GLOBAL VARIABLES ### TEMPDIR="/tmp/pijarr" -APPLIST="jackett sonarr lidarr radarr readarr prowlarr bazarr" +APPLIST="jackett sonarr lidarr radarr readarr prowlarr bazarr qbittorrent-nox" # Set terminal global variable for colors if supported. if [ -t 1 ]; then @@ -27,17 +27,16 @@ else RESET="" fi - # Temporary directory for application sources make_temp_dir() { task_start "Creating temporary directory ${TEMPDIR}..." - mkdir -p "${TEMPDIR}" 2> /dev/null + mkdir -p "${TEMPDIR}" 2>/dev/null check_result } remove_temp_dir() { task_start "Removing temporary directory and files ${TEMPDIR}..." - rm -Rf "${TEMPDIR}" 2> /dev/null + rm -Rf "${TEMPDIR}" 2>/dev/null check_result } @@ -111,9 +110,9 @@ fi if command -v lsb_release >/dev/null 2>&1; then dist=$(lsb_release -d --short) - osInfo="${dist}" + osInfo="${dist}" fi - if $(command -v uname) >/dev/null 2>&1; then +if $(command -v uname) >/dev/null 2>&1; then arch=$(uname -m) kernel=$(uname -r) kname=$(uname -s) @@ -131,28 +130,36 @@ task_info "Detected: ${osInfo} ${kernelInfo}" systemInfo="${cpuBoardInfo} ${kname} ${osInfo} ${kernelInfo} ${archInfo}" case "${systemInfo}" in - *x86_64* | *X86_64* | *amd64* | *AMD64* ) task_pass "Detected: x86 64-Bit Architecture$(tput el)" - JACKETT_ARCH="AMDx64" - SERVARR_ARCH="x64" ;; +*x86_64* | *X86_64* | *amd64* | *AMD64*) + task_pass "Detected: x86 64-Bit Architecture$(tput el)" + JACKETT_ARCH="AMDx64" + SERVARR_ARCH="x64" + ;; esac case "${systemInfo}" in - *aarch64* | *AARCH64* | *arm64* | *ARM64* | *armv8* | *ARMV8* ) task_pass "Detected: ARM 64-Bit Architecture$(tput el)" - JACKETT_ARCH="ARM64" - SERVARR_ARCH="arm64" ;; +*aarch64* | *AARCH64* | *arm64* | *ARM64* | *armv8* | *ARMV8*) + task_pass "Detected: ARM 64-Bit Architecture$(tput el)" + JACKETT_ARCH="ARM64" + SERVARR_ARCH="arm64" + ;; esac case "${systemInfo}" in - *aarch32* | *AARCH32* | *arm32* | *ARM32* | *armv7l* | *ARMV7L* ) task_pass "Detected: ARM 32-Bit Architecture$(tput el)" - JACKETT_ARCH="ARM32" - SERVARR_ARCH="arm" ;; +*aarch32* | *AARCH32* | *arm32* | *ARM32* | *armv7l* | *ARMV7L*) + task_pass "Detected: ARM 32-Bit Architecture$(tput el)" + JACKETT_ARCH="ARM32" + SERVARR_ARCH="arm" + ;; esac case "${systemInfo}" in - *linux* | *Linux* | *LINUX*) task_pass "Detected: Linux based OS$(tput el)" ;; - *) task_fail "Linux required. Not detected. Exiting...$(tput el)" - echo "" - exit 1 ;; +*linux* | *Linux* | *LINUX*) task_pass "Detected: Linux based OS$(tput el)" ;; +*) + task_fail "Linux required. Not detected. Exiting...$(tput el)" + echo "" + exit 1 + ;; esac ### END CHECK SYSTEM REQUIREMENTS AND ARCHITECTURE ### @@ -174,12 +181,14 @@ prowlarr_src_url="http://prowlarr.servarr.com/v1/update/master/updatefile?os=lin readarr_src_url="http://readarr.servarr.com/v1/update/develop/updatefile?os=linux&runtime=netcore&arch=${SERVARR_ARCH}" sonarr_src_url="https://services.sonarr.tv/v1/download/main/latest?version=3&os=linux" bazarr_src_url="https://github.com/morpheus65535/bazarr/releases/latest/download/bazarr.zip" +qbittorrent_nox_src_url="Not applicable. Installed via apt." check_sources() { task_info "Application Installation Source URLs" for app in ${APPLIST}; do - src_url=${app}\_src_url - src_url=$(eval echo \$"$src_url") + app_var_name=$(echo "${app}" | tr '-' '_') # Replace hyphens with underscores + src_url_var="${app_var_name}_src_url" + src_url=$(eval echo \$"$src_url_var") task_info "${app} src: ${src_url}" done } @@ -221,15 +230,15 @@ pkg_updates() { apt update apt upgrade -y apt --fix-broken install -y - apt autoclean -y 2> /dev/null - apt autoremove -y 2> /dev/null + apt autoclean -y 2>/dev/null + apt autoremove -y 2>/dev/null } # Function to check if packages are installed and install them if they are not found. pkg_install() { for pkg in "${@}"; do task_start "Checking for required package > ${pkg}" - pkgStatus=$(dpkg -s "${pkg}" 2> /dev/null) + pkgStatus=$(dpkg -s "${pkg}" 2>/dev/null) result=$? if [ "${result}" -ne 0 ]; then task_warn "Package ${pkg} not installed.$(tput el)" @@ -241,6 +250,21 @@ pkg_install() { done } +pkg_remove() { + for pkg in "${@}"; do + task_start "Checking for required package > ${pkg}" + pkgStatus=$(dpkg -s "${pkg}" 2>/dev/null) + result=$? + if [ "${result}" -eq 0 ]; then + task_warn "Package ${pkg} installed.$(tput el)" + task_info "Removing ${pkg}..." + apt remove -y "${pkg}" + else + task_pass "Package ${pkg} not installed.$(tput el)" + fi + done +} + # Function to install all the dependencies including packages and server keys. setup_dependencies() { task_info "Installing required dependencies..." @@ -322,7 +346,7 @@ setup_app() { file_extension="tar.gz" fi app_user="${app_name}" - app_group="media" + app_group="pijarr" src_url=${app_name}\_src_url src_url=$(eval echo \$"$src_url") new_file="${app_name}.${file_extension}" @@ -331,19 +355,27 @@ setup_app() { if id "${app_user}" >/dev/null 2>&1; then task_pass "User account for ${app_user} already exists." else - useradd -s /usr/sbin/nologin -d "/var/lib/${app_user}" -r -m -U "${app_user}" 2> /dev/null + useradd -s /usr/sbin/nologin -d "/var/lib/${app_user}" -r -m -U "${app_user}" 2>/dev/null check_result fi task_start "Adding ${app_group} service group..." if getent group "${app_group}" >/dev/null 2>&1; then task_pass "Group ${app_group} already exists." else - groupadd "${app_group}" 2> /dev/null + groupadd "${app_group}" 2>/dev/null + check_result + fi + # Determine the actual username (not sudo or root) + actual_user="${SUDO_USER:-$USER}" + if id "$actual_user" | grep -qE "\b${app_group}\b"; then + task_pass "User $actual_user is already a member of the ${app_group} group." + else + usermod -a -G "${app_group}" "$actual_user" check_result fi task_info "Download source URL: ${src_url}" wget -O "${temp_dir}"/"${new_file}" -q --show-progress --progress=bar:force "${src_url}" 2>&1 && - task_pass "Source file downloaded. SHA256: $(sha256sum ${temp_dir}/${new_file} | cut -d ' ' -f 1)$(tput el)" + task_pass "Source file downloaded. SHA256: $(sha256sum ${temp_dir}/${new_file} | cut -d ' ' -f 1)$(tput el)" task_info "Extracting ${temp_dir}/${new_file} to ${app_opt_path}..." if [ "${app_name}" = "bazarr" ]; then unzip "${temp_dir}/${new_file}" -d "${app_opt_path}" @@ -369,21 +401,21 @@ setup_app() { mkdir -p "${app_config_path}" check_result task_start "Setting user permissions on ${app_lib_path}..." - chown -R "${app_user}":"${app_group}" "${app_lib_path}" && - check_result + chown -R "${app_user}":"${app_group}" "${app_lib_path}" && + check_result # Begin writting out the service configuration file. Minor change needed for Jackett. if [ "${app_name}" = "jackett" ]; then app_exec="${app_opt_path}/${app_name}_launcher.sh" elif [ "${app_name}" = "sonarr" ]; then app_exec="/usr/bin/mono --debug ${app_opt_path}/$(title_case ${app_name}).exe -nobrowser" - elif [ "${app_name}" = "bazarr" ]; then + elif [ "${app_name}" = "bazarr" ]; then app_exec="${app_opt_path}/venv/bin/python ${app_opt_path}/bazarr.py" else app_exec="${app_opt_path}/$(title_case ${app_name})" fi task_start "Writing service configuration file /etc/systemd/system/${app_name}.service..." - tee /etc/systemd/system/"${app_name}".service 1>/dev/null </dev/null < /dev/null + systemctl daemon-reload 2>/dev/null check_result task_start "Enabling auto start for ${app_name} service..." - systemctl enable "${app_name}" 2> /dev/null + systemctl enable "${app_name}" 2>/dev/null check_result task_start "Starting ${app_name} service..." - systemctl start "${app_name}" 2> /dev/null + systemctl start "${app_name}" 2>/dev/null check_result check_service ${app_name} task_info "Completed install for ${app_name}\n" @@ -434,11 +466,11 @@ remove_app() { check_continue task_info "Deleting existing settings or files for ${app}..." task_start "Stopping ${app} service..." - systemctl stop "${app}" 2> /dev/null + systemctl stop "${app}" 2>/dev/null task_pass task_start "Removing ${app_opt_path}..." if [ "${app_opt_path}" != "/opt" ] && [ "${app_opt_path}" != "/opt/" ]; then - rm -rf "${app_opt_path}" 2> /dev/null + rm -rf "${app_opt_path}" 2>/dev/null task_pass else task_skip "Skipping removal of default /opt/ directory." @@ -446,23 +478,115 @@ remove_app() { task_start "Removing ${app_lib_path}..." if [ "${app_lib_path}" != "/var/lib" ] && [ "${app_lib_path}" != "/var/lib/" ]; then - rm -rf "${app_lib_path}" 2> /dev/null + rm -rf "${app_lib_path}" 2>/dev/null task_pass else task_skip "Skipping removal of default /var/lib/ directory." fi task_start "Removing service config /etc/systemd/system/${app}.service..." - rm "/etc/systemd/system/${app}.service"* 2> /dev/null + rm "/etc/systemd/system/${app}.service"* 2>/dev/null task_pass task_info "Removing ${app} service user account..." - deluser "${app}" 2> /dev/null + deluser "${app}" 2>/dev/null task_start "Reloading systemctl daemon..." - systemctl daemon-reload 2> /dev/null + systemctl daemon-reload 2>/dev/null task_pass task_info "${app} deleted.\n" done } +setup_qbittorrent_nox() { + date_stamp="$(date '+%Y-%m-%d %H%M')" + app_name="qbittorrent-nox" + app_user="${app_name}" + app_group="pijarr" + task_info "Commencing install for ${app_name}..." + task_start "Adding ${app_user} service user..." + if id "${app_user}" >/dev/null 2>&1; then + task_pass "User account for ${app_user} already exists." + else + useradd -s /usr/sbin/nologin -d "/var/lib/${app_user}" -r -m -U "${app_user}" 2>/dev/null + check_result + fi + task_start "Adding ${app_group} service group..." + if getent group "${app_group}" >/dev/null 2>&1; then + task_pass "Group ${app_group} already exists." + else + groupadd "${app_group}" 2>/dev/null + check_result + fi + # Determine the actual username (not sudo or root) + actual_user="${SUDO_USER:-$USER}" + if id "$actual_user" | grep -qE "\b${app_group}\b"; then + task_pass "User $actual_user is already a member of the ${app_group} group." + else + usermod -a -G "${app_group}" "$actual_user" + check_result + fi + task_info "Installing ${app_name} package..." + pkg_install qbittorrent-nox + task_start "Writing service configuration file /etc/systemd/system/${app_name}.service..." + tee /etc/systemd/system/"${app_name}".service 1>/dev/null </dev/null + check_result + task_start "Enabling auto start for ${app_name} service..." + systemctl enable "${app_name}" 2>/dev/null + check_result + task_start "Starting ${app_name} service..." + systemctl start "${app_name}" 2>/dev/null + check_result + check_service ${app_name} + task_info "Completed install for ${app_name}\n" + task_info "Default qBittorrent username: admin password: adminadmin" + task_info "Default qBittorrent save directory /var/lib/qbittorrent-nox/Downloads" +} + +remove_qbittorrent_nox() { + app_name="qbittorrent-nox" + app_lib_path="/var/lib/${app_name}" + task_warn "You are about to delete all settings and files for ${app_name}..." + check_continue + task_info "Deleting existing settings or files for ${app_name}..." + task_start "Stopping ${app_name} service..." + systemctl stop "${app_name}" 2>/dev/null + task_pass + task_start "Removing service config /etc/systemd/system/${app_name}.service..." + rm "/etc/systemd/system/${app_name}.service"* 2>/dev/null + task_pass + pkg_remove qbittorrent-nox + task_info "Removing ${app} service user account..." + deluser "${app_name}" 2>/dev/null + task_start "Removing ${app_lib_path}..." + if [ "${app_lib_path}" != "/var/lib" ] && [ "${app_lib_path}" != "/var/lib/" ]; then + rm -rf "${app_lib_path}" 2>/dev/null + task_pass + else + task_skip "Skipping removal of default /var/lib/ directory." + fi + task_info "${app_name} deleted.\n" +} active_services() { task_info "Active Services" @@ -473,7 +597,6 @@ active_services() { done } - check_service() { task_start "Checking service status for ${1}..." if [ $(systemctl is-active "$1") = "active" ]; then @@ -485,20 +608,21 @@ check_service() { default_ports() { task_info "Default Application Ports" - task_info "Jackett: http://hostip:9117" - task_info "Sonarr: http://hostip:8989" - task_info "Lidarr: http://hostip:8686" - task_info "Radarr: http://hostip:7878" - task_info "Readarr: http://hostip:8787" - task_info "Prowlarr: http://hostip:9696" - task_info "Bazarr: http://hostip:6767" + task_info "Jackett: http://hostip:9117" + task_info "Sonarr: http://hostip:8989" + task_info "Lidarr: http://hostip:8686" + task_info "Radarr: http://hostip:7878" + task_info "Readarr: http://hostip:8787" + task_info "Prowlarr: http://hostip:9696" + task_info "Bazarr: http://hostip:6767" + task_info "qBittorrent-nox: http://hostip:8080" } # Display a list of menu items for selection -display_menu () { +display_menu() { clear banner_info - echo "==============" + echo "==============" echo " Menu Options " echo "==============" echo @@ -510,77 +634,105 @@ display_menu () { printf "6. Install readarr only\n" printf "7. Install prowlarr only\n" printf "8. Install bazarr only\n" - printf "\n9. Remove ALL (jackett sonarr lidarr radarr readarr prowlarr bazarr)\n" - printf "10. Remove jackett only\n" - printf "11. Remove sonarr only\n" - printf "12. Remove lidarr only\n" - printf "13. Remove radarr only\n" - printf "14. Remove readarr only\n" - printf "15. Remove prowlarr only\n" - printf "16. Remove bazarr only\n" - printf "\n17. Show active services\n" - printf "18. Show application default ports\n" - printf "19. Show application source urls\n" - printf "\n20. Exit\n" + printf "9. Install qBittorrent-nox (headless torrent client) only\n" + printf "\n10. Remove ALL (jackett sonarr lidarr radarr readarr prowlarr bazarr)\n" + printf "11. Remove jackett only\n" + printf "12. Remove sonarr only\n" + printf "13. Remove lidarr only\n" + printf "14. Remove radarr only\n" + printf "15. Remove readarr only\n" + printf "16. Remove prowlarr only\n" + printf "17. Remove bazarr only\n" + printf "18. Remove qbittorrent-nox only\n" + printf "\n19. Show active services\n" + printf "20. Show application default ports\n" + printf "21. Show application source urls\n" + printf "\n22. Exit\n" echo - printf " Enter option [1-20]: " + printf " Enter option [1-22]: " - while : - do - read choice - case ${choice} in - 1) setup_app jackett sonarr lidarr radarr readarr prowlarr bazarr + while :; do + read choice + case ${choice} in + 1) + setup_app jackett sonarr lidarr radarr readarr prowlarr bazarr ;; - 2) setup_app jackett + 2) + setup_app jackett ;; - 3) setup_app sonarr + 3) + setup_app sonarr ;; - 4) setup_app lidarr + 4) + setup_app lidarr ;; - 5) setup_app radarr + 5) + setup_app radarr ;; - 6) setup_app readarr + 6) + setup_app readarr ;; - 7) setup_app prowlarr + 7) + setup_app prowlarr ;; - 8) setup_app bazarr + 8) + setup_app bazarr ;; - 9) remove_app jackett sonarr lidarr radarr readarr prowlarr bazarr + 9) + setup_qbittorrent_nox ;; - 10) remove_app jackett + 10) + remove_app jackett sonarr lidarr radarr readarr prowlarr bazarr ;; - 11) remove_app sonarr + 11) + remove_app jackett ;; - 12) remove_app lidarr + 12) + remove_app sonarr ;; - 13) remove_app radarr + 13) + remove_app lidarr ;; - 14) remove_app readarr + 14) + remove_app radarr ;; - 15) remove_app prowlarr + 15) + remove_app readarr ;; - 16) remove_app bazarr + 16) + remove_app prowlarr ;; - 17) clear + 17) + remove_app bazarr + ;; + 18) + remove_qbittorrent_nox + ;; + 19) + clear active_services ;; - 18) clear + 20) + clear default_ports ;; - 19) clear + 21) + clear check_sources ;; - 20) printf "\nExiting...\n" + 22) + printf "\nExiting...\n" exit ;; - *) clear + *) + clear display_menu ;; - esac - printf "\nSelection [${choice}] completed.\n" - press_any_key - clear - display_menu + esac + printf "\nSelection [${choice}] completed.\n" + press_any_key + clear + display_menu done }