From 7c35ceaacfff44c0ca822ce32fbe27d5746db5ae Mon Sep 17 00:00:00 2001 From: MickLesk <47820557+MickLesk@users.noreply.github.com> Date: Thu, 29 Oct 2026 15:56:00 +0100 Subject: [PATCH 1/3] Add var_cmode to set the container console mode pct leaves cmode at tty. On Debian 13 that console corrupts multiline pastes (community-scripts/ProxmoxVE#18303), and cmode shell avoids it, but it also skips the login prompt - so this stays opt-in instead of becoming a new default. --- pve/backend.func | 13 +++++++++++++ ui/advanced.func | 1 + ui/defaults.func | 16 +++++++++++++--- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/pve/backend.func b/pve/backend.func index 009326b..8f840ab 100644 --- a/pve/backend.func +++ b/pve/backend.func @@ -620,6 +620,19 @@ $PCT_OPTIONS_STRING" -protection 1" fi + # Console mode (if var_cmode was set); pct takes shell, console or tty + if [ -n "${CT_CMODE:-}" ]; then + case "$CT_CMODE" in + shell | console | tty) + PCT_OPTIONS_STRING="$PCT_OPTIONS_STRING + -cmode $CT_CMODE" + ;; + *) + msg_warn "Console mode '${CT_CMODE}' is not shell, console or tty; the container keeps the Proxmox default (tty)." + ;; + esac + fi + # pct takes UTC or a zone.tab name only; aliases resolve, "host" is read here if [ -n "${CT_TIMEZONE:-}" ]; then local _pct_timezone diff --git a/ui/advanced.func b/ui/advanced.func index 080ba4b..6dd330f 100644 --- a/ui/advanced.func +++ b/ui/advanced.func @@ -1276,6 +1276,7 @@ Advanced: [[ "${ENABLE_MKNOD:-0}" == "1" ]] && echo -e "${CONTAINERTYPE}${BOLD}${DGN}Mknod: ${BGN}Enabled${CL}" [[ -n "${ALLOW_MOUNT_FS:-}" ]] && echo -e "${CONTAINERTYPE}${BOLD}${DGN}Mount FS: ${BGN}${ALLOW_MOUNT_FS}${CL}" [[ "${PROTECT_CT:-no}" == "yes" || "${PROTECT_CT:-no}" == "1" ]] && echo -e "${CONTAINERTYPE}${BOLD}${DGN}Protection: ${BGN}Enabled${CL}" + [[ -n "${CT_CMODE:-}" ]] && echo -e "${INFO}${BOLD}${DGN}Console Mode: ${BGN}$CT_CMODE${CL}" [[ -n "${CT_TIMEZONE:-}" ]] && echo -e "${INFO}${BOLD}${DGN}Timezone: ${BGN}$CT_TIMEZONE${CL}" [[ "$APT_CACHER" == "yes" ]] && echo -e "${INFO}${BOLD}${DGN}APT Cacher: ${BGN}$APT_CACHER_IP${CL}" [[ -n "${HTTP_PROXY:-}" ]] && echo -e "${INFO}${BOLD}${DGN}HTTP Proxy: ${BGN}$HTTP_PROXY${CL}" diff --git a/ui/defaults.func b/ui/defaults.func index d7ffc7b..64548f0 100644 --- a/ui/defaults.func +++ b/ui/defaults.func @@ -366,6 +366,7 @@ base_settings() { ENABLE_MKNOD=${var_mknod:-"0"} ALLOW_MOUNT_FS=${var_mount_fs:-""} PROTECT_CT=${var_protection:-"no"} + CT_CMODE=${var_cmode:-""} CT_TIMEZONE=${var_timezone:-"$timezone"} [[ "${CT_TIMEZONE:-}" == Etc/* ]] && CT_TIMEZONE="host" # pct doesn't accept Etc/* zones @@ -421,7 +422,7 @@ load_vars_file() { # Allowed var_* keys local VAR_WHITELIST=( - var_apt_cacher var_apt_cacher_ip var_brg var_cpu var_disk var_fuse var_github_token var_gpu var_http_no_proxy var_http_proxy var_inherit_host_ca var_keyctl + var_apt_cacher var_apt_cacher_ip var_brg var_cmode var_cpu var_disk var_fuse var_github_token var_gpu var_http_no_proxy var_http_proxy var_inherit_host_ca var_keyctl var_gateway var_hostname var_ipv6_method var_mac var_mknod var_mount_fs var_mtu var_net var_nesting var_ns var_os var_post_install var_protection var_pw var_ram var_sdn_vnet var_searchdomain var_tags var_timezone var_tun var_unprivileged var_verbose var_version var_vlan var_ssh var_ssh_authorized_key var_container_storage var_template_storage @@ -597,6 +598,12 @@ load_vars_file() { continue fi ;; + var_cmode) + if [[ "$var_val" != "shell" && "$var_val" != "console" && "$var_val" != "tty" ]]; then + msg_warn "Invalid console mode '$var_val' for $var_key in $file (must be shell/console/tty), ignoring" + continue + fi + ;; var_ipv6_method) if [[ "$var_val" != "auto" && "$var_val" != "dhcp" && "$var_val" != "static" && "$var_val" != "none" ]]; then msg_warn "Invalid IPv6 method '$var_val' in $file (must be auto/dhcp/static/none), ignoring" @@ -674,7 +681,7 @@ default_var_settings() { # Allowed var_* keys (alphabetically sorted) # Note: Removed var_ctid (can only exist once), var_ipv6_static (static IPs are unique) local VAR_WHITELIST=( - var_apt_cacher var_apt_cacher_ip var_brg var_cpu var_disk var_fuse var_github_token var_gpu var_http_no_proxy var_http_proxy var_inherit_host_ca var_keyctl + var_apt_cacher var_apt_cacher_ip var_brg var_cmode var_cpu var_disk var_fuse var_github_token var_gpu var_http_no_proxy var_http_proxy var_inherit_host_ca var_keyctl var_gateway var_hostname var_ipv6_method var_mac var_mknod var_mount_fs var_mtu var_net var_nesting var_ns var_os var_post_install var_protection var_pw var_ram var_sdn_vnet var_searchdomain var_tags var_timezone var_tun var_unprivileged var_verbose var_version var_vlan var_ssh var_ssh_authorized_key var_container_storage var_template_storage @@ -774,6 +781,7 @@ var_mknod=0 # Allow device node creation var_mount_fs= # Allow specific filesystems: nfs,fuse,ext4,etc (leave empty for defaults) var_protection=no # Prevent accidental deletion of container var_timezone= # Container timezone (e.g. Europe/Berlin, leave empty for host timezone) +var_cmode= # Console mode: shell, console or tty (leave empty for the Proxmox default) var_tags=community-script var_verbose=no @@ -866,7 +874,7 @@ get_app_defaults_path() { if ! declare -p VAR_WHITELIST >/dev/null 2>&1; then # Note: Removed var_ctid (can only exist once), var_ipv6_static (static IPs are unique) declare -ag VAR_WHITELIST=( - var_apt_cacher var_apt_cacher_ip var_brg var_cpu var_disk var_fuse var_github_token var_gpu var_http_no_proxy var_http_proxy var_inherit_host_ca var_keyctl + var_apt_cacher var_apt_cacher_ip var_brg var_cmode var_cpu var_disk var_fuse var_github_token var_gpu var_http_no_proxy var_http_proxy var_inherit_host_ca var_keyctl var_gateway var_hostname var_ipv6_method var_mac var_mknod var_mount_fs var_mtu var_net var_nesting var_ns var_os var_post_install var_protection var_pw var_ram var_sdn_vnet var_searchdomain var_tags var_timezone var_tun var_unprivileged var_verbose var_version var_vlan var_ssh var_ssh_authorized_key var_container_storage var_template_storage @@ -1031,6 +1039,7 @@ _build_current_app_vars_tmp() { _mknod="${ENABLE_MKNOD:-0}" _mount_fs="${ALLOW_MOUNT_FS:-}" _protect="${PROTECT_CT:-no}" + _cmode="${CT_CMODE:-}" _timezone="${CT_TIMEZONE:-}" _tags="${TAGS:-}" _verbose="${VERBOSE:-no}" @@ -1084,6 +1093,7 @@ _build_current_app_vars_tmp() { [ -n "$_mknod" ] && echo "var_mknod=$(_sanitize_value "$_mknod")" [ -n "$_mount_fs" ] && echo "var_mount_fs=$(_sanitize_value "$_mount_fs")" [ -n "$_protect" ] && echo "var_protection=$(_sanitize_value "$_protect")" + [ -n "$_cmode" ] && echo "var_cmode=$(_sanitize_value "$_cmode")" [ -n "$_timezone" ] && echo "var_timezone=$(_sanitize_value "$_timezone")" [ -n "$_tags" ] && echo "var_tags=$(_sanitize_value "$_tags")" [ -n "$_verbose" ] && echo "var_verbose=$(_sanitize_value "$_verbose")" From 9fdbfdf524f496498aa71a11349edbe3bdb9be6f Mon Sep 17 00:00:00 2001 From: MickLesk <47820557+MickLesk@users.noreply.github.com> Date: Thu, 29 Oct 2026 17:32:55 +0100 Subject: [PATCH 2/3] Offer the console mode in the advanced wizard New step 28 between Container Protection and mknod; the steps after it shift by one and MAX_STEP goes to 32. Picking tty clears the value rather than passing -cmode tty, since that is what pct does anyway. --- ui/advanced.func | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/ui/advanced.func b/ui/advanced.func index 6dd330f..9aa2982 100644 --- a/ui/advanced.func +++ b/ui/advanced.func @@ -37,7 +37,7 @@ advanced_settings() { TAGS="community-script${var_tags:+;${var_tags}}" fi local STEP=1 - local MAX_STEP=31 + local MAX_STEP=32 # Store values for back navigation - inherit from var_* app defaults local _ct_type="${var_unprivileged:-1}" @@ -76,6 +76,7 @@ advanced_settings() { local _enable_mknod="${var_mknod:-0}" local _mount_fs="${var_mount_fs:-}" local _protect_ct="${var_protection:-no}" + local _ct_cmode="${var_cmode:-}" local _post_install="${var_post_install:-}" # Detect host timezone for default (if not set via var_timezone) @@ -998,9 +999,30 @@ advanced_settings() { ;; # ═══════════════════════════════════════════════════════════════════════════ - # STEP 28: Device Node Creation (mknod) + # STEP 28: Console Mode # ═══════════════════════════════════════════════════════════════════════════ 28) + if result=$(whiptail --backtitle "Proxmox VE Helper Scripts [Step $STEP/$MAX_STEP]" \ + --title "CONSOLE MODE" \ + --ok-button "Next" --cancel-button "Back" \ + --default-item "${_ct_cmode:-tty}" \ + --menu "\nHow the Proxmox web console attaches to the container.\n\nshell has no login prompt - console access alone is root.\n\n(App default: ${var_cmode:-tty})" 18 74 3 \ + "tty" "Login prompt on a virtual terminal (Proxmox default)" \ + "console" "Login prompt on /dev/console" \ + "shell" "Root shell, no login prompt (multiline paste works)" \ + 3>&1 1>&2 2>&3); then + [[ "$result" == "tty" ]] && result="" + _ct_cmode="$result" + ((STEP++)) + else + ((STEP--)) + fi + ;; + + # ═══════════════════════════════════════════════════════════════════════════ + # STEP 29: Device Node Creation (mknod) + # ═══════════════════════════════════════════════════════════════════════════ + 29) local mknod_default_flag="--defaultno" [[ "$_enable_mknod" == "1" ]] && mknod_default_flag="" @@ -1022,9 +1044,9 @@ advanced_settings() { ;; # ═══════════════════════════════════════════════════════════════════════════ - # STEP 29: Mount Filesystems + # STEP 30: Mount Filesystems # ═══════════════════════════════════════════════════════════════════════════ - 29) + 30) local mount_hint="" [[ -n "$_mount_fs" ]] && mount_hint="$_mount_fs" || mount_hint="(none)" @@ -1048,9 +1070,9 @@ advanced_settings() { ;; # ═══════════════════════════════════════════════════════════════════════════ - # STEP 30: Optional host-side post-install hook (path on the Proxmox HOST) + # STEP 31: Optional host-side post-install hook (path on the Proxmox HOST) # ═══════════════════════════════════════════════════════════════════════════ - 30) + 31) local _hook_prompt="Optional: absolute path to a *.sh file ON THE PROXMOX HOST. It runs as root on the HOST (NOT in the LXC) after the container @@ -1098,9 +1120,9 @@ Leave empty to skip." ;; # ═══════════════════════════════════════════════════════════════════════════ - # STEP 31: Verbose Mode & Confirmation + # STEP 32: Verbose Mode & Confirmation # ═══════════════════════════════════════════════════════════════════════════ - 31) + 32) local verbose_default_flag="--defaultno" [[ "$_verbose" == "yes" ]] && verbose_default_flag="" @@ -1203,6 +1225,7 @@ Advanced: ENABLE_MKNOD="$_enable_mknod" ALLOW_MOUNT_FS="$_mount_fs" PROTECT_CT="$_protect_ct" + CT_CMODE="$_ct_cmode" CT_TIMEZONE="$_ct_timezone" APT_CACHER="$_apt_cacher" APT_CACHER_IP="$_apt_cacher_ip" @@ -1222,6 +1245,7 @@ Advanced: var_mknod="$_enable_mknod" var_mount_fs="$_mount_fs" var_protection="$_protect_ct" + var_cmode="$_ct_cmode" var_timezone="$_ct_timezone" var_apt_cacher="$_apt_cacher" var_apt_cacher_ip="$_apt_cacher_ip" From 54135ffec5a45988c157ad5766c6754acfedf325 Mon Sep 17 00:00:00 2001 From: MickLesk <47820557+MickLesk@users.noreply.github.com> Date: Thu, 29 Oct 2026 17:38:58 +0100 Subject: [PATCH 3/3] Say what the console modes actually do in our containers Without var_pw, lxc/install.func deletes the root password and puts --autologin root on both container-getty@ and console-getty, so tty and console already drop into a root shell. The dialog claimed they showed a login prompt and that only shell skipped it; that is only true once var_pw is set. --- ui/advanced.func | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ui/advanced.func b/ui/advanced.func index 9aa2982..4956a5e 100644 --- a/ui/advanced.func +++ b/ui/advanced.func @@ -1006,10 +1006,10 @@ advanced_settings() { --title "CONSOLE MODE" \ --ok-button "Next" --cancel-button "Back" \ --default-item "${_ct_cmode:-tty}" \ - --menu "\nHow the Proxmox web console attaches to the container.\n\nshell has no login prompt - console access alone is root.\n\n(App default: ${var_cmode:-tty})" 18 74 3 \ - "tty" "Login prompt on a virtual terminal (Proxmox default)" \ - "console" "Login prompt on /dev/console" \ - "shell" "Root shell, no login prompt (multiline paste works)" \ + --menu "\nHow the Proxmox web console attaches to the container.\n\nWithout var_pw we autologin root on tty and console, so all three\nmodes land in a root shell. With var_pw set, only shell skips the\nlogin prompt.\n\n(App default: ${var_cmode:-tty})" 20 76 3 \ + "tty" "Virtual terminal, /dev/tty1 (Proxmox default)" \ + "console" "/dev/console, same as pct console" \ + "shell" "Attach a root shell directly (multiline paste works)" \ 3>&1 1>&2 2>&3); then [[ "$result" == "tty" ]] && result="" _ct_cmode="$result"