Update build.func

This commit is contained in:
CanbiZ 2025-11-24 11:35:10 +01:00
parent cb2c3fab96
commit 7455f8195c

View File

@ -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
}
# ==============================================================================