From 7455f8195cffd1fd06482cc3ba52dfce72b31c80 Mon Sep 17 00:00:00 2001 From: CanbiZ <47820557+MickLesk@users.noreply.github.com> Date: Mon, 24 Nov 2025 11:35:10 +0100 Subject: [PATCH] Update build.func --- misc/build.func | 499 +++++++++++++----------------------------------- 1 file changed, 131 insertions(+), 368 deletions(-) diff --git a/misc/build.func b/misc/build.func index 564f4f02e..b0b0404cd 100644 --- a/misc/build.func +++ b/misc/build.func @@ -47,17 +47,7 @@ variables() { METHOD="default" # sets the METHOD variable to "default", used for the API call. RANDOM_UUID="$(cat /proc/sys/kernel/random/uuid)" # generates a random UUID and sets it to the RANDOM_UUID variable. SESSION_ID="${RANDOM_UUID:0:8}" # Short session ID (first 8 chars of UUID) for log files - BUILD_LOG="/tmp/create-lxc-${SESSION_ID}.log" # Host-side container creation log - CTTYPE="${CTTYPE:-${CT_TYPE:-1}}" - - # Parse dev_mode early - parse_dev_mode - - # Setup persistent log directory if logs mode active - if [[ "${DEV_MODE_LOGS:-false}" == "true" ]]; then - mkdir -p /var/log/community-scripts - BUILD_LOG="/var/log/community-scripts/create-lxc-${SESSION_ID}-$(date +%Y%m%d_%H%M%S).log" - fi + CTTYPE="${CTTYPE:-${CT_TYPE:-1}}"} # Get Proxmox VE version and kernel version if command -v pveversion >/dev/null 2>&1; then @@ -535,35 +525,6 @@ base_settings() { TAGS="community-script,${var_tags:-}" ENABLE_FUSE=${var_fuse:-"${1:-no}"} ENABLE_TUN=${var_tun:-"${1:-no}"} - ENABLE_NESTING=${var_nesting:-"${1:-1}"} - ENABLE_KEYCTL=${var_keyctl:-"${1:-0}"} - ALLOW_MOUNT_FS=${var_mount_fs:-""} - ENABLE_MKNOD=${var_mknod:-"${1:-0}"} - PROTECT_CT=${var_protection:-"${1:-no}"} - CT_TIMEZONE=${var_timezone:-""} - - # Normalize feature flags to 0/1 immediately (pct requires numeric values, not yes/no) - # This must happen here before any usage of these variables - case "${ENABLE_NESTING,,}" in - yes | true) ENABLE_NESTING="1" ;; - no | false) ENABLE_NESTING="0" ;; - esac - case "${ENABLE_KEYCTL,,}" in - yes | true) ENABLE_KEYCTL="1" ;; - no | false) ENABLE_KEYCTL="0" ;; - esac - case "${ENABLE_MKNOD,,}" in - yes | true) ENABLE_MKNOD="1" ;; - no | false) ENABLE_MKNOD="0" ;; - esac - case "${ENABLE_FUSE,,}" in - yes | true) ENABLE_FUSE="1" ;; - no | false) ENABLE_FUSE="0" ;; - esac - case "${PROTECT_CT,,}" in - yes | true) PROTECT_CT="1" ;; - no | false) PROTECT_CT="0" ;; - esac # Since these 2 are only defined outside of default_settings function, we add a temporary fallback. TODO: To align everything, we should add these as constant variables (e.g. OSTYPE and OSVERSION), but that would currently require updating the default_settings function for all existing scripts if [ -z "$var_os" ]; then @@ -587,9 +548,9 @@ 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_keyctl - var_gateway var_hostname var_ipv6_method var_mac var_mknod var_mount_fs var_mtu - var_net var_nesting var_ns var_protection var_pw var_ram var_tags var_timezone var_tun var_unprivileged + var_apt_cacher var_apt_cacher_ip var_brg var_cpu var_disk var_fuse + var_gateway var_hostname var_ipv6_method var_mac var_mtu + var_net var_ns var_pw var_ram var_tags var_tun var_unprivileged var_verbose var_vlan var_ssh var_ssh_authorized_key var_container_storage var_template_storage ) @@ -667,14 +628,6 @@ var_ssh=no # Features/Tags/verbosity var_fuse=no var_tun=no - -# Advanced Settings (Proxmox-official features) -var_nesting=1 # Allow nesting (required for Docker/LXC in CT) -var_keyctl=0 # Allow keyctl() - needed for Docker (systemd-networkd workaround) -var_mknod=0 # Allow device node creation (requires kernel 5.3+, experimental) -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_tags=community-script var_verbose=no @@ -941,12 +894,6 @@ _build_current_app_vars_tmp() { _apt_cacher_ip="${APT_CACHER_IP:-}" _fuse="${ENABLE_FUSE:-no}" _tun="${ENABLE_TUN:-no}" - _nesting="${ENABLE_NESTING:-1}" - _keyctl="${ENABLE_KEYCTL:-0}" - _mknod="${ENABLE_MKNOD:-0}" - _mount_fs="${ALLOW_MOUNT_FS:-}" - _protect="${PROTECT_CT:-no}" - _timezone="${CT_TIMEZONE:-}" _tags="${TAGS:-}" _verbose="${VERBOSE:-no}" @@ -990,12 +937,6 @@ _build_current_app_vars_tmp() { [ -n "$_fuse" ] && echo "var_fuse=$(_sanitize_value "$_fuse")" [ -n "$_tun" ] && echo "var_tun=$(_sanitize_value "$_tun")" - [ -n "$_nesting" ] && echo "var_nesting=$(_sanitize_value "$_nesting")" - [ -n "$_keyctl" ] && echo "var_keyctl=$(_sanitize_value "$_keyctl")" - [ -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 "$_timezone" ] && echo "var_timezone=$(_sanitize_value "$_timezone")" [ -n "$_tags" ] && echo "var_tags=$(_sanitize_value "$_tags")" [ -n "$_verbose" ] && echo "var_verbose=$(_sanitize_value "$_verbose")" @@ -1578,51 +1519,6 @@ advanced_settings() { configure_ssh_settings export SSH_KEYS_FILE echo -e "${ROOTSSH}${BOLD}${DGN}Root SSH Access: ${BGN}$SSH${CL}" - - # Advanced Settings - Proxmox Features - if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS" --yesno "Configure Advanced Proxmox Features?" 10 58); then - # keyctl: for Docker support - if (whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "Enable keyctl()" --yesno "Allow keyctl() system calls?\n\nNeeded for: Docker inside container, systemd-networkd\nDefault: No (not needed for most applications)" 10 58); then - ENABLE_KEYCTL="1" - else - ENABLE_KEYCTL="0" - fi - echo -e "${SEARCH}${BOLD}${DGN}Allow keyctl(): ${BGN}$ENABLE_KEYCTL${CL}" - - # mknod: device node creation - if (whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "Enable mknod()" --yesno "Allow device node creation?\n\nNeeded for: Complex device management (experimental, kernel 5.3+)\nDefault: No (rarely needed)" 10 58); then - ENABLE_MKNOD="1" - else - ENABLE_MKNOD="0" - fi - echo -e "${SEARCH}${BOLD}${DGN}Allow mknod(): ${BGN}$ENABLE_MKNOD${CL}" - - # mount: specific filesystems - if MOUNT_FS=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allow specific filesystems (e.g., nfs,fuse,ext4)\nLeave blank for defaults" 8 58 "$ALLOW_MOUNT_FS" --title "Mount Filesystems" 3>&1 1>&2 2>&3); then - ALLOW_MOUNT_FS="$MOUNT_FS" - [ -z "$ALLOW_MOUNT_FS" ] && ALLOW_MOUNT_FS="(defaults)" - else - exit_script - fi - echo -e "${SEARCH}${BOLD}${DGN}Mount Filesystems: ${BGN}$ALLOW_MOUNT_FS${CL}" - - # Container protection - if (whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "Protection Flag" --yesno "Prevent accidental deletion?\n\nIf enabled, container cannot be deleted or its disk modified\nDefault: No" 10 58); then - PROTECT_CT="yes" - else - PROTECT_CT="no" - fi - echo -e "${SEARCH}${BOLD}${DGN}Container Protection: ${BGN}$PROTECT_CT${CL}" - - # Container timezone - if CT_TIMEZONE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set container timezone (e.g., Europe/Berlin)\nLeave blank to use host timezone" 8 58 "$CT_TIMEZONE" --title "Container Timezone" 3>&1 1>&2 2>&3); then - [ -z "$CT_TIMEZONE" ] && CT_TIMEZONE="(host)" - else - exit_script - fi - echo -e "${SEARCH}${BOLD}${DGN}Container Timezone: ${BGN}$CT_TIMEZONE${CL}" - fi - if (whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "FUSE Support" --yesno "Enable FUSE support?\nRequired for tools like rclone, mergerfs, AppImage, etc." 10 58); then ENABLE_FUSE="yes" else @@ -1795,16 +1691,7 @@ install_script() { fi NEXTID=$(pvesh get /cluster/nextid) - - # Get timezone using timedatectl (Debian 13+ compatible) - # Fallback to /etc/timezone for older systems - if command -v timedatectl >/dev/null 2>&1; then - timezone=$(timedatectl show --value --property=Timezone 2>/dev/null || echo "UTC") - elif [ -f /etc/timezone ]; then - timezone=$(cat /etc/timezone) - else - timezone="UTC" - fi + timezone=$(cat /etc/timezone) # Show APP Header header_info @@ -1932,12 +1819,13 @@ settings_menu() { local settings_items=( "1" "Manage API-Diagnostic Setting" "2" "Edit Default.vars" + "3" "Edit Default Storage" ) if [ -f "$(get_app_defaults_path)" ]; then - settings_items+=("3" "Edit App.vars for ${APP}") - settings_items+=("4" "Exit") + settings_items+=("4" "Edit App.vars for ${APP}") + settings_items+=("5" "Exit") else - settings_items+=("3" "Exit") + settings_items+=("4" "Exit") fi local choice @@ -2298,34 +2186,14 @@ build_container() { none) ;; esac - # Build FEATURES array with advanced settings - # Note: All feature flags are already normalized to 0/1 in default_settings() - # Proxmox requires each feature as a separate parameter, not comma-separated string - FEATURES_ARRAY=() - FEATURES_ARRAY+=("nesting=${ENABLE_NESTING}") - - # keyctl: needed for Docker inside containers (systemd-networkd workaround) - # Typically needed for unprivileged containers with Docker - if [ "$CT_TYPE" == "1" ] || [ "$ENABLE_KEYCTL" == "1" ]; then - FEATURES_ARRAY+=("keyctl=1") + if [ "$CT_TYPE" == "1" ]; then + FEATURES="keyctl=1,nesting=1" + else + FEATURES="nesting=1" fi - # mknod: allow device node creation (requires kernel 5.3+, experimental) - if [ "$ENABLE_MKNOD" == "1" ]; then - FEATURES_ARRAY+=("mknod=1") - fi - - # FUSE: required for rclone, mergerfs, AppImage, etc. - if [ "$ENABLE_FUSE" == "1" ]; then - FEATURES_ARRAY+=("fuse=1") - fi - - # mount: allow specific filesystems (e.g., nfs, ext4, etc.) - # Format: mount=fstype1;fstype2;fstype3 (semicolon-separated, not comma!) - if [ -n "$ALLOW_MOUNT_FS" ]; then - # Replace commas with semicolons for proper pct syntax - ALLOW_MOUNT_FS_FORMATTED="${ALLOW_MOUNT_FS//,/;}" - FEATURES_ARRAY+=("mount=$ALLOW_MOUNT_FS_FORMATTED") + if [ "$ENABLE_FUSE" == "yes" ]; then + FEATURES="$FEATURES,fuse=1" fi TEMP_DIR=$(mktemp -d) @@ -2338,16 +2206,6 @@ build_container() { export DIAGNOSTICS="$DIAGNOSTICS" export RANDOM_UUID="$RANDOM_UUID" export SESSION_ID="$SESSION_ID" - export BUILD_LOG="$BUILD_LOG" - export INSTALL_LOG="/root/.install-${SESSION_ID}.log" - export dev_mode="${dev_mode:-}" - export DEV_MODE_MOTD="${DEV_MODE_MOTD:-false}" - export DEV_MODE_KEEP="${DEV_MODE_KEEP:-false}" - export DEV_MODE_TRACE="${DEV_MODE_TRACE:-false}" - export DEV_MODE_PAUSE="${DEV_MODE_PAUSE:-false}" - export DEV_MODE_BREAKPOINT="${DEV_MODE_BREAKPOINT:-false}" - export DEV_MODE_LOGS="${DEV_MODE_LOGS:-false}" - export DEV_MODE_DRYRUN="${DEV_MODE_DRYRUN:-false}" export CACHER="$APT_CACHER" export CACHER_IP="$APT_CACHER_IP" export tz="$timezone" @@ -2361,59 +2219,22 @@ build_container() { export CTTYPE="$CT_TYPE" export ENABLE_FUSE="$ENABLE_FUSE" export ENABLE_TUN="$ENABLE_TUN" - export ENABLE_NESTING="$ENABLE_NESTING" - export ENABLE_KEYCTL="$ENABLE_KEYCTL" - export ENABLE_MKNOD="$ENABLE_MKNOD" - export ALLOW_MOUNT_FS="$ALLOW_MOUNT_FS" - export PROTECT_CT="$PROTECT_CT" - export CT_TIMEZONE="$CT_TIMEZONE" export PCT_OSTYPE="$var_os" export PCT_OSVERSION="$var_version" export PCT_DISK_SIZE="$DISK_SIZE" - - # Build PCT_OPTIONS array (not string) for proper parameter handling - PCT_OPTIONS=() - - # Add features - each as separate -features parameter - for feature in "${FEATURES_ARRAY[@]}"; do - PCT_OPTIONS+=("-features" "$feature") - done - - PCT_OPTIONS+=("-hostname" "$HN") - PCT_OPTIONS+=("-tags" "$TAGS") - - if [ -n "$SD" ]; then - PCT_OPTIONS+=($SD) # Storage device flags (already formatted) - fi - - if [ -n "$NS" ]; then - PCT_OPTIONS+=($NS) # Nameserver flags (already formatted) - fi - - # Network configuration (single string with all network parameters) - PCT_OPTIONS+=($NET_STRING) - - PCT_OPTIONS+=("-onboot" "1") - PCT_OPTIONS+=("-cores" "$CORE_COUNT") - PCT_OPTIONS+=("-memory" "$RAM_SIZE") - PCT_OPTIONS+=("-unprivileged" "$CT_TYPE") - - # Protection flag - if [ "$PROTECT_CT" == "1" ]; then - PCT_OPTIONS+=("-protection" "1") - fi - - # Timezone flag - if [ -n "$CT_TIMEZONE" ]; then - PCT_OPTIONS+=("-timezone" "$CT_TIMEZONE") - fi - - # Password flag (already formatted as "-password xxx") - if [ -n "$PW" ]; then - PCT_OPTIONS+=($PW) - fi - - export PCT_OPTIONS + export PCT_OPTIONS=" + -features $FEATURES + -hostname $HN + -tags $TAGS + $SD + $NS + $NET_STRING + -onboot 1 + -cores $CORE_COUNT + -memory $RAM_SIZE + -unprivileged $CT_TYPE + $PW +" export TEMPLATE_STORAGE="${var_template_storage:-}" export CONTAINER_STORAGE="${var_container_storage:-}" create_lxc_container || exit $? @@ -2588,13 +2409,20 @@ EOF [[ "$selected_gpu" == "INTEL" ]] && devices=("${INTEL_DEVICES[@]}") [[ "$selected_gpu" == "AMD" ]] && devices=("${AMD_DEVICES[@]}") - # Use pct set to add devices with proper dev0/dev1 format - # GIDs will be detected and set after container starts - local dev_index=0 + # Add lxc.mount.entry for each device for dev in "${devices[@]}"; do - # Add to config using pct set (will be visible in GUI) - echo "dev${dev_index}: ${dev},gid=44" >>"$LXC_CONFIG" - dev_index=$((dev_index + 1)) + echo "lxc.mount.entry: $dev $dev none bind,optional,create=file" >>"$LXC_CONFIG" + + if [[ "$CT_TYPE" == "0" ]]; then + # Privileged container - also add cgroup allows + local major minor + major=$(stat -c '%t' "$dev" 2>/dev/null || echo "0") + minor=$(stat -c '%T' "$dev" 2>/dev/null || echo "0") + + if [[ "$major" != "0" && "$minor" != "0" ]]; then + echo "lxc.cgroup2.devices.allow: c $((0x$major)):$((0x$minor)) rwm" >>"$LXC_CONFIG" + fi + fi done export GPU_TYPE="$selected_gpu" @@ -2607,11 +2435,20 @@ EOF return 0 fi - # Use pct set for NVIDIA devices - local dev_index=0 + # Add lxc.mount.entry for each NVIDIA device for dev in "${NVIDIA_DEVICES[@]}"; do - echo "dev${dev_index}: ${dev},gid=44" >>"$LXC_CONFIG" - dev_index=$((dev_index + 1)) + echo "lxc.mount.entry: $dev $dev none bind,optional,create=file" >>"$LXC_CONFIG" + + if [[ "$CT_TYPE" == "0" ]]; then + # Privileged container - also add cgroup allows + local major minor + major=$(stat -c '%t' "$dev" 2>/dev/null || echo "0") + minor=$(stat -c '%T' "$dev" 2>/dev/null || echo "0") + + if [[ "$major" != "0" && "$minor" != "0" ]]; then + echo "lxc.cgroup2.devices.allow: c $((0x$major)):$((0x$minor)) rwm" >>"$LXC_CONFIG" + fi + fi done export GPU_TYPE="NVIDIA" @@ -2723,9 +2560,7 @@ EOF' fi if pct exec "$CTID" -- test -e "/usr/share/zoneinfo/$tz"; then - # Set timezone using symlink (Debian 13+ compatible) - # Create /etc/timezone for backwards compatibility with older scripts - pct exec "$CTID" -- bash -c "tz='$tz'; ln -sf \"/usr/share/zoneinfo/\$tz\" /etc/localtime && echo \"\$tz\" >/etc/timezone || true" + pct exec "$CTID" -- bash -c "tz='$tz'; echo \"\$tz\" >/etc/timezone && ln -sf \"/usr/share/zoneinfo/\$tz\" /etc/localtime" else msg_warn "Skipping timezone setup – zone '$tz' not found in container" fi @@ -2741,121 +2576,14 @@ EOF' # Install SSH keys install_ssh_keys_into_ct - # Dev mode: Setup MOTD/SSH AFTER network is ready and before installation - # This ensures the container is fully booted and accessible via SSH - if [[ "${DEV_MODE_MOTD:-false}" == "true" ]]; then - msg_dev "Setting up MOTD and SSH for debugging access" - pct exec "$CTID" -- bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/install/${var_install}.sh)" <<'MOTD_SETUP' - # Only run motd_ssh function if it exists - if declare -f motd_ssh >/dev/null 2>&1; then - motd_ssh - else - msg_warn "motd_ssh function not found in ${var_install}.sh" - fi -MOTD_SETUP - msg_dev "MOTD/SSH ready - container accessible via SSH (IP: $ip_in_lxc)" - fi - # Run application installer - # NOTE: We disable error handling here because: - # 1. Container errors are caught by error_handler INSIDE container - # 2. Container creates flag file with exit code - # 3. We read flag file and handle cleanup manually below - # 4. We DON'T want host error_handler to fire for lxc-attach command itself - - set +Eeuo pipefail # Disable ALL error handling temporarily - trap - ERR # Remove ERR trap completely - - lxc-attach -n "$CTID" -- bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/install/${var_install}.sh)" - local lxc_exit=$? - - set -Eeuo pipefail # Re-enable error handling - trap 'error_handler' ERR # Restore ERR trap - - # Check for error flag file in container (more reliable than lxc-attach exit code) - local install_exit_code=0 - if [[ -n "${SESSION_ID:-}" ]]; then - local error_flag="/root/.install-${SESSION_ID}.failed" - if pct exec "$CTID" -- test -f "$error_flag" 2>/dev/null; then - install_exit_code=$(pct exec "$CTID" -- cat "$error_flag" 2>/dev/null || echo "1") - pct exec "$CTID" -- rm -f "$error_flag" 2>/dev/null || true - fi - fi - - # Fallback to lxc-attach exit code if no flag file - if [[ $install_exit_code -eq 0 && $lxc_exit -ne 0 ]]; then - install_exit_code=$lxc_exit - fi - - # Installation failed? - if [[ $install_exit_code -ne 0 ]]; then - msg_error "Installation failed in container ${CTID} (exit code: ${install_exit_code})" - - # Copy both logs from container before potential deletion - local build_log_copied=false - local install_log_copied=false - + if ! lxc-attach -n "$CTID" -- bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/install/${var_install}.sh)"; then + local exit_code=$? + # Try to copy installation log from container before exiting if [[ -n "$CTID" && -n "${SESSION_ID:-}" ]]; then - # Copy BUILD_LOG (creation log) if it exists - if [[ -f "${BUILD_LOG}" ]]; then - cp "${BUILD_LOG}" "/tmp/create-lxc-${CTID}-${SESSION_ID}.log" 2>/dev/null && build_log_copied=true - fi - - # Copy INSTALL_LOG from container - if pct pull "$CTID" "/root/.install-${SESSION_ID}.log" "/tmp/install-lxc-${CTID}-${SESSION_ID}.log" 2>/dev/null; then - install_log_copied=true - fi - - # Show available logs - echo "" - [[ $build_log_copied == true ]] && echo -e "${GN}✔${CL} Container creation log: ${BL}/tmp/create-lxc-${CTID}-${SESSION_ID}.log${CL}" - [[ $install_log_copied == true ]] && echo -e "${GN}✔${CL} Installation log: ${BL}/tmp/install-lxc-${CTID}-${SESSION_ID}.log${CL}" + pct pull "$CTID" "/root/.install-${SESSION_ID}.log" "/tmp/install-${SESSION_ID}.log" 2>/dev/null || true fi - - # Dev mode: Keep container or open breakpoint shell - if [[ "${DEV_MODE_KEEP:-false}" == "true" ]]; then - msg_dev "Keep mode active - container ${CTID} preserved" - return 0 - elif [[ "${DEV_MODE_BREAKPOINT:-false}" == "true" ]]; then - msg_dev "Breakpoint mode - opening shell in container ${CTID}" - echo -e "${YW}Type 'exit' to return to host${CL}" - pct enter "$CTID" - echo "" - echo -en "${YW}Container ${CTID} still running. Remove now? (y/N): ${CL}" - if read -r response && [[ "$response" =~ ^[Yy]$ ]]; then - pct stop "$CTID" &>/dev/null || true - pct destroy "$CTID" &>/dev/null || true - msg_ok "Container ${CTID} removed" - else - msg_dev "Container ${CTID} kept for debugging" - fi - exit $install_exit_code - fi - - # Prompt user for cleanup with 60s timeout (plain echo - no msg_info to avoid spinner) - echo "" - echo -en "${YW}Remove broken container ${CTID}? (Y/n) [auto-remove in 60s]: ${CL}" - - if read -t 60 -r response; then - if [[ -z "$response" || "$response" =~ ^[Yy]$ ]]; then - # Remove container - echo -e "\n${TAB}${HOLD}${YW}Removing container ${CTID}${CL}" - pct stop "$CTID" &>/dev/null || true - pct destroy "$CTID" &>/dev/null || true - echo -e "${BFR}${CM}${GN}Container ${CTID} removed${CL}" - elif [[ "$response" =~ ^[Nn]$ ]]; then - echo -e "\n${TAB}${YW}Container ${CTID} kept for debugging${CL}" - fi - else - # Timeout - auto-remove - echo -e "\n${YW}No response - auto-removing container${CL}" - echo -e "${TAB}${HOLD}${YW}Removing container ${CTID}${CL}" - pct stop "$CTID" &>/dev/null || true - pct destroy "$CTID" &>/dev/null || true - echo -e "${BFR}${CM}${GN}Container ${CTID} removed${CL}" - fi - - exit $install_exit_code + exit $exit_code fi } @@ -2937,40 +2665,79 @@ fix_gpu_gids() { return 0 fi + # Silent operation to avoid spinner conflicts msg_custom "🔧" "${BL}" "Detecting and setting correct GPU group IDs" - # Get actual GIDs from container + # Ermittle die tatsächlichen GIDs aus dem Container local video_gid=$(pct exec "$CTID" -- sh -c "getent group video 2>/dev/null | cut -d: -f3") local render_gid=$(pct exec "$CTID" -- sh -c "getent group render 2>/dev/null | cut -d: -f3") - # Create groups if they don't exist + # Fallbacks wenn Gruppen nicht existieren if [[ -z "$video_gid" ]]; then - pct exec "$CTID" -- sh -c "groupadd -r video 2>/dev/null || true" >/dev/null 2>&1 + # Versuche die video Gruppe zu erstellen + pct exec "$CTID" -- sh -c "groupadd -r video 2>/dev/null || true" video_gid=$(pct exec "$CTID" -- sh -c "getent group video 2>/dev/null | cut -d: -f3") - [[ -z "$video_gid" ]] && video_gid="44" + [[ -z "$video_gid" ]] && video_gid="44" # Ultimate fallback fi if [[ -z "$render_gid" ]]; then - pct exec "$CTID" -- sh -c "groupadd -r render 2>/dev/null || true" >/dev/null 2>&1 + # Versuche die render Gruppe zu erstellen + pct exec "$CTID" -- sh -c "groupadd -r render 2>/dev/null || true" render_gid=$(pct exec "$CTID" -- sh -c "getent group render 2>/dev/null | cut -d: -f3") - [[ -z "$render_gid" ]] && render_gid="104" + [[ -z "$render_gid" ]] && render_gid="104" # Ultimate fallback fi - # Stop container to update config - pct stop "$CTID" >/dev/null 2>&1 - sleep 1 + msg_custom "ℹ️" "${DGN}" "Container GIDs detected - video:${video_gid}, render:${render_gid}" - # Update dev entries with correct GIDs - sed -i.bak -E "s|(dev[0-9]+: /dev/dri/renderD[0-9]+),gid=[0-9]+|\1,gid=${render_gid}|g" "$LXC_CONFIG" - sed -i -E "s|(dev[0-9]+: /dev/dri/card[0-9]+),gid=[0-9]+|\1,gid=${video_gid}|g" "$LXC_CONFIG" + # Prüfe ob die GIDs von den Defaults abweichen + local need_update=0 + if [[ "$video_gid" != "44" ]] || [[ "$render_gid" != "104" ]]; then + need_update=1 + fi - # Restart container - pct start "$CTID" >/dev/null 2>&1 - sleep 2 + if [[ $need_update -eq 1 ]]; then + msg_custom "🔄" "${YW}" "Updating device GIDs in container config" - msg_ok "GPU passthrough configured (video:${video_gid}, render:${render_gid})" - - # For privileged containers: also fix permissions inside container + # Stoppe Container für Config-Update + pct stop "$CTID" >/dev/null 2>&1 + + # Update die dev Einträge mit korrekten GIDs + # Backup der Config + cp "$LXC_CONFIG" "${LXC_CONFIG}.bak" + + # Parse und update jeden dev Eintrag + while IFS= read -r line; do + if [[ "$line" =~ ^dev[0-9]+: ]]; then + # Extract device path + local device_path=$(echo "$line" | sed -E 's/^dev[0-9]+: ([^,]+).*/\1/') + local dev_num=$(echo "$line" | sed -E 's/^(dev[0-9]+):.*/\1/') + + if [[ "$device_path" =~ renderD ]]; then + # RenderD device - use render GID + echo "${dev_num}: ${device_path},gid=${render_gid}" + elif [[ "$device_path" =~ card ]]; then + # Card device - use video GID + echo "${dev_num}: ${device_path},gid=${video_gid}" + else + # Keep original line + echo "$line" + fi + else + # Keep non-dev lines + echo "$line" + fi + done <"$LXC_CONFIG" >"${LXC_CONFIG}.new" + + mv "${LXC_CONFIG}.new" "$LXC_CONFIG" + + # Starte Container wieder + pct start "$CTID" >/dev/null 2>&1 + sleep 3 + + msg_ok "Device GIDs updated successfully" + else + msg_ok "Device GIDs are already correct" + fi if [[ "$CT_TYPE" == "0" ]]; then pct exec "$CTID" -- bash -c " if [ -d /dev/dri ]; then @@ -3136,7 +2903,7 @@ create_lxc_container() { case "${_ans,,}" in y | yes) msg_info "Upgrading Proxmox LXC stack (pve-container, lxc-pve)" - if $STD apt-get update && $STD apt-get install -y --only-upgrade pve-container lxc-pve; then + if apt-get update -qq >/dev/null && apt-get install -y --only-upgrade pve-container lxc-pve >/dev/null; then msg_ok "LXC stack upgraded." if [[ "$do_retry" == "yes" ]]; then msg_info "Retrying container creation after upgrade" @@ -3581,13 +3348,13 @@ create_lxc_container() { exit 211 } - LOGFILE="/tmp/pct_create_${CTID}_$(date +%Y%m%d_%H%M%S)_${SESSION_ID}.log" + LOGFILE="/tmp/pct_create_${CTID}.log" msg_debug "pct create command: pct create $CTID ${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE} ${PCT_OPTIONS[*]}" msg_debug "Logfile: $LOGFILE" # First attempt if ! pct create "$CTID" "${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE}" "${PCT_OPTIONS[@]}" >"$LOGFILE" 2>&1; then - msg_debug "Container creation failed on ${TEMPLATE_STORAGE}. Validating template..." + msg_error "Container creation failed on ${TEMPLATE_STORAGE}. Checking template..." # Validate template file if [[ ! -s "$TEMPLATE_PATH" || "$(stat -c%s "$TEMPLATE_PATH")" -lt 1000000 ]]; then @@ -3606,16 +3373,18 @@ create_lxc_container() { # Retry after repair if ! pct create "$CTID" "${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE}" "${PCT_OPTIONS[@]}" >>"$LOGFILE" 2>&1; then - # Fallback to local storage if not already on local + # Fallback to local storage if [[ "$TEMPLATE_STORAGE" != "local" ]]; then - msg_info "Retrying container creation with fallback to local storage..." + msg_warn "Retrying container creation with fallback to local storage..." LOCAL_TEMPLATE_PATH="/var/lib/vz/template/cache/$TEMPLATE" if [[ ! -f "$LOCAL_TEMPLATE_PATH" ]]; then msg_info "Downloading template to local..." pveam download local "$TEMPLATE" >/dev/null 2>&1 fi - if ! pct create "$CTID" "local:vztmpl/${TEMPLATE}" "${PCT_OPTIONS[@]}" >>"$LOGFILE" 2>&1; then - # Local fallback also failed - check for LXC stack version issue + if pct create "$CTID" "local:vztmpl/${TEMPLATE}" "${PCT_OPTIONS[@]}" >>"$LOGFILE" 2>&1; then + msg_ok "Container successfully created using local fallback." + else + # --- Dynamic stack upgrade + auto-retry on the well-known error pattern --- if grep -qiE 'unsupported .* version' "$LOGFILE"; then echo echo "pct reported 'unsupported ... version' – your LXC stack might be too old for this template." @@ -3635,19 +3404,18 @@ create_lxc_container() { ;; esac else - msg_error "Container creation failed. See $LOGFILE" + msg_error "Container creation failed even with local fallback. See $LOGFILE" if whiptail --yesno "pct create failed.\nDo you want to enable verbose debug mode and view detailed logs?" 12 70; then set -x - pct create "$CTID" "local:vztmpl/${TEMPLATE}" "${PCT_OPTIONS[@]}" 2>&1 | tee -a "$LOGFILE" + bash -x -c "pct create $CTID local:vztmpl/${TEMPLATE} ${PCT_OPTIONS[*]}" 2>&1 | tee -a "$LOGFILE" set +x fi exit 209 fi - else - msg_ok "Container successfully created using local fallback." fi else - # Already on local storage and still failed - check LXC stack version + msg_error "Container creation failed on local storage. See $LOGFILE" + # --- Dynamic stack upgrade + auto-retry on the well-known error pattern --- if grep -qiE 'unsupported .* version' "$LOGFILE"; then echo echo "pct reported 'unsupported ... version' – your LXC stack might be too old for this template." @@ -3670,14 +3438,12 @@ create_lxc_container() { msg_error "Container creation failed. See $LOGFILE" if whiptail --yesno "pct create failed.\nDo you want to enable verbose debug mode and view detailed logs?" 12 70; then set -x - pct create "$CTID" "local:vztmpl/${TEMPLATE}" "${PCT_OPTIONS[@]}" 2>&1 | tee -a "$LOGFILE" + bash -x -c "pct create $CTID local:vztmpl/${TEMPLATE} ${PCT_OPTIONS[*]}" 2>&1 | tee -a "$LOGFILE" set +x fi exit 209 fi fi - else - msg_ok "Container successfully created after template repair." fi fi @@ -3694,9 +3460,6 @@ create_lxc_container() { } msg_ok "LXC Container ${BL}$CTID${CL} ${GN}was successfully created." - - # Report container creation to API - post_to_api } # ==============================================================================