2025-01-29 21:42:22 +01:00
#!/bin/bash
# ==========================================================
2026-05-09 18:59:59 +02:00
# ProxMenux - Settings (Configuration Menu)
2025-01-29 21:42:22 +01:00
# ==========================================================
2026-05-09 18:59:59 +02:00
# Author : MacRimi
2025-11-14 02:20:07 +00:00
# Contributors : cod378
2026-05-09 18:59:59 +02:00
# Copyright : (c) 2024 MacRimi
# License : GPL-3.0
# https://github.com/MacRimi/ProxMenux/blob/main/LICENSE
2026-05-14 14:23:43 +02:00
# Version : 1.2
2026-05-09 18:59:59 +02:00
# ==========================================================
# Description:
# ProxMenux configuration / settings menu. Options are shown
# conditionally based on the install type and current state:
#
# - ProxMenux Monitor (Activate / Deactivate + Show Status)
# Only if proxmenux-monitor.service is registered with
# systemd. Toggles between active / inactive states.
#
2026-05-14 14:23:43 +02:00
# - Change Release Channel
# Switches between Stable (main branch) and Beta (develop
# branch) by running the official installer for each channel.
2026-05-09 18:59:59 +02:00
#
# - Change Language
# Only on the Translation install type (venv +
# config.json.language present). Languages: en / es / fr /
# de / it / pt.
#
# - Show Version Information
# Always shown. Reports installed components, files,
# virtual environment state and current language.
#
# - Uninstall ProxMenux
# Always shown. Interactive uninstall with optional
# dependency removal (jq, dialog, python3-*, ...) and
# restoration of /root/.bashrc + /etc/motd backups.
2025-01-29 21:42:22 +01:00
# ==========================================================
# Configuration ============================================
2025-11-03 00:22:59 +00:00
LOCAL_SCRIPTS = "/usr/local/share/proxmenux/scripts"
2025-01-29 21:42:22 +01:00
BASE_DIR = "/usr/local/share/proxmenux"
2025-07-05 17:26:31 +02:00
CONFIG_FILE = " $BASE_DIR /config.json "
2025-02-02 09:50:27 +01:00
UTILS_FILE = " $BASE_DIR /utils.sh "
2025-07-05 17:26:31 +02:00
LOCAL_VERSION_FILE = " $BASE_DIR /version.txt "
2026-05-14 14:23:43 +02:00
BETA_VERSION_FILE = " $BASE_DIR /beta_version.txt "
2025-07-05 17:26:31 +02:00
INSTALL_DIR = "/usr/local/bin"
MENU_SCRIPT = "menu"
2026-05-14 14:23:43 +02:00
BACKTITLE = "ProxMenux Configuration"
REPO_MAIN = "https://raw.githubusercontent.com/MacRimi/ProxMenux/main"
REPO_DEVELOP = "https://raw.githubusercontent.com/MacRimi/ProxMenux/develop"
STABLE_INSTALLER_URL = " $REPO_MAIN /install_proxmenux.sh "
BETA_INSTALLER_URL = " $REPO_DEVELOP /install_proxmenux_beta.sh "
2025-11-14 01:49:39 +00:00
2025-10-31 22:44:59 +01:00
MONITOR_SERVICE = "proxmenux-monitor.service"
2025-11-14 01:49:39 +00:00
MONITOR_UNIT_FILE = " /etc/systemd/system/ ${ MONITOR_SERVICE } "
2025-11-14 17:44:19 +01:00
MONITOR_CONFIG_DIR = "/root/.config/proxmenux-monitor"
2026-05-14 14:23:43 +02:00
MONITOR_RUNTIME_DIR = " $BASE_DIR /monitor-app "
MONITOR_PORT = 8008
2025-01-29 21:42:22 +01:00
2025-02-02 09:50:27 +01:00
if [ [ -f " $UTILS_FILE " ] ] ; then
source " $UTILS_FILE "
2025-01-29 21:42:22 +01:00
fi
2025-07-05 17:26:31 +02:00
2025-02-02 09:50:27 +01:00
load_language
initialize_cache
2025-07-05 17:26:31 +02:00
2025-01-29 21:42:22 +01:00
# ==========================================================
2025-11-14 01:49:39 +00:00
uninstall_proxmenux_monitor( ) {
# 1. Stop service if it is running
2025-11-14 02:30:19 +00:00
if systemctl is-active --quiet " ${ MONITOR_SERVICE } " ; then
2025-11-14 01:49:39 +00:00
echo " - Stoping service..."
2025-11-14 02:37:43 +00:00
systemctl stop " ${ MONITOR_SERVICE } " > /dev/null 2>& 1
2025-11-14 01:49:39 +00:00
else
echo " - Service is not running (ok)"
fi
# 2. Disable service if enabled
2025-11-14 02:30:19 +00:00
if systemctl is-enabled --quiet " ${ MONITOR_SERVICE } " ; then
2025-11-14 01:49:39 +00:00
echo " - Disabling service..."
2025-11-14 02:37:43 +00:00
systemctl disable " ${ MONITOR_SERVICE } " > /dev/null 2>& 1
2025-11-14 01:49:39 +00:00
else
echo " - Service is not enabled (ok)"
fi
# 3. Remove unit file
if [ -f " ${ MONITOR_UNIT_FILE } " ] ; then
echo " - Removing unit file ${ MONITOR_UNIT_FILE } ... "
rm -f " ${ MONITOR_UNIT_FILE } "
else
echo " - Unit file ${ MONITOR_UNIT_FILE } does not exist (ok) "
fi
2025-11-14 17:44:19 +01:00
# 4. Remove config directory (~/.config/proxmenux-monitor)
if [ -d " ${ MONITOR_CONFIG_DIR } " ] ; then
echo " - Removing config dir ${ MONITOR_CONFIG_DIR } ... "
rm -rf " ${ MONITOR_CONFIG_DIR } "
else
echo " - Config dir ${ MONITOR_CONFIG_DIR } does not exist (ok) "
fi
# 5. Reload systemd
2025-11-14 01:49:39 +00:00
echo " - Recargando systemd..."
2025-11-14 02:37:43 +00:00
systemctl daemon-reload > /dev/null 2>& 1
systemctl reset-failed > /dev/null 2>& 1 || true
2025-11-14 01:49:39 +00:00
2025-11-14 02:30:19 +00:00
echo " ==> Service ${ MONITOR_SERVICE } uninstalled. "
2025-11-14 17:44:19 +01:00
2025-11-14 01:49:39 +00:00
}
2025-10-31 22:44:59 +01:00
check_monitor_status( ) {
if systemctl list-unit-files | grep -q " $MONITOR_SERVICE " ; then
if systemctl is-active --quiet " $MONITOR_SERVICE " ; then
echo "active"
else
echo "inactive"
fi
else
echo "not_installed"
fi
}
2026-04-18 01:13:13 +02:00
is_beta_program_active( ) {
[ [ -f " $CONFIG_FILE " ] ] || return 1
local flag
flag = $( jq -r '.beta_program.status // empty' " $CONFIG_FILE " 2>/dev/null)
[ [ " $flag " = = "active" ] ]
}
2026-05-14 14:23:43 +02:00
get_release_channel( ) {
if is_beta_program_active; then
echo "beta"
else
echo "stable"
fi
}
release_channel_label( ) {
case " $1 " in
"beta" )
echo " $( translate "Beta (develop branch)" ) "
; ;
*)
echo " $( translate "Stable (main branch)" ) "
; ;
esac
}
download_release_installer( ) {
local channel = " $1 "
local output_file = " $2 "
local installer_url
case " $channel " in
"beta" )
installer_url = " $BETA_INSTALLER_URL "
; ;
"stable" )
installer_url = " $STABLE_INSTALLER_URL "
; ;
*)
return 1
; ;
esac
if command -v curl >/dev/null 2>& 1; then
curl -fsSL " $installer_url " -o " $output_file "
else
wget -qO " $output_file " " $installer_url "
fi
}
set_stable_release_config( ) {
local tmp
mkdir -p " $BASE_DIR "
if [ ! -f " $CONFIG_FILE " ] || ! jq empty " $CONFIG_FILE " >/dev/null 2>& 1; then
echo '{}' > " $CONFIG_FILE "
fi
tmp = $( mktemp)
if jq ' del( .beta_program, .beta_version, .install_branch)
| del( .update_available.beta, .update_available.beta_version)
| if .proxmenux_monitor.status = = "beta_updated" then .proxmenux_monitor.status = "updated" else . end
| if ( .update_available // { } ) = = { } then del( .update_available) else . end' \
" $CONFIG_FILE " > " $tmp " 2>/dev/null; then
mv " $tmp " " $CONFIG_FILE "
rm -f " $BETA_VERSION_FILE " " $BASE_DIR /install_proxmenux_beta.sh "
return 0
fi
rm -f " $tmp "
return 1
}
normalize_stable_monitor_service( ) {
local exec_path = " $MONITOR_RUNTIME_DIR /AppRun "
local was_active = false
[ -x " $exec_path " ] || return 0
[ -f " $MONITOR_UNIT_FILE " ] || return 0
systemctl is-active --quiet " $MONITOR_SERVICE " && was_active = true
msg_info " $( translate "Normalizing stable monitor service..." ) "
cat > " $MONITOR_UNIT_FILE " << EOF
[ Unit]
Description = ProxMenux Monitor - Web Dashboard
After = network.target
[ Service]
Type = simple
User = root
WorkingDirectory = $MONITOR_RUNTIME_DIR
ExecStart = $exec_path
Restart = on-failure
RestartSec = 10
Environment = " PORT= $MONITOR_PORT "
[ Install]
WantedBy = multi-user.target
EOF
systemctl daemon-reload
systemctl enable " $MONITOR_SERVICE " >/dev/null 2>& 1
if [ " $was_active " = true ] ; then
if systemctl restart " $MONITOR_SERVICE " >/dev/null 2>& 1; then
msg_ok " $( translate "Stable monitor service normalized." ) "
return 0
fi
msg_error " $( translate "Could not restart ProxMenux Monitor service." ) "
return 1
fi
msg_ok " $( translate "Stable monitor service normalized." ) "
return 0
}
apply_release_channel( ) {
local target_channel = " $1 "
local current_channel installer_file installer_status
current_channel = $( get_release_channel)
installer_file = $( mktemp /tmp/proxmenux-${ target_channel } -installer.XXXXXX) || return 1
show_proxmenux_logo
msg_title " $( translate "Changing Release Channel" ) "
msg_ok " $( translate "Current channel:" ) $( release_channel_label " $current_channel " ) "
msg_ok " $( translate "Target channel:" ) $( release_channel_label " $target_channel " ) "
msg_info " $( translate "Downloading official installer..." ) "
if download_release_installer " $target_channel " " $installer_file " >/dev/null 2>& 1; then
chmod +x " $installer_file "
msg_ok " $( translate "Installer downloaded." ) "
else
msg_error " $( translate "Could not download the installer." ) "
rm -f " $installer_file "
msg_success " $( translate "Press Enter to return to menu..." ) "
read -r
return 1
fi
msg_info " $( translate "Starting installer..." ) "
stop_spinner
bash " $installer_file "
installer_status = $?
rm -f " $installer_file "
if [ " $installer_status " -ne 0 ] ; then
msg_error " $( translate "Installer finished with errors." ) "
msg_success " $( translate "Press Enter to return to menu..." ) "
read -r
return 1
fi
if [ " $target_channel " = "stable" ] ; then
msg_info " $( translate "Updating release channel configuration..." ) "
if set_stable_release_config; then
msg_ok " $( translate "Release channel set to Stable." ) "
if ! normalize_stable_monitor_service; then
msg_success " $( translate "Press Enter to return to menu..." ) "
read -r
return 1
fi
2026-04-18 01:13:13 +02:00
else
2026-05-14 14:23:43 +02:00
msg_error " $( translate "Could not update config file." ) "
msg_success " $( translate "Press Enter to return to menu..." ) "
read -r
return 1
2026-04-18 01:13:13 +02:00
fi
2026-05-14 14:23:43 +02:00
else
msg_ok " $( translate "Release channel set to Beta." ) "
fi
msg_success " $( translate "Press Enter to return to menu..." ) "
read -r
exec bash " $LOCAL_SCRIPTS /menus/config_menu.sh "
}
change_release_channel( ) {
local current_channel current_label selected_channel selected_label confirm_message
current_channel = $( get_release_channel)
current_label = $( release_channel_label " $current_channel " )
selected_channel = $( dialog --clear --backtitle " $BACKTITLE " \
--title " $( translate "Release Channel" ) " \
--default-item " $current_channel " \
--menu " $( translate "Current channel:" ) $current_label \n\n $( translate "Choose the release channel to use:" ) " 16 74 2 \
"stable" " $( translate "Stable (main branch)" ) " \
"beta" " $( translate "Beta (develop branch)" ) " 3>& 1 1>& 2 2>& 3)
[ -z " $selected_channel " ] && return
if [ " $selected_channel " = " $current_channel " ] ; then
dialog --clear --backtitle " $BACKTITLE " \
--title " $( translate "Release Channel" ) " \
--msgbox " \n\n $( translate "This release channel is already active." ) " 9 56
return
fi
selected_label = $( release_channel_label " $selected_channel " )
case " $selected_channel " in
"beta" )
confirm_message = " $( translate "This will install the Beta version from the develop branch and enable beta update checks.\n\nBeta builds may contain bugs or incomplete features.\n\nContinue?" ) "
; ;
"stable" )
confirm_message = " $( translate "This will reinstall the Stable version from the main branch and disable beta update checks.\n\nContinue?" ) "
; ;
*)
return
; ;
esac
if dialog --clear --backtitle " $BACKTITLE " \
--title " $selected_label " \
--yesno " \n $confirm_message " 14 72; then
apply_release_channel " $selected_channel "
2026-04-18 01:13:13 +02:00
fi
}
2025-10-31 22:44:59 +01:00
toggle_monitor_service( ) {
local status = $( check_monitor_status)
if [ " $status " = "not_installed" ] ; then
dialog --clear --backtitle "ProxMenux Configuration" \
--title " $( translate "ProxMenux Monitor" ) " \
--msgbox " \n\n $( translate "ProxMenux Monitor is not installed." ) " 10 50
return
fi
if [ " $status " = "active" ] ; then
if dialog --clear --backtitle "ProxMenux Configuration" \
--title " $( translate "Deactivate Monitor" ) " \
--yesno " \n $( translate "Do you want to deactivate ProxMenux Monitor?" ) " 8 60; then
systemctl stop " $MONITOR_SERVICE " 2>/dev/null
systemctl disable " $MONITOR_SERVICE " 2>/dev/null
dialog --clear --backtitle "ProxMenux Configuration" \
--title " $( translate "Monitor Deactivated" ) " \
--msgbox " \n\n $( translate "ProxMenux Monitor has been deactivated." ) " 10 50
fi
else
if dialog --clear --backtitle "ProxMenux Configuration" \
--title " $( translate "Activate Monitor" ) " \
--yesno " \n $( translate "Do you want to activate ProxMenux Monitor?" ) " 8 60; then
systemctl enable " $MONITOR_SERVICE " 2>/dev/null
systemctl start " $MONITOR_SERVICE " 2>/dev/null
dialog --clear --backtitle "ProxMenux Configuration" \
--title " $( translate "Monitor Activated" ) " \
--msgbox " \n\n $( translate "ProxMenux Monitor has been activated." ) " 10 50
fi
fi
}
2026-05-21 21:17:59 +02:00
reset_monitor_password( ) {
# Recovery path for operators who lost the Monitor login credentials.
# Wipes only the identity claims from auth.json (username / password /
# 2FA secret / backup codes) so the next visit to the dashboard
# triggers the setup wizard with no password needed. Intentionally
# KEEPS `jwt_secret`, `api_tokens` and `revoked_tokens` — that means
# already-issued API tokens continue to work (Home Assistant /
# custom scripts don't need to be reconfigured) and only the
# interactive web login is reset. The operator chooses a new
# username + password on the next visit.
local auth_file = " $MONITOR_CONFIG_DIR /auth.json "
if [ ! -f " $auth_file " ] ; then
dialog --clear --backtitle " $BACKTITLE " \
--title " $( translate "Reset Monitor Password" ) " \
--msgbox " \n\n $( translate "ProxMenux Monitor authentication is not configured on this host — there is no password to reset." ) " 11 70
return
fi
if ! dialog --clear --backtitle " $BACKTITLE " \
--title " $( translate "Reset Monitor Password" ) " \
--yesno " \n $( translate "This will RESET the ProxMenux Monitor login credentials on this host:" ) \n\n • $( translate "Username and password will be cleared." ) \n • $( translate "Two-factor authentication and backup codes will be removed." ) \n • $( translate "API tokens (Home Assistant, scripts) will keep working." ) \n • $( translate "The next visit to the dashboard will show the initial setup wizard." ) \n\n $( translate "Continue?" ) " 16 78; then
return
fi
if ! command -v jq >/dev/null 2>& 1; then
dialog --clear --backtitle " $BACKTITLE " \
--title " $( translate "Reset Monitor Password" ) " \
--msgbox " \n\n $( translate "jq is required for this operation but is not installed." ) " 10 60
return
fi
show_proxmenux_logo
msg_title " $( translate "Reset Monitor Password" ) "
# Timestamped backup so the operator can recover the previous state
# if the reset was a mistake. Includes the secret material — keep
# this file out of any shared location.
local backup_file
backup_file = " ${ auth_file } .bak- $( date -u +%Y%m%d%H%M%S) "
if ! cp -a " $auth_file " " $backup_file " 2>/dev/null; then
msg_error " $( translate "Could not back up the existing auth.json" ) "
msg_success " $( translate "Press Enter to return to menu..." ) "
read -r
return
fi
chmod 0600 " $backup_file " 2>/dev/null || true
msg_ok " $( translate "Backup saved to:" ) $backup_file "
msg_info " $( translate "Stopping ProxMenux Monitor service..." ) "
systemctl stop " $MONITOR_SERVICE " >/dev/null 2>& 1 || true
msg_ok " $( translate "Service stopped." ) "
msg_info " $( translate "Clearing login credentials..." ) "
local tmp
tmp = $( mktemp)
if jq '
.enabled = false
| .configured = false
| .username = ""
| .password_hash = ""
| .declined = false
| .totp_enabled = false
| .totp_secret = null
| .backup_codes = [ ]
' " $auth_file " > " $tmp " 2>/dev/null; then
chmod 0600 " $tmp " 2>/dev/null || true
mv " $tmp " " $auth_file "
msg_ok " $( translate "Credentials cleared. jwt_secret and API tokens preserved." ) "
else
rm -f " $tmp "
msg_error " $( translate "Failed to update auth.json — restoring backup." ) "
cp -a " $backup_file " " $auth_file "
systemctl start " $MONITOR_SERVICE " >/dev/null 2>& 1 || true
msg_success " $( translate "Press Enter to return to menu..." ) "
read -r
return
fi
msg_info " $( translate "Restarting ProxMenux Monitor service..." ) "
if systemctl start " $MONITOR_SERVICE " >/dev/null 2>& 1; then
msg_ok " $( translate "Service restarted." ) "
else
msg_warn " $( translate "Could not restart the service — start it manually with systemctl start" ) $MONITOR_SERVICE "
fi
local server_ip
server_ip = $( hostname -I | awk '{print $1}' )
echo ""
msg_success " $( translate "Password reset completed." ) "
echo ""
if [ -n " $server_ip " ] ; then
msg_info2 " $( translate "Open the dashboard to create a new admin account:" ) "
echo -e " ${ TAB } ${ BL } http:// ${ server_ip } :8008 ${ CL } "
else
msg_info2 " $( translate "Open the dashboard from this host on port 8008 to create a new admin account." ) "
fi
echo ""
msg_success " $( translate "Press Enter to return to menu..." ) "
read -r
}
2025-10-31 22:44:59 +01:00
show_monitor_status( ) {
clear
show_proxmenux_logo
msg_title " $( translate "ProxMenux Monitor Service Verification" ) "
echo ""
local status = $( check_monitor_status)
if [ " $status " = "not_installed" ] ; then
msg_warn " $( translate "ProxMenux Monitor is not installed" ) "
echo ""
msg_info2 " $( translate "To install the monitor, reinstall ProxMenux with the latest version" ) "
else
msg_info2 " $( translate "Service Status" ) : $MONITOR_SERVICE "
echo ""
if [ " $status " = "active" ] ; then
msg_ok " $( translate "Service is active and running" ) "
local server_ip = $( hostname -I | awk '{print $1}' )
if [ -n " $server_ip " ] ; then
echo -e " ${ TAB } ${ GN } 🌐 $( translate "Monitor URL" ) ${ CL } : ${ BL } http:// ${ server_ip } :8008 ${ CL } "
fi
else
msg_warn " $( translate "Service is inactive" ) "
fi
echo ""
msg_info2 " $( translate "Detailed service information" ) : "
echo ""
systemctl status " $MONITOR_SERVICE " --no-pager -l
fi
echo ""
msg_success " $( translate "Press Enter to continue..." ) "
read -r
}
2025-07-05 17:26:31 +02:00
# ==========================================================
2025-01-29 21:31:10 +01:00
show_config_menu( ) {
while true; do
2025-07-05 17:26:31 +02:00
local menu_options = ( )
local option_actions = ( )
2025-10-31 22:44:59 +01:00
local monitor_status = $( check_monitor_status)
local option_num = 1
if [ " $monitor_status " != "not_installed" ] ; then
if [ " $monitor_status " = "active" ] ; then
menu_options += ( " $option_num " " $( translate "Deactivate ProxMenux Monitor" ) " )
option_actions[ $option_num ] = "toggle_monitor"
else
menu_options += ( " $option_num " " $( translate "Activate ProxMenux Monitor" ) " )
option_actions[ $option_num ] = "toggle_monitor"
fi
( ( option_num++) )
menu_options += ( " $option_num " " $( translate "Show Monitor Service Status" ) " )
option_actions[ $option_num ] = "show_monitor_status"
( ( option_num++) )
2026-05-21 21:17:59 +02:00
menu_options += ( " $option_num " " $( translate "Reset ProxMenux Monitor Password" ) " )
option_actions[ $option_num ] = "reset_monitor_password"
( ( option_num++) )
2025-10-31 22:44:59 +01:00
fi
2026-04-18 01:13:13 +02:00
2026-05-14 14:23:43 +02:00
menu_options += ( " $option_num " " $( translate "Change Release Channel" ) " )
option_actions[ $option_num ] = "change_release_channel"
( ( option_num++) )
2026-04-18 01:13:13 +02:00
2026-06-10 19:53:40 +02:00
# Translation/Normal split is gone — single menu now. Change Language
# is always available since every install ships the lang/*.json cache.
menu_options += ( " $option_num " " $( translate "Change Language" ) " )
option_actions[ $option_num ] = "change_language"
( ( option_num++) )
menu_options += ( " $option_num " " $( translate "Show Version Information" ) " )
option_actions[ $option_num ] = "show_version_info"
( ( option_num++) )
menu_options += ( " $option_num " " $( translate "Uninstall ProxMenux" ) " )
option_actions[ $option_num ] = "uninstall_proxmenu"
( ( option_num++) )
menu_options += ( " $option_num " " $( translate "Return to Main Menu" ) " )
option_actions[ $option_num ] = "return_main"
2025-07-05 17:26:31 +02:00
2025-10-31 22:44:59 +01:00
# Show menu
2025-07-05 17:26:31 +02:00
OPTION = $( dialog --clear --backtitle "ProxMenux Configuration" \
--title " $( translate "Configuration Menu" ) " \
2025-07-05 17:31:18 +02:00
--menu " $( translate "Select an option:" ) " 20 70 10 \
2025-07-05 17:26:31 +02:00
" ${ menu_options [@] } " 3>& 1 1>& 2 2>& 3)
2025-10-31 22:44:59 +01:00
# Execute selected action
2025-07-05 17:26:31 +02:00
case " ${ option_actions [ $OPTION ] } " in
2025-10-31 22:44:59 +01:00
"toggle_monitor" )
toggle_monitor_service
; ;
"show_monitor_status" )
show_monitor_status
; ;
2026-05-21 21:17:59 +02:00
"reset_monitor_password" )
reset_monitor_password
; ;
2026-05-14 14:23:43 +02:00
"change_release_channel" )
change_release_channel
2026-04-18 01:13:13 +02:00
; ;
2025-07-05 17:26:31 +02:00
"change_language" )
2025-01-29 21:31:10 +01:00
change_language
; ;
2025-07-05 17:26:31 +02:00
"show_version_info" )
2025-01-29 21:31:10 +01:00
show_version_info
; ;
2025-07-05 17:26:31 +02:00
"uninstall_proxmenu" )
2025-01-29 21:31:10 +01:00
uninstall_proxmenu
; ;
2025-07-05 17:26:31 +02:00
"return_main" | "" )
2025-11-03 00:22:59 +00:00
exec bash " $LOCAL_SCRIPTS /menus/main_menu.sh "
2025-07-05 17:26:31 +02:00
; ;
2025-01-29 21:31:10 +01:00
esac
done
}
2025-02-06 17:34:39 +01:00
# ==========================================================
2025-01-29 21:31:10 +01:00
change_language( ) {
2025-07-05 17:26:31 +02:00
local new_language
new_language = $( dialog --clear --backtitle "ProxMenux Configuration" \
--title " $( translate "Change Language" ) " \
--menu " $( translate "Select a new language for the menu:" ) " 20 60 6 \
"en" " $( translate "English" ) " \
"es" " $( translate "Spanish" ) " \
"fr" " $( translate "French" ) " \
"de" " $( translate "German" ) " \
"it" " $( translate "Italian" ) " \
"pt" " $( translate "Portuguese" ) " 3>& 1 1>& 2 2>& 3)
if [ -z " $new_language " ] ; then
dialog --clear --backtitle "ProxMenux Configuration" \
--title " $( translate "Language Change" ) " \
--msgbox " \n\n $( translate "No language selected." ) " 10 50
2025-01-29 21:31:10 +01:00
return
fi
2025-07-05 17:26:31 +02:00
2025-10-31 22:44:59 +01:00
# Update language in config file
2025-02-05 20:57:02 +01:00
if [ -f " $CONFIG_FILE " ] ; then
tmp = $( mktemp)
2025-07-05 17:26:31 +02:00
jq --arg lang " $new_language " '.language = $lang' " $CONFIG_FILE " > " $tmp " && mv " $tmp " " $CONFIG_FILE "
2025-02-05 20:57:02 +01:00
else
2025-07-05 17:26:31 +02:00
echo " {\"language\": \" $new_language \"} " > " $CONFIG_FILE "
2025-02-05 20:57:02 +01:00
fi
2025-07-05 17:26:31 +02:00
dialog --clear --backtitle "ProxMenux Configuration" \
--title " $( translate "Language Change" ) " \
--msgbox " \n\n $( translate "Language changed to" ) $new_language " 10 50
2025-10-31 22:44:59 +01:00
# Reload menu with new language
2025-11-03 00:22:59 +00:00
exec bash " $LOCAL_SCRIPTS /menus/config_menu.sh "
2025-01-29 21:31:10 +01:00
}
2025-02-06 17:34:39 +01:00
# ==========================================================
2025-01-29 21:31:10 +01:00
show_version_info( ) {
2026-06-10 19:53:40 +02:00
local version info_message release_channel beta_version
2026-05-14 14:23:43 +02:00
release_channel = $( get_release_channel)
2025-07-05 17:26:31 +02:00
if [ -f " $LOCAL_VERSION_FILE " ] ; then
version = $( <" $LOCAL_VERSION_FILE " )
else
version = "Unknown"
fi
2026-05-14 14:23:43 +02:00
info_message += " $( translate "Current ProxMenux version:" ) $version \n "
info_message += " $( translate "Release channel:" ) $( release_channel_label " $release_channel " ) \n "
if [ " $release_channel " = "beta" ] && [ -f " $BETA_VERSION_FILE " ] ; then
beta_version = $( head -n 1 " $BETA_VERSION_FILE " 2>/dev/null)
[ -n " $beta_version " ] && info_message += " $( translate "Beta version:" ) $beta_version \n "
fi
info_message += "\n"
2025-07-05 17:26:31 +02:00
2026-06-10 19:53:40 +02:00
# Translation/Normal split is gone — single install path now.
# Translation support is always present via the lang/*.json cache.
2025-07-05 17:26:31 +02:00
info_message += " $( translate "Installed components:" ) \n "
2025-02-06 17:34:39 +01:00
if [ -f " $CONFIG_FILE " ] ; then
while IFS = ': ' read -r component value; do
2026-05-14 14:23:43 +02:00
case " $component " in
"language" | "beta_program" | "beta_version" | "install_branch" | "update_available" )
continue
; ;
esac
2025-02-06 17:34:39 +01:00
local status
if echo " $value " | jq -e '.status' >/dev/null 2>& 1; then
status = $( echo " $value " | jq -r '.status' )
else
status = " $value "
fi
local translated_status = $( translate " $status " )
case " $status " in
2025-11-14 22:17:11 +01:00
"installed" | "already_installed" | "created" | "already_exists" | "upgraded" | "updated" )
2025-02-06 17:34:39 +01:00
info_message += " ✓ $component : $translated_status \n "
; ;
*)
info_message += " ✗ $component : $translated_status \n "
; ;
esac
done < <( jq -r 'to_entries[] | "\(.key): \(.value)"' " $CONFIG_FILE " )
else
info_message += " $( translate "No installation information available." ) \n "
fi
2025-07-05 17:26:31 +02:00
2025-09-10 18:47:55 +02:00
info_message += " \n $( translate "ProxMenux files:" ) \n "
2025-02-06 18:40:26 +01:00
[ -f " $INSTALL_DIR / $MENU_SCRIPT " ] && info_message += " ✓ $MENU_SCRIPT → $INSTALL_DIR / $MENU_SCRIPT \n " || info_message += " ✗ $MENU_SCRIPT \n "
[ -f " $UTILS_FILE " ] && info_message += " ✓ utils.sh → $UTILS_FILE \n " || info_message += "✗ utils.sh\n"
[ -f " $CONFIG_FILE " ] && info_message += " ✓ config.json → $CONFIG_FILE \n " || info_message += "✗ config.json\n"
[ -f " $LOCAL_VERSION_FILE " ] && info_message += " ✓ version.txt → $LOCAL_VERSION_FILE \n " || info_message += "✗ version.txt\n"
2025-07-05 17:26:31 +02:00
2026-06-10 19:05:13 +02:00
# Language section: always present now that translations are static
# JSON lookups. Show the configured language and the lang/ directory
# so the operator can verify the cache is in place.
current_language = $( jq -r '.language // "en"' " $CONFIG_FILE " 2>/dev/null)
[ [ -z " $current_language " || " $current_language " = = "null" ] ] && current_language = "en"
info_message += " \n $( translate "Current language:" ) \n ${ current_language } \n "
if [ -d " $BASE_DIR /lang " ] ; then
info_message += " ✓ $( translate "Translation files:" ) $BASE_DIR /lang/\n "
2025-02-06 17:34:39 +01:00
else
2026-06-10 19:05:13 +02:00
info_message += " ✗ $( translate "Translation files:" ) $( translate "missing" ) \n "
2025-02-06 17:34:39 +01:00
fi
2025-07-05 17:26:31 +02:00
2025-10-31 22:44:59 +01:00
# Display information in a scrollable text box
2025-07-05 17:26:31 +02:00
tmpfile = $( mktemp)
echo -e " $info_message " > " $tmpfile "
dialog --clear --backtitle "ProxMenux Configuration" \
--title " $( translate "ProxMenux Information" ) " \
--textbox " $tmpfile " 25 80
rm -f " $tmpfile "
2025-01-29 21:31:10 +01:00
}
2025-02-06 17:34:39 +01:00
# ==========================================================
uninstall_proxmenu( ) {
2025-07-05 17:26:31 +02:00
if ! dialog --clear --backtitle "ProxMenux Configuration" \
2025-09-10 19:06:04 +02:00
--title "Uninstall ProxMenux" \
--yesno " \n $( translate "Are you sure you want to uninstall ProxMenux?" ) " 8 60; then
2025-02-06 17:34:39 +01:00
return
fi
2025-07-05 17:26:31 +02:00
local deps_to_remove = ""
2026-06-10 19:05:13 +02:00
deps_to_remove = $( dialog --clear --backtitle "ProxMenux Configuration" \
--title "Remove Dependencies" \
--checklist "Select dependencies to remove:" 12 60 2 \
"dialog" "Interactive dialog boxes" OFF \
"jq" "JSON processor" OFF \
3>& 1 1>& 2 2>& 3)
2025-10-31 22:44:59 +01:00
# Perform uninstallation with progress bar
2025-07-05 17:26:31 +02:00
(
echo "10" ; echo "Removing ProxMenu files..."
sleep 1
2026-06-10 19:05:13 +02:00
# Purge the legacy googletrans virtualenv if it was left over from
# a pre-static-translations install. Cheap idempotent check.
if [ -d "/opt/googletrans-env" ] ; then
echo "30" ; echo "Removing legacy googletrans virtualenv..."
rm -rf "/opt/googletrans-env"
2025-07-05 17:26:31 +02:00
fi
2026-06-10 19:05:13 +02:00
2025-07-05 17:26:31 +02:00
echo "50" ; echo "Removing ProxMenu files..."
rm -f " $INSTALL_DIR / $MENU_SCRIPT "
rm -rf " $BASE_DIR "
2025-10-31 22:44:59 +01:00
# Remove selected dependencies
2025-07-05 17:26:31 +02:00
if [ -n " $deps_to_remove " ] ; then
echo "70" ; echo "Removing selected dependencies..."
read -r -a DEPS_ARRAY <<< " $( echo " $deps_to_remove " | tr -d '"' ) "
for dep in " ${ DEPS_ARRAY [@] } " ; do
apt-mark auto " $dep " >/dev/null 2>& 1
apt-get -y --purge autoremove " $dep " >/dev/null 2>& 1
done
apt-get autoremove -y --purge >/dev/null 2>& 1
fi
2025-11-14 01:49:39 +00:00
echo "80" ; echo "Removing ProxMenux Monitor..."
uninstall_proxmenux_monitor
2025-07-05 17:26:31 +02:00
echo "90" ; echo "Restoring system files..."
2025-10-31 22:44:59 +01:00
# Restore .bashrc and motd
2025-07-05 17:26:31 +02:00
[ -f /root/.bashrc.bak ] && mv /root/.bashrc.bak /root/.bashrc
if [ -f /etc/motd.bak ] ; then
mv /etc/motd.bak /etc/motd
else
sed -i '/This system is optimised by: ProxMenux/d' /etc/motd
fi
echo "100" ; echo "Uninstallation complete!"
sleep 1
) | dialog --clear --backtitle "ProxMenux Configuration" \
--title "Uninstalling ProxMenux" \
--gauge "Starting uninstallation..." 10 60 0
2025-05-08 09:22:00 +02:00
2025-10-31 22:44:59 +01:00
# Show completion message
2025-07-05 17:26:31 +02:00
local final_message = "ProxMenux has been uninstalled successfully.\n\n"
if [ -n " $deps_to_remove " ] ; then
final_message += " The following dependencies were removed:\n $deps_to_remove \n\n "
2025-02-06 17:34:39 +01:00
fi
2025-07-05 17:26:31 +02:00
final_message += "Thank you for using ProxMenux!"
2025-05-08 09:22:00 +02:00
2025-07-05 17:26:31 +02:00
dialog --clear --backtitle "ProxMenux Configuration" \
--title "Uninstallation Complete" \
--msgbox " $final_message " 12 60
clear
2025-02-06 17:34:39 +01:00
exit 0
}
2025-07-05 17:26:31 +02:00
# ==========================================================
# Main execution
2025-10-31 22:44:59 +01:00
show_config_menu