From 90d871bba5dee1f23ecb4af68aa55c226bc1b7dc Mon Sep 17 00:00:00 2001 From: MichaIng Date: Sun, 1 Dec 2024 17:49:16 +0100 Subject: [PATCH] v9.9 - DietPi-Software | frp: Inform about new toml config file and leave old ini as backup in place. Do not offer client inputs, if the config exists already (and is hence not generated anyway). Allow an empty token input, which is generally possible. Allow unattended installs, using both server and client as default, and applying default values to all inputs and menus. - DietPi-Globals | G_WHIP: Return default value for inputbox, checkbox and menu, if not interactive, but keep returning error code, so that it can be handled in parent script. Minor coding enhancements. - CI | DietPi-Software: Enable frp checks now that it can be installed unattended --- .github/workflows/dietpi-software.bash | 2 +- dietpi/dietpi-software | 76 +++++++++++----- dietpi/func/dietpi-globals | 118 +++++++++++-------------- 3 files changed, 107 insertions(+), 89 deletions(-) diff --git a/.github/workflows/dietpi-software.bash b/.github/workflows/dietpi-software.bash index 8dd83980c0..0c3383578a 100644 --- a/.github/workflows/dietpi-software.bash +++ b/.github/workflows/dietpi-software.bash @@ -204,7 +204,7 @@ Process_Software() 167) (( $arch < 3 )) || aSERVICES[i]='raspotify';; # 32-bit ARM fails with: "arm-binfmt-P: /usr/bin/librespot: Unable to find a guest_base to satisfy all guest address mapping requirements" #169) aSERVICES[i]='voice-recognizer';; "RuntimeError: This module can only be run on a Raspberry Pi!" 170) aCOMMANDS[i]='unrar -V';; - #171) aSERVICES[i]='frps frpc' aTCP[i]='7000 7400 7500';; Interactive install with service and ports depending on server/client/both choice + 171) aSERVICES[i]='frps frpc' aTCP[i]='7000 7400 7500';; 172) aSERVICES[i]='wg-quick@wg0' aUDP[i]='51820';; 174) aCOMMANDS[i]='gimp -v';; 176) aSERVICES[i]='mycroft';; diff --git a/dietpi/dietpi-software b/dietpi/dietpi-software index c2e229892e..e377c9b8f2 100755 --- a/dietpi/dietpi-software +++ b/dietpi/dietpi-software @@ -1509,7 +1509,6 @@ Available commands: aSOFTWARE_DESC[$software_id]='reverse proxy' aSOFTWARE_CATX[$software_id]=16 aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/advanced_networking/#frp' - aSOFTWARE_INTERACTIVE[$software_id]=1 # Home Automation #-------------------------------------------------------------------------------- @@ -6538,18 +6537,16 @@ _EOF_ G_EXEC cd frp_* - local choice_required= - while : - do - G_WHIP_MENU_ARRAY=( - 'Server' ': Use this machine as a server, with a public IP' - 'Client' ': Use this machine as a client, without a public IP' - 'Both' ': Run the reverse proxy only on this machine' - ) + # Mode choice + G_WHIP_MENU_ARRAY=( + 'Server' ': Use this machine as a server, with a public IP' + 'Client' ': Use this machine as a client, without a public IP' + 'Both' ': Run the reverse proxy only on this machine' + ) - G_WHIP_MENU "${choice_required}Please choose how you are going to run frp." && break - choice_required='[ERROR] A choice is required to finish the frp install.\n\n' - done + G_WHIP_NOCANCEL=1 + G_WHIP_DEFAULT_ITEM='Both' + G_WHIP_MENU 'Please choose how you are going to run frp:' local mode=$G_WHIP_RETURNED_VALUE G_EXEC mkdir -p /etc/frp @@ -6577,6 +6574,18 @@ RestartSec=5s [Install] WantedBy=multi-user.target _EOF_ + # Pre-v9.9: Inform about config file migration + if [[ -f '/etc/frp/frps.ini' ]] + then + G_WHIP_MSG '[WARNING] New toml config file will be generated +\nfrp deprecated the ini format for its config files, hence /etc/frp/frps.toml will be generated and used from now on. +\nAn automated conversion is not possible and hence need to be done manually, if you did changes. A backup of the ini config it kept in place: +- /etc/frp/frps.ini.bak +\nA full overview of all config keys can be found here: +- https://github.com/fatedier/frp/blob/dev/conf/frps_full_example.toml' + G_EXEC mv /etc/frp/frps.ini{,.bak} + fi + # Pre-create config file to turn on dashboard token=$(openssl rand -hex 15) [[ -f '/etc/frp/frps.toml' ]] || cat << _EOF_ > /etc/frp/frps.toml @@ -6617,22 +6626,39 @@ RestartSec=5s [Install] WantedBy=multi-user.target _EOF_ - local server_addr='127.0.0.1' server_port=7000 - if [[ $G_WHIP_RETURNED_VALUE == 'Client' ]] + # Pre-v9.9: Inform about config file migration + if [[ -f '/etc/frp/frpc.ini' ]] then - G_WHIP_DEFAULT_ITEM="$server_addr:$server_port" - G_WHIP_INPUTBOX_REGEX='^[0-9.:]+$' - G_WHIP_INPUTBOX_REGEX_TEXT='be a valid IP address, optionally with appended network port number, like "192.168.1.100:7000"' - G_WHIP_INPUTBOX 'Please enter the IP address of your frp server, optionally including port (default 7000):' - server_addr=${G_WHIP_RETURNED_VALUE%:*} - [[ $G_WHIP_RETURNED_VALUE =~ : ]] && server_port=${G_WHIP_RETURNED_VALUE##*:} - - G_WHIP_INPUTBOX 'Please enter the authentication token of your frp server:' - token=$G_WHIP_RETURNED_VALUE + G_WHIP_MSG '[WARNING] New toml config file will be generated +\nfrp deprecated the ini format for its config files, hence /etc/frp/frpc.toml will be generated and used from now on. +\nAn automated conversion is not possible and hence need to be done manually, if you did changes. A backup of the ini config it kept in place: +- /etc/frp/frpc.ini.bak +\nA full overview of all config keys can be found here: +- https://github.com/fatedier/frp/blob/dev/conf/frpc_full_example.toml' + G_EXEC mv /etc/frp/frpc.ini{,.bak} fi # Pre-create config file to turn on admin UI - [[ -f '/etc/frp/frpc.toml' ]] || cat << _EOF_ > /etc/frp/frpc.toml + if [[ ! -f '/etc/frp/frpc.toml' ]] + then + local server_addr='127.0.0.1' server_port=7000 + if [[ $G_WHIP_RETURNED_VALUE == 'Client' ]] + then + G_WHIP_NOCANCEL=1 + G_WHIP_DEFAULT_ITEM="$server_addr:$server_port" + G_WHIP_INPUTBOX_REGEX='^[0-9.:]+$' + G_WHIP_INPUTBOX_REGEX_TEXT='be a valid IP address, optionally with appended network port number, like "192.168.1.100:7000"' + G_WHIP_INPUTBOX 'Please enter the IP address of your frp server, optionally including port (default 7000):' + server_addr=${G_WHIP_RETURNED_VALUE%:*} + [[ $G_WHIP_RETURNED_VALUE =~ : ]] && server_port=${G_WHIP_RETURNED_VALUE##*:} + + G_WHIP_NOCANCEL=1 + G_WHIP_INPUTBOX_REGEX='*' + G_WHIP_INPUTBOX 'Please enter the authentication token of your frp server:' + token=$G_WHIP_RETURNED_VALUE + fi + + cat << _EOF_ > /etc/frp/frpc.toml serverAddr = "$server_addr" serverPort = $server_port @@ -6644,6 +6670,8 @@ webServer.password = "$GLOBAL_PW" auth.method = "token" auth.token = "$token" _EOF_ + fi + G_EXEC chmod 0660 /etc/frp/frpc.toml G_EXEC chown root:frp /etc/frp/frpc.toml aENABLE_SERVICES+=('frpc') diff --git a/dietpi/func/dietpi-globals b/dietpi/func/dietpi-globals index 36a6efd12c..4136e15a8e 100644 --- a/dietpi/func/dietpi-globals +++ b/dietpi/func/dietpi-globals @@ -483,8 +483,8 @@ $grey───────────────────────── local whip_chars_text=$(( $WHIP_SIZE_X - 4 )) # Due to internal margins, the available width is 4 characters smaller WHIP_SCROLLTEXT= # Add "--scrolltext" automatically if text height exceeds max available - Process_Line(){ - + Process_Line() + { local split line=$1 # Split line by "\n" newline escape sequences, the only one which is interpreted by whiptail, in a strict way: "\\n" still creates a newline, hence the sequence cannot be escaped! @@ -504,27 +504,25 @@ $grey───────────────────────── (( whip_lines_text += 1 + ( ${#line} - 1 ) / $whip_chars_text )) # Stop counting if required size exceeds screen already (( $whip_lines_text <= $WHIP_SIZE_Y )) || return 1 - } # - WHIP_MESSAGE - if [[ $WHIP_ERROR$WHIP_MESSAGE ]]; then - + if [[ $WHIP_ERROR$WHIP_MESSAGE ]] + then while read -r line; do Process_Line "$line" || break; done <<< "$WHIP_ERROR$WHIP_MESSAGE" # - WHIP_TEXTFILE - elif [[ $WHIP_TEXTFILE ]]; then - + elif [[ $WHIP_TEXTFILE ]] + then while read -r line; do Process_Line "$line" || break; done < "$WHIP_TEXTFILE" - fi unset -f Process_Line # Process menu and checklist # - G_WHIP_MENU - if [[ $input_mode == 2 ]]; then - + if [[ $input_mode == 2 ]] + then # Requires 1 additional line for text ((whip_lines_text++)) @@ -554,8 +552,8 @@ $grey───────────────────────── done # - G_WHIP_CHECKLIST - elif [[ $input_mode == 3 ]]; then - + elif [[ $input_mode == 3 ]] + then # Lines required for checklist: ( ${#array} + 2 ) to round up single+double array entries WHIP_SIZE_Z=$(( ( ${#G_WHIP_CHECKLIST_ARRAY[@]} + 2 ) / 3 )) @@ -580,44 +578,37 @@ $grey───────────────────────── G_WHIP_CHECKLIST_ARRAY[$i]+='●' done - fi # Adjust sizes to fit content # - G_WHIP_MENU/G_WHIP_CHECKLIST needs to hold text + selection field (WHIP_SIZE_Z) - if [[ $input_mode == [23] ]]; then - + if [[ $input_mode == [23] ]] + then # If required lines would exceed screen, reduce WHIP_SIZE_Z - if (( $whip_lines_text + $WHIP_SIZE_Z > $WHIP_SIZE_Y )); then - + if (( $whip_lines_text + $WHIP_SIZE_Z > $WHIP_SIZE_Y )) + then WHIP_SIZE_Z=$(( $WHIP_SIZE_Y - $whip_lines_text )) # Assure at least 2 lines to have the selection field scroll bar identifiable - if (( $WHIP_SIZE_Z < 2 )); then - + if (( $WHIP_SIZE_Z < 2 )) + then WHIP_SIZE_Z=2 # Since text is partly hidden now, add text scroll ability and info to backtitle WHIP_SCROLLTEXT='--scrolltext' WHIP_BACKTITLE+=' | Use up/down buttons to scroll text' - fi # else reduce WHIP_SIZE_Y to hold all content else - WHIP_SIZE_Y=$(( $whip_lines_text + $WHIP_SIZE_Z )) - fi # - Everything else needs to hold text only - elif (( $whip_lines_text > $WHIP_SIZE_Y )); then - + elif (( $whip_lines_text > $WHIP_SIZE_Y )) + then WHIP_SCROLLTEXT='--scrolltext' WHIP_BACKTITLE+=' | Use up/down buttons to scroll text' - else - WHIP_SIZE_Y=$whip_lines_text - fi } @@ -627,17 +618,14 @@ $grey───────────────────────── { local WHIP_MESSAGE=$* - if [[ $G_INTERACTIVE == 1 ]]; then - + if [[ $G_INTERACTIVE == 1 ]] + then local WHIP_ERROR WHIP_BACKTITLE WHIP_SCROLLTEXT WHIP_SIZE_X WHIP_SIZE_Y G_WHIP_INIT # shellcheck disable=SC2086 whiptail ${G_PROGRAM_NAME:+--title "$G_PROGRAM_NAME"} --backtitle "$WHIP_BACKTITLE" --msgbox "$WHIP_MESSAGE" --ok-button "$G_WHIP_BUTTON_OK_TEXT" $WHIP_SCROLLTEXT "$WHIP_SIZE_Y" "$WHIP_SIZE_X" - else - G_DIETPI-NOTIFY 2 "$WHIP_MESSAGE" - fi G_WHIP_DESTROY @@ -650,30 +638,26 @@ $grey───────────────────────── { local result=0 - if [[ $G_INTERACTIVE == 1 ]]; then - + if [[ $G_INTERACTIVE == 1 ]] + then local WHIP_ERROR WHIP_MESSAGE WHIP_BACKTITLE WHIP_SCROLLTEXT WHIP_SIZE_X WHIP_SIZE_Y WHIP_TEXTFILE=$1 header='File viewer' [[ $log == 1 ]] && header='Log viewer' - if [[ -f $WHIP_TEXTFILE ]]; then - + if [[ -f $WHIP_TEXTFILE ]] + then G_WHIP_INIT # shellcheck disable=SC2086 whiptail --title "${G_PROGRAM_NAME:+$G_PROGRAM_NAME | }$header" --backtitle "$WHIP_BACKTITLE" --textbox "$WHIP_TEXTFILE" --ok-button "$G_WHIP_BUTTON_OK_TEXT" $WHIP_SCROLLTEXT "$WHIP_SIZE_Y" "$WHIP_SIZE_X" - else - result=1 WHIP_ERROR="[FAILED] File does not exist: $WHIP_TEXTFILE" G_WHIP_INIT # shellcheck disable=SC2086 whiptail --title "${G_PROGRAM_NAME:+$G_PROGRAM_NAME | }$header" --backtitle "$WHIP_BACKTITLE" --msgbox "$WHIP_ERROR" --ok-button "$G_WHIP_BUTTON_OK_TEXT" $WHIP_SCROLLTEXT "$WHIP_SIZE_Y" "$WHIP_SIZE_X" - fi - fi G_WHIP_DESTROY - return "$result" + return "${result:-1}" } # G_WHIP_YESNO "message" @@ -684,18 +668,17 @@ $grey───────────────────────── local result=1 default_no='--defaultno' [[ ${G_WHIP_DEFAULT_ITEM,,} == 'yes' || ${G_WHIP_DEFAULT_ITEM,,} == 'ok' ]] && result=0 default_no= - if [[ $G_INTERACTIVE == 1 ]]; then - + if [[ $G_INTERACTIVE == 1 ]] + then local WHIP_ERROR WHIP_BACKTITLE WHIP_SCROLLTEXT WHIP_SIZE_X WHIP_SIZE_Y WHIP_MESSAGE=$* G_WHIP_INIT # shellcheck disable=SC2086 whiptail ${G_PROGRAM_NAME:+--title "$G_PROGRAM_NAME"} --backtitle "$WHIP_BACKTITLE" --yesno "$WHIP_MESSAGE" --yes-button "$G_WHIP_BUTTON_OK_TEXT" --no-button "$G_WHIP_BUTTON_CANCEL_TEXT" "$default_no" $WHIP_SCROLLTEXT "$WHIP_SIZE_Y" "$WHIP_SIZE_X" result=$? - fi G_WHIP_DESTROY - return "$result" + return "${result:-1}" } # G_WHIP_INPUTBOX "message" @@ -707,26 +690,27 @@ $grey───────────────────────── local result=1 unset -v G_WHIP_RETURNED_VALUE # in case left from last G_WHIP - if [[ $G_INTERACTIVE == 1 ]]; then - + if [[ $G_INTERACTIVE == 1 ]] + then local WHIP_ERROR WHIP_BACKTITLE WHIP_SCROLLTEXT WHIP_SIZE_X WHIP_SIZE_Y WHIP_MESSAGE=$* NOCANCEL=() + G_WHIP_INPUTBOX_REGEX=${G_WHIP_INPUTBOX_REGEX:-'.'} + G_WHIP_INPUTBOX_REGEX_TEXT=${G_WHIP_INPUTBOX_REGEX_TEXT:-'not be empty'} [[ $G_WHIP_NOCANCEL == 1 ]] && NOCANCEL=('--nocancel') while : do G_WHIP_INIT - G_WHIP_INPUTBOX_REGEX=${G_WHIP_INPUTBOX_REGEX:-'.'} - G_WHIP_INPUTBOX_REGEX_TEXT=${G_WHIP_INPUTBOX_REGEX_TEXT:-'not be empty'} # shellcheck disable=SC2086 G_WHIP_RETURNED_VALUE=$(whiptail ${G_PROGRAM_NAME:+--title "$G_PROGRAM_NAME"} --backtitle "$WHIP_BACKTITLE" --inputbox "$WHIP_ERROR$WHIP_MESSAGE" --ok-button "$G_WHIP_BUTTON_OK_TEXT" --cancel-button "$G_WHIP_BUTTON_CANCEL_TEXT" "${NOCANCEL[@]}" $WHIP_SCROLLTEXT "$WHIP_SIZE_Y" "$WHIP_SIZE_X" "$G_WHIP_DEFAULT_ITEM" 3>&1 1>&2 2>&3-; echo $? > /tmp/.G_WHIP_INPUTBOX_RESULT) read -r result < /tmp/.G_WHIP_INPUTBOX_RESULT; rm -f /tmp/.G_WHIP_INPUTBOX_RESULT [[ $result == 0 && ! $G_WHIP_RETURNED_VALUE =~ $G_WHIP_INPUTBOX_REGEX ]] && { WHIP_ERROR="[FAILED] Input must $G_WHIP_INPUTBOX_REGEX_TEXT, please try again ...\n\n"; continue; } break done - + else + G_WHIP_RETURNED_VALUE=$G_WHIP_DEFAULT_ITEM fi G_WHIP_DESTROY - return "$result" + return "${result:-1}" } # G_WHIP_PASSWORD "message" @@ -738,8 +722,8 @@ $grey───────────────────────── local return_value=1 unset -v result # in case left from last call - if [[ $G_INTERACTIVE == 1 ]]; then - + if [[ $G_INTERACTIVE == 1 ]] + then local WHIP_ERROR WHIP_BACKTITLE WHIP_SCROLLTEXT WHIP_SIZE_X WHIP_SIZE_Y WHIP_MESSAGE=$* while : do @@ -753,11 +737,10 @@ $grey───────────────────────── return_value=0 break done - fi G_WHIP_DESTROY - return "$return_value" + return "${return_value:-1}" } # G_WHIP_MENU "message" @@ -768,19 +751,24 @@ $grey───────────────────────── local result=1 unset -v G_WHIP_RETURNED_VALUE # in case left from last call - [[ $G_INTERACTIVE == 1 ]] && until [[ $G_WHIP_RETURNED_VALUE ]] # Stay in menu if empty option was selected (separator line) - do + if [[ $G_INTERACTIVE == 1 ]] + then local WHIP_ERROR WHIP_BACKTITLE WHIP_SCROLLTEXT WHIP_SIZE_X WHIP_SIZE_Y WHIP_SIZE_Z WHIP_MESSAGE=$* NOCANCEL=() [[ $G_WHIP_NOCANCEL == 1 ]] && NOCANCEL=('--nocancel') - G_WHIP_INIT 2 - # shellcheck disable=SC2086 - G_WHIP_RETURNED_VALUE=$(whiptail ${G_PROGRAM_NAME:+--title "$G_PROGRAM_NAME"} --backtitle "$WHIP_BACKTITLE" --menu "$WHIP_MESSAGE" --ok-button "$G_WHIP_BUTTON_OK_TEXT" --cancel-button "$G_WHIP_BUTTON_CANCEL_TEXT" "${NOCANCEL[@]}" --default-item "$G_WHIP_DEFAULT_ITEM" $WHIP_SCROLLTEXT "$WHIP_SIZE_Y" "$WHIP_SIZE_X" "$WHIP_SIZE_Z" -- "${G_WHIP_MENU_ARRAY[@]}" 3>&1 1>&2 2>&3-; echo $? > /tmp/.WHIP_MENU_RESULT) - read -r result < /tmp/.WHIP_MENU_RESULT; rm -f /tmp/.WHIP_MENU_RESULT - [[ ${result:=1} == 0 ]] || break # Exit loop in case of cancel button selection or error or if .WHIP_MENU_RESULT could not be created - done + until [[ $G_WHIP_RETURNED_VALUE ]] # Stay in menu if empty option was selected (separator line) + do + G_WHIP_INIT 2 + # shellcheck disable=SC2086 + G_WHIP_RETURNED_VALUE=$(whiptail ${G_PROGRAM_NAME:+--title "$G_PROGRAM_NAME"} --backtitle "$WHIP_BACKTITLE" --menu "$WHIP_MESSAGE" --ok-button "$G_WHIP_BUTTON_OK_TEXT" --cancel-button "$G_WHIP_BUTTON_CANCEL_TEXT" "${NOCANCEL[@]}" --default-item "$G_WHIP_DEFAULT_ITEM" $WHIP_SCROLLTEXT "$WHIP_SIZE_Y" "$WHIP_SIZE_X" "$WHIP_SIZE_Z" -- "${G_WHIP_MENU_ARRAY[@]}" 3>&1 1>&2 2>&3-; echo $? > /tmp/.WHIP_MENU_RESULT) + read -r result < /tmp/.WHIP_MENU_RESULT; rm -f /tmp/.WHIP_MENU_RESULT + [[ ${result:=1} == 0 ]] || break # Exit loop in case of cancel button selection or error or if .WHIP_MENU_RESULT could not be created + done + else + G_WHIP_RETURNED_VALUE=$G_WHIP_DEFAULT_ITEM + fi G_WHIP_DESTROY - return "$result" + return "${result:-1}" } # G_WHIP_CHECKLIST "message" @@ -800,6 +788,8 @@ $grey───────────────────────── G_WHIP_RETURNED_VALUE=$(whiptail ${G_PROGRAM_NAME:+--title "$G_PROGRAM_NAME"} --backtitle "$WHIP_BACKTITLE | Use spacebar to toggle selection" --checklist "$WHIP_MESSAGE" --separate-output --ok-button "$G_WHIP_BUTTON_OK_TEXT" --cancel-button "$G_WHIP_BUTTON_CANCEL_TEXT" "${NOCANCEL[@]}" --default-item "$G_WHIP_DEFAULT_ITEM" $WHIP_SCROLLTEXT "$WHIP_SIZE_Y" "$WHIP_SIZE_X" "$WHIP_SIZE_Z" -- "${G_WHIP_CHECKLIST_ARRAY[@]}" 3>&1 1>&2 2>&3-; echo $? > /tmp/.WHIP_CHECKLIST_RESULT) G_WHIP_RETURNED_VALUE=$(echo -e "$G_WHIP_RETURNED_VALUE" | tr '\n' ' ') read -r result < /tmp/.WHIP_CHECKLIST_RESULT; rm -f /tmp/.WHIP_CHECKLIST_RESULT + else + G_WHIP_RETURNED_VALUE=$G_WHIP_DEFAULT_ITEM fi G_WHIP_DESTROY