mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2026-06-11 19:07:01 +00:00
Update lib_host_backup_common.sh
This commit is contained in:
@@ -1113,11 +1113,17 @@ hb_ask_pbs_encryption() {
|
|||||||
# BORG
|
# BORG
|
||||||
# ==========================================================
|
# ==========================================================
|
||||||
hb_ensure_borg() {
|
hb_ensure_borg() {
|
||||||
# Resolution order:
|
# Borg is intentionally NOT a base dep of install_proxmenux.sh —
|
||||||
# 1. system borg (apt-installed)
|
# operators who only ever use PBS or local archives shouldn't carry
|
||||||
# 2. /usr/local/share/proxmenux/borg (state-dir cache)
|
# ~3 MB of dead weight. The canonical source is the Monitor AppImage
|
||||||
# 3. Monitor AppImage's bundled borg (offline, post-install)
|
# bundle, which is built with a SHA-verified borg-linux64 binary
|
||||||
# 4. GitHub download → state-dir (first run, online)
|
# alongside the dashboard. Resolution order:
|
||||||
|
#
|
||||||
|
# 1. system borg (already apt-installed)
|
||||||
|
# 2. /usr/local/share/proxmenux/borg (state-dir cache from prior run)
|
||||||
|
# 3. Monitor AppImage's bundled borg (canonical — offline-safe)
|
||||||
|
# 4. GitHub download → state-dir (last resort for hosts
|
||||||
|
# without the new AppImage)
|
||||||
command -v borg >/dev/null 2>&1 && { echo "borg"; return 0; }
|
command -v borg >/dev/null 2>&1 && { echo "borg"; return 0; }
|
||||||
|
|
||||||
local appimage_cache="$HB_STATE_DIR/borg"
|
local appimage_cache="$HB_STATE_DIR/borg"
|
||||||
@@ -1271,16 +1277,126 @@ hb_borg_generate_and_install_key() {
|
|||||||
# for the test target on CT 112.
|
# for the test target on CT 112.
|
||||||
authorized_line="command=\"/usr/bin/borg serve --restrict-to-path ${rpath}\",restrict ${pubkey}"
|
authorized_line="command=\"/usr/bin/borg serve --restrict-to-path ${rpath}\",restrict ${pubkey}"
|
||||||
|
|
||||||
|
if [[ "$mode" == "generate-pct" ]]; then
|
||||||
|
# Authorize via `pct exec` from a PVE host. This is the right
|
||||||
|
# fix for the very common "Borg server is an LXC on another
|
||||||
|
# Proxmox node" setup, where the CT typically ships with
|
||||||
|
# PermitRootLogin prohibit-password and SSH password auth into
|
||||||
|
# the CT itself fails. We bypass SSH-to-the-CT entirely and
|
||||||
|
# rely on root@PVE-host being able to run `pct exec <vmid> --`
|
||||||
|
# — that already runs as root inside the CT, so writing into
|
||||||
|
# ~borg/.ssh/authorized_keys is trivial.
|
||||||
|
|
||||||
|
# Silently make sure sshpass is around (same pattern as
|
||||||
|
# generate-auto). If it can't be installed, fall back to
|
||||||
|
# generate-manual.
|
||||||
|
if ! command -v sshpass >/dev/null 2>&1; then
|
||||||
|
if command -v apt-get >/dev/null 2>&1; then
|
||||||
|
DEBIAN_FRONTEND=noninteractive apt-get install -y -qq sshpass >/dev/null 2>&1 || true
|
||||||
|
fi
|
||||||
|
if ! command -v sshpass >/dev/null 2>&1; then
|
||||||
|
hb_borg_generate_and_install_key "$borg_user" "$host" "$rpath" "generate-manual" "$_out_var"
|
||||||
|
return $?
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
local pve_host pve_user pve_pass vmid
|
||||||
|
pve_host=$(dialog --backtitle "ProxMenux" \
|
||||||
|
--title "$(hb_translate "PVE host (where the Borg LXC lives)")" \
|
||||||
|
--inputbox "$(hb_translate "IP or hostname of the PVE node hosting the Borg server LXC:")" \
|
||||||
|
"$HB_UI_INPUT_H" "$HB_UI_INPUT_W" "" 3>&1 1>&2 2>&3) || return 1
|
||||||
|
pve_user=$(dialog --backtitle "ProxMenux" \
|
||||||
|
--inputbox "$(hb_translate "Root user on the PVE host (default 'root'):")" \
|
||||||
|
"$HB_UI_INPUT_H" "$HB_UI_INPUT_W" "root" 3>&1 1>&2 2>&3) || return 1
|
||||||
|
pve_pass=$(dialog --backtitle "ProxMenux" --insecure --passwordbox \
|
||||||
|
"$(hb_translate "Password for") ${pve_user}@${pve_host}:" \
|
||||||
|
"$HB_UI_PASS_H" "$HB_UI_PASS_W" "" 3>&1 1>&2 2>&3) || return 1
|
||||||
|
vmid=$(dialog --backtitle "ProxMenux" \
|
||||||
|
--inputbox "$(hb_translate "VMID of the Borg server LXC on") ${pve_host}:" \
|
||||||
|
"$HB_UI_INPUT_H" "$HB_UI_INPUT_W" "" 3>&1 1>&2 2>&3) || return 1
|
||||||
|
if [[ -z "$pve_host" || -z "$vmid" || -z "$pve_pass" ]]; then
|
||||||
|
dialog --backtitle "ProxMenux" --msgbox \
|
||||||
|
"$(hb_translate "PVE host, VMID and password are all required for this mode.")" 8 60
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Build the pct-exec script. The authorized_line is fed through
|
||||||
|
# stdin so quotes in `command="..."` are preserved verbatim
|
||||||
|
# without shell re-expansion. `getent passwd` resolves whatever
|
||||||
|
# the borg user's actual home is, regardless of name.
|
||||||
|
local pct_cmd
|
||||||
|
pct_cmd="set -e
|
||||||
|
pct exec ${vmid} -- bash -c '
|
||||||
|
set -e
|
||||||
|
target_dir=\$(getent passwd ${borg_user} | cut -d: -f6)/.ssh
|
||||||
|
mkdir -p \"\$target_dir\"
|
||||||
|
chmod 700 \"\$target_dir\"
|
||||||
|
chown ${borg_user}: \"\$target_dir\"
|
||||||
|
line=\$(cat)
|
||||||
|
touch \"\$target_dir/authorized_keys\"
|
||||||
|
grep -Fxq \"\$line\" \"\$target_dir/authorized_keys\" 2>/dev/null || \
|
||||||
|
echo \"\$line\" >> \"\$target_dir/authorized_keys\"
|
||||||
|
chown ${borg_user}: \"\$target_dir/authorized_keys\"
|
||||||
|
chmod 600 \"\$target_dir/authorized_keys\"
|
||||||
|
'
|
||||||
|
echo OK"
|
||||||
|
|
||||||
|
local push_rc
|
||||||
|
SSHPASS="$pve_pass" sshpass -e ssh \
|
||||||
|
-o StrictHostKeyChecking=accept-new \
|
||||||
|
-o PreferredAuthentications=password -o PubkeyAuthentication=no \
|
||||||
|
-o ConnectTimeout=15 \
|
||||||
|
"$pve_user@$pve_host" "$pct_cmd" <<<"$authorized_line" >/tmp/proxmenux-borg-pctpush.log 2>&1
|
||||||
|
push_rc=$?
|
||||||
|
|
||||||
|
if (( push_rc != 0 )); then
|
||||||
|
dialog --backtitle "ProxMenux" --colors \
|
||||||
|
--title "$(hb_translate "pct exec authorization failed")" \
|
||||||
|
--msgbox "$(hb_translate "Could not authorize the key via 'pct exec' on") \Z1${pve_host}\Zn (VMID ${vmid}).\n\n$(hb_translate "See") /tmp/proxmenux-borg-pctpush.log\n\n$(hb_translate "Falling back to manual paste mode.")" 14 78
|
||||||
|
hb_borg_generate_and_install_key "$borg_user" "$host" "$rpath" "generate-manual" "$_out_var"
|
||||||
|
return $?
|
||||||
|
fi
|
||||||
|
|
||||||
|
dialog --backtitle "ProxMenux" --colors \
|
||||||
|
--title "$(hb_translate "Authorized")" \
|
||||||
|
--msgbox "$(hb_translate "The new SSH key was pushed to the LXC via 'pct exec' on") \Z4${pve_host}\Zn (VMID ${vmid})." 10 78
|
||||||
|
_out_ref="$key_file"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ "$mode" == "generate-manual" ]]; then
|
if [[ "$mode" == "generate-manual" ]]; then
|
||||||
local msg
|
# Print the line on the raw terminal (NOT inside dialog --msgbox)
|
||||||
msg="$(hb_translate "On the Borg server, append the following line to:")"$'\n'
|
# so the operator can select & copy it with their terminal client.
|
||||||
msg+=" ~${borg_user}/.ssh/authorized_keys"$'\n\n'
|
# ncurses captures all input inside dialog/whiptail, which means
|
||||||
msg+="$(hb_translate "Line to paste (single line, including \"command=...\" prefix):")"$'\n\n'
|
# "click + drag to select" silently does nothing — a real footgun
|
||||||
msg+="${authorized_line}"$'\n\n'
|
# for a paste-this-string-elsewhere flow. Also dump the line to a
|
||||||
msg+="$(hb_translate "After pasting, ensure the file is chmod 600 and owned by") ${borg_user}."
|
# file so anyone who can't paste (noVNC console, intermediate
|
||||||
dialog --backtitle "ProxMenux" \
|
# firewall, ...) can `scp` or `cat` it from this host directly.
|
||||||
--title "$(hb_translate "Authorize this key on the server")" \
|
local out_file="/tmp/proxmenux-borg-authkey.txt"
|
||||||
--msgbox "$msg" 22 100
|
printf '%s\n' "$authorized_line" > "$out_file"
|
||||||
|
chmod 600 "$out_file"
|
||||||
|
|
||||||
|
clear
|
||||||
|
type_text "$(hb_translate "Authorize this key on the server")" 2>/dev/null || \
|
||||||
|
echo " ── $(hb_translate "Authorize this key on the server") ──"
|
||||||
|
echo ""
|
||||||
|
echo -e "${TAB}${BGN}$(hb_translate "On the Borg server, append the following line to:")${CL}"
|
||||||
|
echo -e "${TAB} ${BL}~${borg_user}/.ssh/authorized_keys${CL}"
|
||||||
|
echo ""
|
||||||
|
echo -e "${TAB}${BGN}$(hb_translate "Line to paste (single line, including \"command=...\" prefix):")${CL}"
|
||||||
|
echo ""
|
||||||
|
# Print the line on its own block so it's easy to triple-click
|
||||||
|
# / shift-click to select in any terminal client. No wrapping —
|
||||||
|
# we use plain echo, not the indented format above.
|
||||||
|
echo "${authorized_line}"
|
||||||
|
echo ""
|
||||||
|
echo -e "${TAB}${BGN}$(hb_translate "Or, if your terminal can't select text, copy it from:")${CL}"
|
||||||
|
echo -e "${TAB} ${BL}${out_file}${CL} $(hb_translate "(e.g.") scp root@$(hostname -I 2>/dev/null | awk '{print $1}'):${out_file} .${CL}$(hb_translate ")")"
|
||||||
|
echo ""
|
||||||
|
echo -e "${TAB}${YWB}$(hb_translate "After pasting on the server, ensure the file is chmod 600 and owned by") ${borg_user}.${CL}"
|
||||||
|
echo ""
|
||||||
|
msg_success "$(hb_translate "Press Enter when the line has been pasted on the server...")"
|
||||||
|
read -r
|
||||||
_out_ref="$key_file"
|
_out_ref="$key_file"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
@@ -1289,17 +1405,17 @@ hb_borg_generate_and_install_key() {
|
|||||||
# for whichever account can write to ~borg/.ssh/authorized_keys —
|
# for whichever account can write to ~borg/.ssh/authorized_keys —
|
||||||
# typically `root`, or the borg user itself if it has a login
|
# typically `root`, or the borg user itself if it has a login
|
||||||
# password.
|
# password.
|
||||||
|
# Silent best-effort install — same pattern as hb_ensure_pv. Asking
|
||||||
|
# the operator "install sshpass?" is backwards: we already have apt,
|
||||||
|
# they shouldn't have to confirm a 40 KB install for us. If apt
|
||||||
|
# can't reach the repo, we silently fall back to manual mode.
|
||||||
if ! command -v sshpass >/dev/null 2>&1; then
|
if ! command -v sshpass >/dev/null 2>&1; then
|
||||||
if dialog --backtitle "ProxMenux" \
|
if command -v apt-get >/dev/null 2>&1; then
|
||||||
--yesno "$(hb_translate "sshpass is not installed. Install it now from apt? (Required to push the new SSH key in this mode.)")" \
|
DEBIAN_FRONTEND=noninteractive apt-get install -y -qq sshpass >/dev/null 2>&1 || true
|
||||||
"$HB_UI_YESNO_H" "$HB_UI_YESNO_W"; then
|
fi
|
||||||
DEBIAN_FRONTEND=noninteractive apt-get install -y -qq sshpass >/dev/null 2>&1 || {
|
if ! command -v sshpass >/dev/null 2>&1; then
|
||||||
dialog --backtitle "ProxMenux" \
|
dialog --backtitle "ProxMenux" --colors \
|
||||||
--msgbox "$(hb_translate "apt-get install sshpass failed. Falling back to manual mode.")" 8 70
|
--msgbox "$(hb_translate "Could not install sshpass automatically (no internet?). Falling back to manual paste mode — you'll see the line to copy onto the server next.")" 11 78
|
||||||
hb_borg_generate_and_install_key "$borg_user" "$host" "$rpath" "generate-manual" "$_out_var"
|
|
||||||
return $?
|
|
||||||
}
|
|
||||||
else
|
|
||||||
hb_borg_generate_and_install_key "$borg_user" "$host" "$rpath" "generate-manual" "$_out_var"
|
hb_borg_generate_and_install_key "$borg_user" "$host" "$rpath" "generate-manual" "$_out_var"
|
||||||
return $?
|
return $?
|
||||||
fi
|
fi
|
||||||
@@ -1313,6 +1429,47 @@ hb_borg_generate_and_install_key() {
|
|||||||
"$(hb_translate "Password for") ${admin_user}@${host}:" \
|
"$(hb_translate "Password for") ${admin_user}@${host}:" \
|
||||||
"$HB_UI_PASS_H" "$HB_UI_PASS_W" "" 3>&1 1>&2 2>&3) || return 1
|
"$HB_UI_PASS_H" "$HB_UI_PASS_W" "" 3>&1 1>&2 2>&3) || return 1
|
||||||
|
|
||||||
|
# Quick probe: many Debian-based servers (including LXC templates)
|
||||||
|
# ship with `PermitRootLogin prohibit-password`, which rejects the
|
||||||
|
# sshpass push BEFORE the password is even checked. Detect that here
|
||||||
|
# and fall back to manual mode with a clear explanation instead of
|
||||||
|
# the generic "could not push the key" error.
|
||||||
|
local _probe
|
||||||
|
_probe=$(SSHPASS="$admin_pass" sshpass -e ssh \
|
||||||
|
-o StrictHostKeyChecking=accept-new \
|
||||||
|
-o PreferredAuthentications=password -o PubkeyAuthentication=no \
|
||||||
|
-o NumberOfPasswordPrompts=1 -o ConnectTimeout=10 \
|
||||||
|
"$admin_user@$host" "true" 2>&1) || true
|
||||||
|
if echo "$_probe" | grep -qiE "permission denied[[:space:]]*\(publickey"; then
|
||||||
|
# SSH password auth refused by the server — common when the Borg
|
||||||
|
# server is a Debian/LXC with PermitRootLogin prohibit-password.
|
||||||
|
# Before falling back to manual paste, offer the pct-exec path,
|
||||||
|
# which is the right automatic alternative for the very common
|
||||||
|
# "Borg server is an LXC on another PVE host" setup.
|
||||||
|
local _alt
|
||||||
|
_alt=$(dialog --backtitle "ProxMenux" --colors \
|
||||||
|
--title "$(hb_translate "SSH password auth refused on server")" \
|
||||||
|
--default-item "pct" \
|
||||||
|
--menu "\n$(hb_translate "The server refused password authentication for") \Z1${admin_user}\Zn $(hb_translate "(common default on Debian/LXC: PermitRootLogin prohibit-password).")"$'\n\n'"$(hb_translate "Pick an alternative way to authorize the new key:")" \
|
||||||
|
"$HB_UI_MENU_H" "$HB_UI_MENU_W" "$HB_UI_MENU_LIST" \
|
||||||
|
"pct" "$(hb_translate "Authorize via 'pct exec' (Borg server is an LXC on a PVE host I can SSH into)")" \
|
||||||
|
"manual" "$(hb_translate "Show me the line to paste manually on the server")" \
|
||||||
|
"cancel" "$(hb_translate "Cancel this setup")" \
|
||||||
|
3>&1 1>&2 2>&3) || return 1
|
||||||
|
case "$_alt" in
|
||||||
|
pct) hb_borg_generate_and_install_key "$borg_user" "$host" "$rpath" "generate-pct" "$_out_var"; return $? ;;
|
||||||
|
manual) hb_borg_generate_and_install_key "$borg_user" "$host" "$rpath" "generate-manual" "$_out_var"; return $? ;;
|
||||||
|
*) return 1 ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
if echo "$_probe" | grep -qiE "permission denied"; then
|
||||||
|
dialog --backtitle "ProxMenux" --colors \
|
||||||
|
--title "$(hb_translate "SSH login failed")" \
|
||||||
|
--msgbox "$(hb_translate "The server rejected") \Zb${admin_user}\ZB $(hb_translate "with the password you provided.")"$'\n\n'"$(hb_translate "Verify the credentials. Switching to manual paste mode so you can finish the setup without re-typing the password.")" 12 78
|
||||||
|
hb_borg_generate_and_install_key "$borg_user" "$host" "$rpath" "generate-manual" "$_out_var"
|
||||||
|
return $?
|
||||||
|
fi
|
||||||
|
|
||||||
# Append the authorized line. We pipe through stdin so the password
|
# Append the authorized line. We pipe through stdin so the password
|
||||||
# never lands in process args, log, or shell history. -t allocates
|
# never lands in process args, log, or shell history. -t allocates
|
||||||
# a tty so password-prompting sudo still works if admin_user is
|
# a tty so password-prompting sudo still works if admin_user is
|
||||||
@@ -1433,8 +1590,16 @@ hb_configure_borg_manual() {
|
|||||||
;;
|
;;
|
||||||
remote)
|
remote)
|
||||||
local user host rpath
|
local user host rpath
|
||||||
user=$(dialog --backtitle "ProxMenux" --inputbox "$(hb_translate "SSH user:")" \
|
# Explicit label + default `borg` — this is the user that runs
|
||||||
"$HB_UI_INPUT_H" "$HB_UI_INPUT_W" "root" 3>&1 1>&2 2>&3) || return 1
|
# `borg serve` on the remote host, NOT the admin user we'd log
|
||||||
|
# in as. Calling it just "SSH user" with default root led to
|
||||||
|
# users typing their admin credentials here, which then failed
|
||||||
|
# later when generate-auto looked for ~root/.ssh/ instead of
|
||||||
|
# ~borg/.ssh/ on the server.
|
||||||
|
user=$(dialog --backtitle "ProxMenux" \
|
||||||
|
--title "$(hb_translate "Borg server SSH user")" \
|
||||||
|
--inputbox "$(hb_translate "Username on the Borg server that runs \"borg serve\" (typically \"borg\"). This is NOT the admin/root user of the server — that one is asked later only if you choose \"Generate a new key and authorize it\".")" \
|
||||||
|
12 78 "borg" 3>&1 1>&2 2>&3) || return 1
|
||||||
host=$(dialog --backtitle "ProxMenux" --inputbox "$(hb_translate "SSH host or IP:")" \
|
host=$(dialog --backtitle "ProxMenux" --inputbox "$(hb_translate "SSH host or IP:")" \
|
||||||
"$HB_UI_INPUT_H" "$HB_UI_INPUT_W" "" 3>&1 1>&2 2>&3) || return 1
|
"$HB_UI_INPUT_H" "$HB_UI_INPUT_W" "" 3>&1 1>&2 2>&3) || return 1
|
||||||
rpath=$(dialog --backtitle "ProxMenux" \
|
rpath=$(dialog --backtitle "ProxMenux" \
|
||||||
@@ -1453,29 +1618,79 @@ hb_configure_borg_manual() {
|
|||||||
local key_mode
|
local key_mode
|
||||||
key_mode=$(dialog --backtitle "ProxMenux" \
|
key_mode=$(dialog --backtitle "ProxMenux" \
|
||||||
--title "$(hb_translate "SSH key strategy")" \
|
--title "$(hb_translate "SSH key strategy")" \
|
||||||
|
--default-item "generate-auto" \
|
||||||
--menu "\n$(hb_translate "How do you want to authenticate this backup target?")" \
|
--menu "\n$(hb_translate "How do you want to authenticate this backup target?")" \
|
||||||
"$HB_UI_MENU_H" "$HB_UI_MENU_W" "$HB_UI_MENU_LIST" \
|
"$HB_UI_MENU_H" "$HB_UI_MENU_W" "$HB_UI_MENU_LIST" \
|
||||||
|
"generate-auto" "$(hb_translate "Generate a new key and authorize it on the server automatically (recommended)")" \
|
||||||
|
"generate-manual" "$(hb_translate "Generate a new key, show me the line to paste manually")" \
|
||||||
"existing" "$(hb_translate "Use an existing SSH private key file on this host")" \
|
"existing" "$(hb_translate "Use an existing SSH private key file on this host")" \
|
||||||
"generate-auto" "$(hb_translate "Generate a new key and authorize it on the server now (one-time password)")" \
|
|
||||||
"generate-manual" "$(hb_translate "Generate a new key, show me the line to paste on the server")" \
|
|
||||||
"none" "$(hb_translate "No custom key (rely on default SSH config)")" \
|
"none" "$(hb_translate "No custom key (rely on default SSH config)")" \
|
||||||
3>&1 1>&2 2>&3) || return 1
|
3>&1 1>&2 2>&3) || return 1
|
||||||
|
|
||||||
case "$key_mode" in
|
case "$key_mode" in
|
||||||
existing)
|
existing)
|
||||||
while :; do
|
# Auto-detect SSH private keys instead of forcing the
|
||||||
ssh_key=$(dialog --backtitle "ProxMenux" \
|
# operator through dialog's `--fselect`, which is
|
||||||
--title "$(hb_translate "Select SSH private key file")" \
|
# confusing (no extension filter, easy to pick the .pub
|
||||||
--fselect "$HOME/.ssh/" 14 76 3>&1 1>&2 2>&3) || return 1
|
# by mistake, hard to navigate paths). Each candidate
|
||||||
ssh_key="${ssh_key%"${ssh_key##*[![:space:]]}"}"
|
# is verified to actually be a parseable private key
|
||||||
[[ -f "$ssh_key" ]] && break
|
# via `ssh-keygen -y -f`.
|
||||||
dialog --backtitle "ProxMenux" \
|
local -a candidates=()
|
||||||
--title "$(hb_translate "Invalid selection")" \
|
local _f
|
||||||
--msgbox "$(hb_translate "You picked a directory or a missing file. Select the SSH private key file itself (e.g. ~/.ssh/id_ed25519), not its parent folder.")" \
|
for _f in /root/.ssh/* "$HOME/.ssh"/*; do
|
||||||
10 70
|
[[ -f "$_f" ]] || continue
|
||||||
|
case "$(basename "$_f")" in
|
||||||
|
*.pub|authorized_keys|known_hosts*|config) continue ;;
|
||||||
|
esac
|
||||||
|
if ssh-keygen -y -f "$_f" >/dev/null 2>&1; then
|
||||||
|
candidates+=("$_f")
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
|
# Dedup (HOME and /root may overlap on root-owned installs).
|
||||||
|
mapfile -t candidates < <(printf '%s\n' "${candidates[@]}" | sort -u)
|
||||||
|
|
||||||
|
local -a key_menu=()
|
||||||
|
local _i=1
|
||||||
|
for _f in "${candidates[@]}"; do
|
||||||
|
key_menu+=("$_i" "$_f")
|
||||||
|
((_i++))
|
||||||
|
done
|
||||||
|
local _browse_idx="$_i"
|
||||||
|
key_menu+=("$_browse_idx" "$(hb_translate "Browse manually (advanced)...")")
|
||||||
|
|
||||||
|
local _choice
|
||||||
|
if (( ${#candidates[@]} == 0 )); then
|
||||||
|
# Nothing auto-detected → go straight to manual browse.
|
||||||
|
_choice="$_browse_idx"
|
||||||
|
else
|
||||||
|
_choice=$(dialog --backtitle "ProxMenux" \
|
||||||
|
--title "$(hb_translate "Select SSH private key")" \
|
||||||
|
--default-item "1" \
|
||||||
|
--menu "\n$(hb_translate "Pick an SSH private key (auto-detected on this host):")" \
|
||||||
|
"$HB_UI_MENU_H" "$HB_UI_MENU_W" "$HB_UI_MENU_LIST" "${key_menu[@]}" \
|
||||||
|
3>&1 1>&2 2>&3) || return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$_choice" == "$_browse_idx" ]]; then
|
||||||
|
# Manual fselect fallback (key in a non-standard path).
|
||||||
|
while :; do
|
||||||
|
ssh_key=$(dialog --backtitle "ProxMenux" \
|
||||||
|
--title "$(hb_translate "Select SSH private key file")" \
|
||||||
|
--fselect "$HOME/.ssh/" 14 76 3>&1 1>&2 2>&3) || return 1
|
||||||
|
ssh_key="${ssh_key%"${ssh_key##*[![:space:]]}"}"
|
||||||
|
if [[ -f "$ssh_key" ]] && ssh-keygen -y -f "$ssh_key" >/dev/null 2>&1; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
dialog --backtitle "ProxMenux" \
|
||||||
|
--title "$(hb_translate "Invalid selection")" \
|
||||||
|
--msgbox "$(hb_translate "That doesn't look like an SSH private key. Pick the private key file (no .pub extension, parseable by ssh-keygen).")" \
|
||||||
|
10 72
|
||||||
|
done
|
||||||
|
else
|
||||||
|
ssh_key="${candidates[$((_choice-1))]}"
|
||||||
|
fi
|
||||||
;;
|
;;
|
||||||
generate-auto|generate-manual)
|
generate-auto|generate-manual|generate-pct)
|
||||||
if ! hb_borg_generate_and_install_key "$user" "$host" "$rpath" "$key_mode" ssh_key; then
|
if ! hb_borg_generate_and_install_key "$user" "$host" "$rpath" "$key_mode" ssh_key; then
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|||||||
Reference in New Issue
Block a user