reverted
This commit is contained in:
parent
e147c848bb
commit
bea8814994
@ -47,17 +47,7 @@ variables() {
|
|||||||
METHOD="default" # sets the METHOD variable to "default", used for the API call.
|
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.
|
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
|
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}}"}
|
||||||
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
|
|
||||||
|
|
||||||
# Get Proxmox VE version and kernel version
|
# Get Proxmox VE version and kernel version
|
||||||
if command -v pveversion >/dev/null 2>&1; then
|
if command -v pveversion >/dev/null 2>&1; then
|
||||||
@ -535,35 +525,6 @@ base_settings() {
|
|||||||
TAGS="community-script,${var_tags:-}"
|
TAGS="community-script,${var_tags:-}"
|
||||||
ENABLE_FUSE=${var_fuse:-"${1:-no}"}
|
ENABLE_FUSE=${var_fuse:-"${1:-no}"}
|
||||||
ENABLE_TUN=${var_tun:-"${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
|
# 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
|
if [ -z "$var_os" ]; then
|
||||||
@ -587,9 +548,9 @@ default_var_settings() {
|
|||||||
# Allowed var_* keys (alphabetically sorted)
|
# Allowed var_* keys (alphabetically sorted)
|
||||||
# Note: Removed var_ctid (can only exist once), var_ipv6_static (static IPs are unique)
|
# Note: Removed var_ctid (can only exist once), var_ipv6_static (static IPs are unique)
|
||||||
local VAR_WHITELIST=(
|
local VAR_WHITELIST=(
|
||||||
var_apt_cacher var_apt_cacher_ip var_brg var_cpu var_disk var_fuse var_keyctl
|
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_mknod var_mount_fs var_mtu
|
var_gateway var_hostname var_ipv6_method var_mac var_mtu
|
||||||
var_net var_nesting var_ns var_protection var_pw var_ram var_tags var_timezone var_tun var_unprivileged
|
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
|
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
|
# Features/Tags/verbosity
|
||||||
var_fuse=no
|
var_fuse=no
|
||||||
var_tun=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_tags=community-script
|
||||||
var_verbose=no
|
var_verbose=no
|
||||||
|
|
||||||
@ -941,12 +894,6 @@ _build_current_app_vars_tmp() {
|
|||||||
_apt_cacher_ip="${APT_CACHER_IP:-}"
|
_apt_cacher_ip="${APT_CACHER_IP:-}"
|
||||||
_fuse="${ENABLE_FUSE:-no}"
|
_fuse="${ENABLE_FUSE:-no}"
|
||||||
_tun="${ENABLE_TUN:-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:-}"
|
_tags="${TAGS:-}"
|
||||||
_verbose="${VERBOSE:-no}"
|
_verbose="${VERBOSE:-no}"
|
||||||
|
|
||||||
@ -990,12 +937,6 @@ _build_current_app_vars_tmp() {
|
|||||||
|
|
||||||
[ -n "$_fuse" ] && echo "var_fuse=$(_sanitize_value "$_fuse")"
|
[ -n "$_fuse" ] && echo "var_fuse=$(_sanitize_value "$_fuse")"
|
||||||
[ -n "$_tun" ] && echo "var_tun=$(_sanitize_value "$_tun")"
|
[ -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 "$_tags" ] && echo "var_tags=$(_sanitize_value "$_tags")"
|
||||||
[ -n "$_verbose" ] && echo "var_verbose=$(_sanitize_value "$_verbose")"
|
[ -n "$_verbose" ] && echo "var_verbose=$(_sanitize_value "$_verbose")"
|
||||||
|
|
||||||
@ -1578,51 +1519,6 @@ advanced_settings() {
|
|||||||
configure_ssh_settings
|
configure_ssh_settings
|
||||||
export SSH_KEYS_FILE
|
export SSH_KEYS_FILE
|
||||||
echo -e "${ROOTSSH}${BOLD}${DGN}Root SSH Access: ${BGN}$SSH${CL}"
|
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
|
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"
|
ENABLE_FUSE="yes"
|
||||||
else
|
else
|
||||||
@ -1795,16 +1691,7 @@ install_script() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
NEXTID=$(pvesh get /cluster/nextid)
|
NEXTID=$(pvesh get /cluster/nextid)
|
||||||
|
timezone=$(cat /etc/timezone)
|
||||||
# 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
|
|
||||||
|
|
||||||
# Show APP Header
|
# Show APP Header
|
||||||
header_info
|
header_info
|
||||||
@ -1932,12 +1819,13 @@ settings_menu() {
|
|||||||
local settings_items=(
|
local settings_items=(
|
||||||
"1" "Manage API-Diagnostic Setting"
|
"1" "Manage API-Diagnostic Setting"
|
||||||
"2" "Edit Default.vars"
|
"2" "Edit Default.vars"
|
||||||
|
"3" "Edit Default Storage"
|
||||||
)
|
)
|
||||||
if [ -f "$(get_app_defaults_path)" ]; then
|
if [ -f "$(get_app_defaults_path)" ]; then
|
||||||
settings_items+=("3" "Edit App.vars for ${APP}")
|
settings_items+=("4" "Edit App.vars for ${APP}")
|
||||||
settings_items+=("4" "Exit")
|
settings_items+=("5" "Exit")
|
||||||
else
|
else
|
||||||
settings_items+=("3" "Exit")
|
settings_items+=("4" "Exit")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local choice
|
local choice
|
||||||
@ -2298,34 +2186,14 @@ build_container() {
|
|||||||
none) ;;
|
none) ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
# Build FEATURES array with advanced settings
|
if [ "$CT_TYPE" == "1" ]; then
|
||||||
# Note: All feature flags are already normalized to 0/1 in default_settings()
|
FEATURES="keyctl=1,nesting=1"
|
||||||
# Proxmox requires each feature as a separate parameter, not comma-separated string
|
else
|
||||||
FEATURES_ARRAY=()
|
FEATURES="nesting=1"
|
||||||
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")
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# mknod: allow device node creation (requires kernel 5.3+, experimental)
|
if [ "$ENABLE_FUSE" == "yes" ]; then
|
||||||
if [ "$ENABLE_MKNOD" == "1" ]; then
|
FEATURES="$FEATURES,fuse=1"
|
||||||
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")
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
TEMP_DIR=$(mktemp -d)
|
TEMP_DIR=$(mktemp -d)
|
||||||
@ -2338,16 +2206,6 @@ build_container() {
|
|||||||
export DIAGNOSTICS="$DIAGNOSTICS"
|
export DIAGNOSTICS="$DIAGNOSTICS"
|
||||||
export RANDOM_UUID="$RANDOM_UUID"
|
export RANDOM_UUID="$RANDOM_UUID"
|
||||||
export SESSION_ID="$SESSION_ID"
|
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="$APT_CACHER"
|
||||||
export CACHER_IP="$APT_CACHER_IP"
|
export CACHER_IP="$APT_CACHER_IP"
|
||||||
export tz="$timezone"
|
export tz="$timezone"
|
||||||
@ -2361,59 +2219,22 @@ build_container() {
|
|||||||
export CTTYPE="$CT_TYPE"
|
export CTTYPE="$CT_TYPE"
|
||||||
export ENABLE_FUSE="$ENABLE_FUSE"
|
export ENABLE_FUSE="$ENABLE_FUSE"
|
||||||
export ENABLE_TUN="$ENABLE_TUN"
|
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_OSTYPE="$var_os"
|
||||||
export PCT_OSVERSION="$var_version"
|
export PCT_OSVERSION="$var_version"
|
||||||
export PCT_DISK_SIZE="$DISK_SIZE"
|
export PCT_DISK_SIZE="$DISK_SIZE"
|
||||||
|
export PCT_OPTIONS="
|
||||||
# Build PCT_OPTIONS array (not string) for proper parameter handling
|
-features $FEATURES
|
||||||
PCT_OPTIONS=()
|
-hostname $HN
|
||||||
|
-tags $TAGS
|
||||||
# Add features - each as separate -features parameter
|
$SD
|
||||||
for feature in "${FEATURES_ARRAY[@]}"; do
|
$NS
|
||||||
PCT_OPTIONS+=("-features" "$feature")
|
$NET_STRING
|
||||||
done
|
-onboot 1
|
||||||
|
-cores $CORE_COUNT
|
||||||
PCT_OPTIONS+=("-hostname" "$HN")
|
-memory $RAM_SIZE
|
||||||
PCT_OPTIONS+=("-tags" "$TAGS")
|
-unprivileged $CT_TYPE
|
||||||
|
$PW
|
||||||
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 TEMPLATE_STORAGE="${var_template_storage:-}"
|
export TEMPLATE_STORAGE="${var_template_storage:-}"
|
||||||
export CONTAINER_STORAGE="${var_container_storage:-}"
|
export CONTAINER_STORAGE="${var_container_storage:-}"
|
||||||
create_lxc_container || exit $?
|
create_lxc_container || exit $?
|
||||||
@ -2588,13 +2409,20 @@ EOF
|
|||||||
[[ "$selected_gpu" == "INTEL" ]] && devices=("${INTEL_DEVICES[@]}")
|
[[ "$selected_gpu" == "INTEL" ]] && devices=("${INTEL_DEVICES[@]}")
|
||||||
[[ "$selected_gpu" == "AMD" ]] && devices=("${AMD_DEVICES[@]}")
|
[[ "$selected_gpu" == "AMD" ]] && devices=("${AMD_DEVICES[@]}")
|
||||||
|
|
||||||
# Use pct set to add devices with proper dev0/dev1 format
|
# Add lxc.mount.entry for each device
|
||||||
# GIDs will be detected and set after container starts
|
|
||||||
local dev_index=0
|
|
||||||
for dev in "${devices[@]}"; do
|
for dev in "${devices[@]}"; do
|
||||||
# Add to config using pct set (will be visible in GUI)
|
echo "lxc.mount.entry: $dev $dev none bind,optional,create=file" >>"$LXC_CONFIG"
|
||||||
echo "dev${dev_index}: ${dev},gid=44" >>"$LXC_CONFIG"
|
|
||||||
dev_index=$((dev_index + 1))
|
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
|
done
|
||||||
|
|
||||||
export GPU_TYPE="$selected_gpu"
|
export GPU_TYPE="$selected_gpu"
|
||||||
@ -2607,11 +2435,20 @@ EOF
|
|||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Use pct set for NVIDIA devices
|
# Add lxc.mount.entry for each NVIDIA device
|
||||||
local dev_index=0
|
|
||||||
for dev in "${NVIDIA_DEVICES[@]}"; do
|
for dev in "${NVIDIA_DEVICES[@]}"; do
|
||||||
echo "dev${dev_index}: ${dev},gid=44" >>"$LXC_CONFIG"
|
echo "lxc.mount.entry: $dev $dev none bind,optional,create=file" >>"$LXC_CONFIG"
|
||||||
dev_index=$((dev_index + 1))
|
|
||||||
|
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
|
done
|
||||||
|
|
||||||
export GPU_TYPE="NVIDIA"
|
export GPU_TYPE="NVIDIA"
|
||||||
@ -2723,9 +2560,7 @@ EOF'
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if pct exec "$CTID" -- test -e "/usr/share/zoneinfo/$tz"; then
|
if pct exec "$CTID" -- test -e "/usr/share/zoneinfo/$tz"; then
|
||||||
# Set timezone using symlink (Debian 13+ compatible)
|
pct exec "$CTID" -- bash -c "tz='$tz'; echo \"\$tz\" >/etc/timezone && ln -sf \"/usr/share/zoneinfo/\$tz\" /etc/localtime"
|
||||||
# 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"
|
|
||||||
else
|
else
|
||||||
msg_warn "Skipping timezone setup – zone '$tz' not found in container"
|
msg_warn "Skipping timezone setup – zone '$tz' not found in container"
|
||||||
fi
|
fi
|
||||||
@ -2742,105 +2577,13 @@ EOF'
|
|||||||
install_ssh_keys_into_ct
|
install_ssh_keys_into_ct
|
||||||
|
|
||||||
# Run application installer
|
# Run application installer
|
||||||
# NOTE: We disable error handling here because:
|
if ! lxc-attach -n "$CTID" -- bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/install/${var_install}.sh)"; then
|
||||||
# 1. Container errors are caught by error_handler INSIDE container
|
local exit_code=$?
|
||||||
# 2. Container creates flag file with exit code
|
# Try to copy installation log from container before exiting
|
||||||
# 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 [[ -n "$CTID" && -n "${SESSION_ID:-}" ]]; then
|
if [[ -n "$CTID" && -n "${SESSION_ID:-}" ]]; then
|
||||||
# Copy BUILD_LOG (creation log) if it exists
|
pct pull "$CTID" "/root/.install-${SESSION_ID}.log" "/tmp/install-${SESSION_ID}.log" 2>/dev/null || true
|
||||||
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}"
|
|
||||||
fi
|
fi
|
||||||
|
exit $exit_code
|
||||||
# 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
|
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2922,40 +2665,79 @@ fix_gpu_gids() {
|
|||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Silent operation to avoid spinner conflicts
|
||||||
msg_custom "🔧" "${BL}" "Detecting and setting correct GPU group IDs"
|
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 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")
|
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
|
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")
|
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
|
fi
|
||||||
|
|
||||||
if [[ -z "$render_gid" ]]; then
|
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")
|
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
|
fi
|
||||||
|
|
||||||
# Stop container to update config
|
msg_custom "ℹ️" "${DGN}" "Container GIDs detected - video:${video_gid}, render:${render_gid}"
|
||||||
pct stop "$CTID" >/dev/null 2>&1
|
|
||||||
sleep 1
|
|
||||||
|
|
||||||
# Update dev entries with correct GIDs
|
# Prüfe ob die GIDs von den Defaults abweichen
|
||||||
sed -i.bak -E "s|(dev[0-9]+: /dev/dri/renderD[0-9]+),gid=[0-9]+|\1,gid=${render_gid}|g" "$LXC_CONFIG"
|
local need_update=0
|
||||||
sed -i -E "s|(dev[0-9]+: /dev/dri/card[0-9]+),gid=[0-9]+|\1,gid=${video_gid}|g" "$LXC_CONFIG"
|
if [[ "$video_gid" != "44" ]] || [[ "$render_gid" != "104" ]]; then
|
||||||
|
need_update=1
|
||||||
|
fi
|
||||||
|
|
||||||
# Restart container
|
if [[ $need_update -eq 1 ]]; then
|
||||||
pct start "$CTID" >/dev/null 2>&1
|
msg_custom "🔄" "${YW}" "Updating device GIDs in container config"
|
||||||
sleep 2
|
|
||||||
|
|
||||||
msg_ok "GPU passthrough configured (video:${video_gid}, render:${render_gid})"
|
# Stoppe Container für Config-Update
|
||||||
|
pct stop "$CTID" >/dev/null 2>&1
|
||||||
|
|
||||||
# For privileged containers: also fix permissions inside container
|
# 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
|
if [[ "$CT_TYPE" == "0" ]]; then
|
||||||
pct exec "$CTID" -- bash -c "
|
pct exec "$CTID" -- bash -c "
|
||||||
if [ -d /dev/dri ]; then
|
if [ -d /dev/dri ]; then
|
||||||
@ -3121,7 +2903,7 @@ create_lxc_container() {
|
|||||||
case "${_ans,,}" in
|
case "${_ans,,}" in
|
||||||
y | yes)
|
y | yes)
|
||||||
msg_info "Upgrading Proxmox LXC stack (pve-container, lxc-pve)"
|
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."
|
msg_ok "LXC stack upgraded."
|
||||||
if [[ "$do_retry" == "yes" ]]; then
|
if [[ "$do_retry" == "yes" ]]; then
|
||||||
msg_info "Retrying container creation after upgrade"
|
msg_info "Retrying container creation after upgrade"
|
||||||
@ -3566,13 +3348,13 @@ create_lxc_container() {
|
|||||||
exit 211
|
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 "pct create command: pct create $CTID ${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE} ${PCT_OPTIONS[*]}"
|
||||||
msg_debug "Logfile: $LOGFILE"
|
msg_debug "Logfile: $LOGFILE"
|
||||||
|
|
||||||
# First attempt
|
# First attempt
|
||||||
if ! pct create "$CTID" "${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE}" "${PCT_OPTIONS[@]}" >"$LOGFILE" 2>&1; then
|
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
|
# Validate template file
|
||||||
if [[ ! -s "$TEMPLATE_PATH" || "$(stat -c%s "$TEMPLATE_PATH")" -lt 1000000 ]]; then
|
if [[ ! -s "$TEMPLATE_PATH" || "$(stat -c%s "$TEMPLATE_PATH")" -lt 1000000 ]]; then
|
||||||
@ -3591,16 +3373,18 @@ create_lxc_container() {
|
|||||||
|
|
||||||
# Retry after repair
|
# Retry after repair
|
||||||
if ! pct create "$CTID" "${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE}" "${PCT_OPTIONS[@]}" >>"$LOGFILE" 2>&1; then
|
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
|
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"
|
LOCAL_TEMPLATE_PATH="/var/lib/vz/template/cache/$TEMPLATE"
|
||||||
if [[ ! -f "$LOCAL_TEMPLATE_PATH" ]]; then
|
if [[ ! -f "$LOCAL_TEMPLATE_PATH" ]]; then
|
||||||
msg_info "Downloading template to local..."
|
msg_info "Downloading template to local..."
|
||||||
pveam download local "$TEMPLATE" >/dev/null 2>&1
|
pveam download local "$TEMPLATE" >/dev/null 2>&1
|
||||||
fi
|
fi
|
||||||
if ! pct create "$CTID" "local:vztmpl/${TEMPLATE}" "${PCT_OPTIONS[@]}" >>"$LOGFILE" 2>&1; then
|
if pct create "$CTID" "local:vztmpl/${TEMPLATE}" "${PCT_OPTIONS[@]}" >>"$LOGFILE" 2>&1; then
|
||||||
# Local fallback also failed - check for LXC stack version issue
|
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
|
if grep -qiE 'unsupported .* version' "$LOGFILE"; then
|
||||||
echo
|
echo
|
||||||
echo "pct reported 'unsupported ... version' – your LXC stack might be too old for this template."
|
echo "pct reported 'unsupported ... version' – your LXC stack might be too old for this template."
|
||||||
@ -3620,19 +3404,18 @@ create_lxc_container() {
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
else
|
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
|
if whiptail --yesno "pct create failed.\nDo you want to enable verbose debug mode and view detailed logs?" 12 70; then
|
||||||
set -x
|
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
|
set +x
|
||||||
fi
|
fi
|
||||||
exit 209
|
exit 209
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
msg_ok "Container successfully created using local fallback."
|
|
||||||
fi
|
fi
|
||||||
else
|
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
|
if grep -qiE 'unsupported .* version' "$LOGFILE"; then
|
||||||
echo
|
echo
|
||||||
echo "pct reported 'unsupported ... version' – your LXC stack might be too old for this template."
|
echo "pct reported 'unsupported ... version' – your LXC stack might be too old for this template."
|
||||||
@ -3655,14 +3438,12 @@ create_lxc_container() {
|
|||||||
msg_error "Container creation failed. See $LOGFILE"
|
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
|
if whiptail --yesno "pct create failed.\nDo you want to enable verbose debug mode and view detailed logs?" 12 70; then
|
||||||
set -x
|
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
|
set +x
|
||||||
fi
|
fi
|
||||||
exit 209
|
exit 209
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
msg_ok "Container successfully created after template repair."
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -3679,9 +3460,6 @@ create_lxc_container() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
msg_ok "LXC Container ${BL}$CTID${CL} ${GN}was successfully created."
|
msg_ok "LXC Container ${BL}$CTID${CL} ${GN}was successfully created."
|
||||||
|
|
||||||
# Report container creation to API
|
|
||||||
post_to_api
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
499
misc/build.func
499
misc/build.func
@ -47,7 +47,17 @@ variables() {
|
|||||||
METHOD="default" # sets the METHOD variable to "default", used for the API call.
|
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.
|
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
|
SESSION_ID="${RANDOM_UUID:0:8}" # Short session ID (first 8 chars of UUID) for log files
|
||||||
CTTYPE="${CTTYPE:-${CT_TYPE:-1}}"}
|
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
|
||||||
|
|
||||||
# Get Proxmox VE version and kernel version
|
# Get Proxmox VE version and kernel version
|
||||||
if command -v pveversion >/dev/null 2>&1; then
|
if command -v pveversion >/dev/null 2>&1; then
|
||||||
@ -525,6 +535,35 @@ base_settings() {
|
|||||||
TAGS="community-script,${var_tags:-}"
|
TAGS="community-script,${var_tags:-}"
|
||||||
ENABLE_FUSE=${var_fuse:-"${1:-no}"}
|
ENABLE_FUSE=${var_fuse:-"${1:-no}"}
|
||||||
ENABLE_TUN=${var_tun:-"${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
|
# 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
|
if [ -z "$var_os" ]; then
|
||||||
@ -548,9 +587,9 @@ default_var_settings() {
|
|||||||
# Allowed var_* keys (alphabetically sorted)
|
# Allowed var_* keys (alphabetically sorted)
|
||||||
# Note: Removed var_ctid (can only exist once), var_ipv6_static (static IPs are unique)
|
# Note: Removed var_ctid (can only exist once), var_ipv6_static (static IPs are unique)
|
||||||
local VAR_WHITELIST=(
|
local VAR_WHITELIST=(
|
||||||
var_apt_cacher var_apt_cacher_ip var_brg var_cpu var_disk var_fuse
|
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_mtu
|
var_gateway var_hostname var_ipv6_method var_mac var_mknod var_mount_fs var_mtu
|
||||||
var_net var_ns var_pw var_ram var_tags var_tun var_unprivileged
|
var_net var_nesting var_ns var_protection var_pw var_ram var_tags var_timezone var_tun var_unprivileged
|
||||||
var_verbose var_vlan var_ssh var_ssh_authorized_key var_container_storage var_template_storage
|
var_verbose var_vlan var_ssh var_ssh_authorized_key var_container_storage var_template_storage
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -628,6 +667,14 @@ var_ssh=no
|
|||||||
# Features/Tags/verbosity
|
# Features/Tags/verbosity
|
||||||
var_fuse=no
|
var_fuse=no
|
||||||
var_tun=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_tags=community-script
|
||||||
var_verbose=no
|
var_verbose=no
|
||||||
|
|
||||||
@ -894,6 +941,12 @@ _build_current_app_vars_tmp() {
|
|||||||
_apt_cacher_ip="${APT_CACHER_IP:-}"
|
_apt_cacher_ip="${APT_CACHER_IP:-}"
|
||||||
_fuse="${ENABLE_FUSE:-no}"
|
_fuse="${ENABLE_FUSE:-no}"
|
||||||
_tun="${ENABLE_TUN:-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:-}"
|
_tags="${TAGS:-}"
|
||||||
_verbose="${VERBOSE:-no}"
|
_verbose="${VERBOSE:-no}"
|
||||||
|
|
||||||
@ -937,6 +990,12 @@ _build_current_app_vars_tmp() {
|
|||||||
|
|
||||||
[ -n "$_fuse" ] && echo "var_fuse=$(_sanitize_value "$_fuse")"
|
[ -n "$_fuse" ] && echo "var_fuse=$(_sanitize_value "$_fuse")"
|
||||||
[ -n "$_tun" ] && echo "var_tun=$(_sanitize_value "$_tun")"
|
[ -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 "$_tags" ] && echo "var_tags=$(_sanitize_value "$_tags")"
|
||||||
[ -n "$_verbose" ] && echo "var_verbose=$(_sanitize_value "$_verbose")"
|
[ -n "$_verbose" ] && echo "var_verbose=$(_sanitize_value "$_verbose")"
|
||||||
|
|
||||||
@ -1519,6 +1578,51 @@ advanced_settings() {
|
|||||||
configure_ssh_settings
|
configure_ssh_settings
|
||||||
export SSH_KEYS_FILE
|
export SSH_KEYS_FILE
|
||||||
echo -e "${ROOTSSH}${BOLD}${DGN}Root SSH Access: ${BGN}$SSH${CL}"
|
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
|
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"
|
ENABLE_FUSE="yes"
|
||||||
else
|
else
|
||||||
@ -1691,7 +1795,16 @@ install_script() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
NEXTID=$(pvesh get /cluster/nextid)
|
NEXTID=$(pvesh get /cluster/nextid)
|
||||||
timezone=$(cat /etc/timezone)
|
|
||||||
|
# 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
|
||||||
|
|
||||||
# Show APP Header
|
# Show APP Header
|
||||||
header_info
|
header_info
|
||||||
@ -1819,13 +1932,12 @@ settings_menu() {
|
|||||||
local settings_items=(
|
local settings_items=(
|
||||||
"1" "Manage API-Diagnostic Setting"
|
"1" "Manage API-Diagnostic Setting"
|
||||||
"2" "Edit Default.vars"
|
"2" "Edit Default.vars"
|
||||||
"3" "Edit Default Storage"
|
|
||||||
)
|
)
|
||||||
if [ -f "$(get_app_defaults_path)" ]; then
|
if [ -f "$(get_app_defaults_path)" ]; then
|
||||||
settings_items+=("4" "Edit App.vars for ${APP}")
|
settings_items+=("3" "Edit App.vars for ${APP}")
|
||||||
settings_items+=("5" "Exit")
|
|
||||||
else
|
|
||||||
settings_items+=("4" "Exit")
|
settings_items+=("4" "Exit")
|
||||||
|
else
|
||||||
|
settings_items+=("3" "Exit")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local choice
|
local choice
|
||||||
@ -2186,14 +2298,34 @@ build_container() {
|
|||||||
none) ;;
|
none) ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
if [ "$CT_TYPE" == "1" ]; then
|
# Build FEATURES array with advanced settings
|
||||||
FEATURES="keyctl=1,nesting=1"
|
# Note: All feature flags are already normalized to 0/1 in default_settings()
|
||||||
else
|
# Proxmox requires each feature as a separate parameter, not comma-separated string
|
||||||
FEATURES="nesting=1"
|
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")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$ENABLE_FUSE" == "yes" ]; then
|
# mknod: allow device node creation (requires kernel 5.3+, experimental)
|
||||||
FEATURES="$FEATURES,fuse=1"
|
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")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
TEMP_DIR=$(mktemp -d)
|
TEMP_DIR=$(mktemp -d)
|
||||||
@ -2206,6 +2338,16 @@ build_container() {
|
|||||||
export DIAGNOSTICS="$DIAGNOSTICS"
|
export DIAGNOSTICS="$DIAGNOSTICS"
|
||||||
export RANDOM_UUID="$RANDOM_UUID"
|
export RANDOM_UUID="$RANDOM_UUID"
|
||||||
export SESSION_ID="$SESSION_ID"
|
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="$APT_CACHER"
|
||||||
export CACHER_IP="$APT_CACHER_IP"
|
export CACHER_IP="$APT_CACHER_IP"
|
||||||
export tz="$timezone"
|
export tz="$timezone"
|
||||||
@ -2219,22 +2361,59 @@ build_container() {
|
|||||||
export CTTYPE="$CT_TYPE"
|
export CTTYPE="$CT_TYPE"
|
||||||
export ENABLE_FUSE="$ENABLE_FUSE"
|
export ENABLE_FUSE="$ENABLE_FUSE"
|
||||||
export ENABLE_TUN="$ENABLE_TUN"
|
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_OSTYPE="$var_os"
|
||||||
export PCT_OSVERSION="$var_version"
|
export PCT_OSVERSION="$var_version"
|
||||||
export PCT_DISK_SIZE="$DISK_SIZE"
|
export PCT_DISK_SIZE="$DISK_SIZE"
|
||||||
export PCT_OPTIONS="
|
|
||||||
-features $FEATURES
|
# Build PCT_OPTIONS array (not string) for proper parameter handling
|
||||||
-hostname $HN
|
PCT_OPTIONS=()
|
||||||
-tags $TAGS
|
|
||||||
$SD
|
# Add features - each as separate -features parameter
|
||||||
$NS
|
for feature in "${FEATURES_ARRAY[@]}"; do
|
||||||
$NET_STRING
|
PCT_OPTIONS+=("-features" "$feature")
|
||||||
-onboot 1
|
done
|
||||||
-cores $CORE_COUNT
|
|
||||||
-memory $RAM_SIZE
|
PCT_OPTIONS+=("-hostname" "$HN")
|
||||||
-unprivileged $CT_TYPE
|
PCT_OPTIONS+=("-tags" "$TAGS")
|
||||||
$PW
|
|
||||||
"
|
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 TEMPLATE_STORAGE="${var_template_storage:-}"
|
export TEMPLATE_STORAGE="${var_template_storage:-}"
|
||||||
export CONTAINER_STORAGE="${var_container_storage:-}"
|
export CONTAINER_STORAGE="${var_container_storage:-}"
|
||||||
create_lxc_container || exit $?
|
create_lxc_container || exit $?
|
||||||
@ -2409,20 +2588,13 @@ EOF
|
|||||||
[[ "$selected_gpu" == "INTEL" ]] && devices=("${INTEL_DEVICES[@]}")
|
[[ "$selected_gpu" == "INTEL" ]] && devices=("${INTEL_DEVICES[@]}")
|
||||||
[[ "$selected_gpu" == "AMD" ]] && devices=("${AMD_DEVICES[@]}")
|
[[ "$selected_gpu" == "AMD" ]] && devices=("${AMD_DEVICES[@]}")
|
||||||
|
|
||||||
# Add lxc.mount.entry for each device
|
# Use pct set to add devices with proper dev0/dev1 format
|
||||||
|
# GIDs will be detected and set after container starts
|
||||||
|
local dev_index=0
|
||||||
for dev in "${devices[@]}"; do
|
for dev in "${devices[@]}"; do
|
||||||
echo "lxc.mount.entry: $dev $dev none bind,optional,create=file" >>"$LXC_CONFIG"
|
# Add to config using pct set (will be visible in GUI)
|
||||||
|
echo "dev${dev_index}: ${dev},gid=44" >>"$LXC_CONFIG"
|
||||||
if [[ "$CT_TYPE" == "0" ]]; then
|
dev_index=$((dev_index + 1))
|
||||||
# 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
|
done
|
||||||
|
|
||||||
export GPU_TYPE="$selected_gpu"
|
export GPU_TYPE="$selected_gpu"
|
||||||
@ -2435,20 +2607,11 @@ EOF
|
|||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Add lxc.mount.entry for each NVIDIA device
|
# Use pct set for NVIDIA devices
|
||||||
|
local dev_index=0
|
||||||
for dev in "${NVIDIA_DEVICES[@]}"; do
|
for dev in "${NVIDIA_DEVICES[@]}"; do
|
||||||
echo "lxc.mount.entry: $dev $dev none bind,optional,create=file" >>"$LXC_CONFIG"
|
echo "dev${dev_index}: ${dev},gid=44" >>"$LXC_CONFIG"
|
||||||
|
dev_index=$((dev_index + 1))
|
||||||
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
|
done
|
||||||
|
|
||||||
export GPU_TYPE="NVIDIA"
|
export GPU_TYPE="NVIDIA"
|
||||||
@ -2560,7 +2723,9 @@ EOF'
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if pct exec "$CTID" -- test -e "/usr/share/zoneinfo/$tz"; then
|
if pct exec "$CTID" -- test -e "/usr/share/zoneinfo/$tz"; then
|
||||||
pct exec "$CTID" -- bash -c "tz='$tz'; echo \"\$tz\" >/etc/timezone && ln -sf \"/usr/share/zoneinfo/\$tz\" /etc/localtime"
|
# 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"
|
||||||
else
|
else
|
||||||
msg_warn "Skipping timezone setup – zone '$tz' not found in container"
|
msg_warn "Skipping timezone setup – zone '$tz' not found in container"
|
||||||
fi
|
fi
|
||||||
@ -2576,14 +2741,121 @@ EOF'
|
|||||||
# Install SSH keys
|
# Install SSH keys
|
||||||
install_ssh_keys_into_ct
|
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
|
# Run application installer
|
||||||
if ! lxc-attach -n "$CTID" -- bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/install/${var_install}.sh)"; then
|
# NOTE: We disable error handling here because:
|
||||||
local exit_code=$?
|
# 1. Container errors are caught by error_handler INSIDE container
|
||||||
# Try to copy installation log from container before exiting
|
# 2. Container creates flag file with exit code
|
||||||
if [[ -n "$CTID" && -n "${SESSION_ID:-}" ]]; then
|
# 3. We read flag file and handle cleanup manually below
|
||||||
pct pull "$CTID" "/root/.install-${SESSION_ID}.log" "/tmp/install-${SESSION_ID}.log" 2>/dev/null || true
|
# 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
|
||||||
exit $exit_code
|
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 [[ -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}"
|
||||||
|
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
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2665,79 +2937,40 @@ fix_gpu_gids() {
|
|||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Silent operation to avoid spinner conflicts
|
|
||||||
msg_custom "🔧" "${BL}" "Detecting and setting correct GPU group IDs"
|
msg_custom "🔧" "${BL}" "Detecting and setting correct GPU group IDs"
|
||||||
|
|
||||||
# Ermittle die tatsächlichen GIDs aus dem Container
|
# Get actual GIDs from container
|
||||||
local video_gid=$(pct exec "$CTID" -- sh -c "getent group video 2>/dev/null | cut -d: -f3")
|
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")
|
local render_gid=$(pct exec "$CTID" -- sh -c "getent group render 2>/dev/null | cut -d: -f3")
|
||||||
|
|
||||||
# Fallbacks wenn Gruppen nicht existieren
|
# Create groups if they don't exist
|
||||||
if [[ -z "$video_gid" ]]; then
|
if [[ -z "$video_gid" ]]; then
|
||||||
# Versuche die video Gruppe zu erstellen
|
pct exec "$CTID" -- sh -c "groupadd -r video 2>/dev/null || true" >/dev/null 2>&1
|
||||||
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")
|
video_gid=$(pct exec "$CTID" -- sh -c "getent group video 2>/dev/null | cut -d: -f3")
|
||||||
[[ -z "$video_gid" ]] && video_gid="44" # Ultimate fallback
|
[[ -z "$video_gid" ]] && video_gid="44"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -z "$render_gid" ]]; then
|
if [[ -z "$render_gid" ]]; then
|
||||||
# Versuche die render Gruppe zu erstellen
|
pct exec "$CTID" -- sh -c "groupadd -r render 2>/dev/null || true" >/dev/null 2>&1
|
||||||
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")
|
render_gid=$(pct exec "$CTID" -- sh -c "getent group render 2>/dev/null | cut -d: -f3")
|
||||||
[[ -z "$render_gid" ]] && render_gid="104" # Ultimate fallback
|
[[ -z "$render_gid" ]] && render_gid="104"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
msg_custom "ℹ️" "${DGN}" "Container GIDs detected - video:${video_gid}, render:${render_gid}"
|
# Stop container to update config
|
||||||
|
pct stop "$CTID" >/dev/null 2>&1
|
||||||
|
sleep 1
|
||||||
|
|
||||||
# Prüfe ob die GIDs von den Defaults abweichen
|
# Update dev entries with correct GIDs
|
||||||
local need_update=0
|
sed -i.bak -E "s|(dev[0-9]+: /dev/dri/renderD[0-9]+),gid=[0-9]+|\1,gid=${render_gid}|g" "$LXC_CONFIG"
|
||||||
if [[ "$video_gid" != "44" ]] || [[ "$render_gid" != "104" ]]; then
|
sed -i -E "s|(dev[0-9]+: /dev/dri/card[0-9]+),gid=[0-9]+|\1,gid=${video_gid}|g" "$LXC_CONFIG"
|
||||||
need_update=1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ $need_update -eq 1 ]]; then
|
# Restart container
|
||||||
msg_custom "🔄" "${YW}" "Updating device GIDs in container config"
|
pct start "$CTID" >/dev/null 2>&1
|
||||||
|
sleep 2
|
||||||
|
|
||||||
# Stoppe Container für Config-Update
|
msg_ok "GPU passthrough configured (video:${video_gid}, render:${render_gid})"
|
||||||
pct stop "$CTID" >/dev/null 2>&1
|
|
||||||
|
|
||||||
# Update die dev Einträge mit korrekten GIDs
|
# For privileged containers: also fix permissions inside container
|
||||||
# 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
|
if [[ "$CT_TYPE" == "0" ]]; then
|
||||||
pct exec "$CTID" -- bash -c "
|
pct exec "$CTID" -- bash -c "
|
||||||
if [ -d /dev/dri ]; then
|
if [ -d /dev/dri ]; then
|
||||||
@ -2903,7 +3136,7 @@ create_lxc_container() {
|
|||||||
case "${_ans,,}" in
|
case "${_ans,,}" in
|
||||||
y | yes)
|
y | yes)
|
||||||
msg_info "Upgrading Proxmox LXC stack (pve-container, lxc-pve)"
|
msg_info "Upgrading Proxmox LXC stack (pve-container, lxc-pve)"
|
||||||
if apt-get update -qq >/dev/null && apt-get install -y --only-upgrade pve-container lxc-pve >/dev/null; then
|
if $STD apt-get update && $STD apt-get install -y --only-upgrade pve-container lxc-pve; then
|
||||||
msg_ok "LXC stack upgraded."
|
msg_ok "LXC stack upgraded."
|
||||||
if [[ "$do_retry" == "yes" ]]; then
|
if [[ "$do_retry" == "yes" ]]; then
|
||||||
msg_info "Retrying container creation after upgrade"
|
msg_info "Retrying container creation after upgrade"
|
||||||
@ -3348,13 +3581,13 @@ create_lxc_container() {
|
|||||||
exit 211
|
exit 211
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGFILE="/tmp/pct_create_${CTID}.log"
|
LOGFILE="/tmp/pct_create_${CTID}_$(date +%Y%m%d_%H%M%S)_${SESSION_ID}.log"
|
||||||
msg_debug "pct create command: pct create $CTID ${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE} ${PCT_OPTIONS[*]}"
|
msg_debug "pct create command: pct create $CTID ${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE} ${PCT_OPTIONS[*]}"
|
||||||
msg_debug "Logfile: $LOGFILE"
|
msg_debug "Logfile: $LOGFILE"
|
||||||
|
|
||||||
# First attempt
|
# First attempt
|
||||||
if ! pct create "$CTID" "${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE}" "${PCT_OPTIONS[@]}" >"$LOGFILE" 2>&1; then
|
if ! pct create "$CTID" "${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE}" "${PCT_OPTIONS[@]}" >"$LOGFILE" 2>&1; then
|
||||||
msg_error "Container creation failed on ${TEMPLATE_STORAGE}. Checking template..."
|
msg_debug "Container creation failed on ${TEMPLATE_STORAGE}. Validating template..."
|
||||||
|
|
||||||
# Validate template file
|
# Validate template file
|
||||||
if [[ ! -s "$TEMPLATE_PATH" || "$(stat -c%s "$TEMPLATE_PATH")" -lt 1000000 ]]; then
|
if [[ ! -s "$TEMPLATE_PATH" || "$(stat -c%s "$TEMPLATE_PATH")" -lt 1000000 ]]; then
|
||||||
@ -3373,18 +3606,16 @@ create_lxc_container() {
|
|||||||
|
|
||||||
# Retry after repair
|
# Retry after repair
|
||||||
if ! pct create "$CTID" "${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE}" "${PCT_OPTIONS[@]}" >>"$LOGFILE" 2>&1; then
|
if ! pct create "$CTID" "${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE}" "${PCT_OPTIONS[@]}" >>"$LOGFILE" 2>&1; then
|
||||||
# Fallback to local storage
|
# Fallback to local storage if not already on local
|
||||||
if [[ "$TEMPLATE_STORAGE" != "local" ]]; then
|
if [[ "$TEMPLATE_STORAGE" != "local" ]]; then
|
||||||
msg_warn "Retrying container creation with fallback to local storage..."
|
msg_info "Retrying container creation with fallback to local storage..."
|
||||||
LOCAL_TEMPLATE_PATH="/var/lib/vz/template/cache/$TEMPLATE"
|
LOCAL_TEMPLATE_PATH="/var/lib/vz/template/cache/$TEMPLATE"
|
||||||
if [[ ! -f "$LOCAL_TEMPLATE_PATH" ]]; then
|
if [[ ! -f "$LOCAL_TEMPLATE_PATH" ]]; then
|
||||||
msg_info "Downloading template to local..."
|
msg_info "Downloading template to local..."
|
||||||
pveam download local "$TEMPLATE" >/dev/null 2>&1
|
pveam download local "$TEMPLATE" >/dev/null 2>&1
|
||||||
fi
|
fi
|
||||||
if pct create "$CTID" "local:vztmpl/${TEMPLATE}" "${PCT_OPTIONS[@]}" >>"$LOGFILE" 2>&1; then
|
if ! pct create "$CTID" "local:vztmpl/${TEMPLATE}" "${PCT_OPTIONS[@]}" >>"$LOGFILE" 2>&1; then
|
||||||
msg_ok "Container successfully created using local fallback."
|
# Local fallback also failed - check for LXC stack version issue
|
||||||
else
|
|
||||||
# --- Dynamic stack upgrade + auto-retry on the well-known error pattern ---
|
|
||||||
if grep -qiE 'unsupported .* version' "$LOGFILE"; then
|
if grep -qiE 'unsupported .* version' "$LOGFILE"; then
|
||||||
echo
|
echo
|
||||||
echo "pct reported 'unsupported ... version' – your LXC stack might be too old for this template."
|
echo "pct reported 'unsupported ... version' – your LXC stack might be too old for this template."
|
||||||
@ -3404,18 +3635,19 @@ create_lxc_container() {
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
else
|
else
|
||||||
msg_error "Container creation failed even with local fallback. See $LOGFILE"
|
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
|
if whiptail --yesno "pct create failed.\nDo you want to enable verbose debug mode and view detailed logs?" 12 70; then
|
||||||
set -x
|
set -x
|
||||||
bash -x -c "pct create $CTID local:vztmpl/${TEMPLATE} ${PCT_OPTIONS[*]}" 2>&1 | tee -a "$LOGFILE"
|
pct create "$CTID" "local:vztmpl/${TEMPLATE}" "${PCT_OPTIONS[@]}" 2>&1 | tee -a "$LOGFILE"
|
||||||
set +x
|
set +x
|
||||||
fi
|
fi
|
||||||
exit 209
|
exit 209
|
||||||
fi
|
fi
|
||||||
|
else
|
||||||
|
msg_ok "Container successfully created using local fallback."
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
msg_error "Container creation failed on local storage. See $LOGFILE"
|
# Already on local storage and still failed - check LXC stack version
|
||||||
# --- Dynamic stack upgrade + auto-retry on the well-known error pattern ---
|
|
||||||
if grep -qiE 'unsupported .* version' "$LOGFILE"; then
|
if grep -qiE 'unsupported .* version' "$LOGFILE"; then
|
||||||
echo
|
echo
|
||||||
echo "pct reported 'unsupported ... version' – your LXC stack might be too old for this template."
|
echo "pct reported 'unsupported ... version' – your LXC stack might be too old for this template."
|
||||||
@ -3438,12 +3670,14 @@ create_lxc_container() {
|
|||||||
msg_error "Container creation failed. See $LOGFILE"
|
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
|
if whiptail --yesno "pct create failed.\nDo you want to enable verbose debug mode and view detailed logs?" 12 70; then
|
||||||
set -x
|
set -x
|
||||||
bash -x -c "pct create $CTID local:vztmpl/${TEMPLATE} ${PCT_OPTIONS[*]}" 2>&1 | tee -a "$LOGFILE"
|
pct create "$CTID" "local:vztmpl/${TEMPLATE}" "${PCT_OPTIONS[@]}" 2>&1 | tee -a "$LOGFILE"
|
||||||
set +x
|
set +x
|
||||||
fi
|
fi
|
||||||
exit 209
|
exit 209
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
else
|
||||||
|
msg_ok "Container successfully created after template repair."
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -3460,6 +3694,9 @@ create_lxc_container() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
msg_ok "LXC Container ${BL}$CTID${CL} ${GN}was successfully created."
|
msg_ok "LXC Container ${BL}$CTID${CL} ${GN}was successfully created."
|
||||||
|
|
||||||
|
# Report container creation to API
|
||||||
|
post_to_api
|
||||||
}
|
}
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
|
|||||||
277
misc/install copy.func
Normal file
277
misc/install copy.func
Normal file
@ -0,0 +1,277 @@
|
|||||||
|
# Copyright (c) 2021-2025 tteck
|
||||||
|
# Author: tteck (tteckster)
|
||||||
|
# Co-Author: MickLesk
|
||||||
|
# Co-Author: michelroegl-brunner
|
||||||
|
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
||||||
|
|
||||||
|
# ==============================================================================
|
||||||
|
# INSTALL.FUNC - CONTAINER INSTALLATION & SETUP
|
||||||
|
# ==============================================================================
|
||||||
|
#
|
||||||
|
# This file provides installation functions executed inside LXC containers
|
||||||
|
# after creation. Handles:
|
||||||
|
#
|
||||||
|
# - Network connectivity verification (IPv4/IPv6)
|
||||||
|
# - OS updates and package installation
|
||||||
|
# - DNS resolution checks
|
||||||
|
# - MOTD and SSH configuration
|
||||||
|
# - Container customization and auto-login
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# - Sourced by <app>-install.sh scripts
|
||||||
|
# - Executes via pct exec inside container
|
||||||
|
# - Requires internet connectivity
|
||||||
|
#
|
||||||
|
# ==============================================================================
|
||||||
|
|
||||||
|
# ==============================================================================
|
||||||
|
# SECTION 1: INITIALIZATION
|
||||||
|
# ==============================================================================
|
||||||
|
|
||||||
|
if ! command -v curl >/dev/null 2>&1; then
|
||||||
|
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||||
|
apt-get update >/dev/null 2>&1
|
||||||
|
apt-get install -y curl >/dev/null 2>&1
|
||||||
|
fi
|
||||||
|
source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/core.func)
|
||||||
|
source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/error_handler.func)
|
||||||
|
load_functions
|
||||||
|
catch_errors
|
||||||
|
|
||||||
|
# ==============================================================================
|
||||||
|
# SECTION 2: NETWORK & CONNECTIVITY
|
||||||
|
# ==============================================================================
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# verb_ip6()
|
||||||
|
#
|
||||||
|
# - Configures IPv6 based on DISABLEIPV6 variable
|
||||||
|
# - If DISABLEIPV6=yes: disables IPv6 via sysctl
|
||||||
|
# - Sets verbose mode via set_std_mode()
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
verb_ip6() {
|
||||||
|
set_std_mode # Set STD mode based on VERBOSE
|
||||||
|
|
||||||
|
if [ "$DISABLEIPV6" == "yes" ]; then
|
||||||
|
echo "net.ipv6.conf.all.disable_ipv6 = 1" >>/etc/sysctl.conf
|
||||||
|
$STD sysctl -p
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# setting_up_container()
|
||||||
|
#
|
||||||
|
# - Verifies network connectivity via hostname -I
|
||||||
|
# - Retries up to RETRY_NUM times with RETRY_EVERY seconds delay
|
||||||
|
# - Removes Python EXTERNALLY-MANAGED restrictions
|
||||||
|
# - Disables systemd-networkd-wait-online.service for faster boot
|
||||||
|
# - Exits with error if network unavailable after retries
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
setting_up_container() {
|
||||||
|
msg_info "Setting up Container OS"
|
||||||
|
for ((i = RETRY_NUM; i > 0; i--)); do
|
||||||
|
if [ "$(hostname -I)" != "" ]; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
echo 1>&2 -en "${CROSS}${RD} No Network! "
|
||||||
|
sleep $RETRY_EVERY
|
||||||
|
done
|
||||||
|
if [ "$(hostname -I)" = "" ]; then
|
||||||
|
echo 1>&2 -e "\n${CROSS}${RD} No Network After $RETRY_NUM Tries${CL}"
|
||||||
|
echo -e "${NETWORK}Check Network Settings"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED
|
||||||
|
systemctl disable -q --now systemd-networkd-wait-online.service
|
||||||
|
msg_ok "Set up Container OS"
|
||||||
|
#msg_custom "${CM}" "${GN}" "Network Connected: ${BL}$(hostname -I)"
|
||||||
|
msg_ok "Network Connected: ${BL}$(hostname -I)"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# network_check()
|
||||||
|
#
|
||||||
|
# - Comprehensive network connectivity check for IPv4 and IPv6
|
||||||
|
# - Tests connectivity to multiple DNS servers:
|
||||||
|
# * IPv4: 1.1.1.1 (Cloudflare), 8.8.8.8 (Google), 9.9.9.9 (Quad9)
|
||||||
|
# * IPv6: 2606:4700:4700::1111, 2001:4860:4860::8888, 2620:fe::fe
|
||||||
|
# - Verifies DNS resolution for GitHub and Community-Scripts domains
|
||||||
|
# - Prompts user to continue if no internet detected
|
||||||
|
# - Uses fatal() on DNS resolution failure for critical hosts
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
network_check() {
|
||||||
|
set +e
|
||||||
|
trap - ERR
|
||||||
|
ipv4_connected=false
|
||||||
|
ipv6_connected=false
|
||||||
|
sleep 1
|
||||||
|
|
||||||
|
# Check IPv4 connectivity to Google, Cloudflare & Quad9 DNS servers.
|
||||||
|
if ping -c 1 -W 1 1.1.1.1 &>/dev/null || ping -c 1 -W 1 8.8.8.8 &>/dev/null || ping -c 1 -W 1 9.9.9.9 &>/dev/null; then
|
||||||
|
msg_ok "IPv4 Internet Connected"
|
||||||
|
ipv4_connected=true
|
||||||
|
else
|
||||||
|
msg_error "IPv4 Internet Not Connected"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check IPv6 connectivity to Google, Cloudflare & Quad9 DNS servers.
|
||||||
|
if ping6 -c 1 -W 1 2606:4700:4700::1111 &>/dev/null || ping6 -c 1 -W 1 2001:4860:4860::8888 &>/dev/null || ping6 -c 1 -W 1 2620:fe::fe &>/dev/null; then
|
||||||
|
msg_ok "IPv6 Internet Connected"
|
||||||
|
ipv6_connected=true
|
||||||
|
else
|
||||||
|
msg_error "IPv6 Internet Not Connected"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If both IPv4 and IPv6 checks fail, prompt the user
|
||||||
|
if [[ $ipv4_connected == false && $ipv6_connected == false ]]; then
|
||||||
|
read -r -p "No Internet detected, would you like to continue anyway? <y/N> " prompt
|
||||||
|
if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||||
|
echo -e "${INFO}${RD}Expect Issues Without Internet${CL}"
|
||||||
|
else
|
||||||
|
echo -e "${NETWORK}Check Network Settings"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# DNS resolution checks for GitHub-related domains (IPv4 and/or IPv6)
|
||||||
|
GIT_HOSTS=("github.com" "raw.githubusercontent.com" "api.github.com" "git.community-scripts.org")
|
||||||
|
GIT_STATUS="Git DNS:"
|
||||||
|
DNS_FAILED=false
|
||||||
|
|
||||||
|
for HOST in "${GIT_HOSTS[@]}"; do
|
||||||
|
RESOLVEDIP=$(getent hosts "$HOST" | awk '{ print $1 }' | grep -E '(^([0-9]{1,3}\.){3}[0-9]{1,3}$)|(^[a-fA-F0-9:]+$)' | head -n1)
|
||||||
|
if [[ -z "$RESOLVEDIP" ]]; then
|
||||||
|
GIT_STATUS+="$HOST:($DNSFAIL)"
|
||||||
|
DNS_FAILED=true
|
||||||
|
else
|
||||||
|
GIT_STATUS+=" $HOST:($DNSOK)"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ "$DNS_FAILED" == true ]]; then
|
||||||
|
fatal "$GIT_STATUS"
|
||||||
|
else
|
||||||
|
msg_ok "$GIT_STATUS"
|
||||||
|
fi
|
||||||
|
|
||||||
|
set -e
|
||||||
|
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
|
||||||
|
}
|
||||||
|
|
||||||
|
# ==============================================================================
|
||||||
|
# SECTION 3: OS UPDATE & PACKAGE MANAGEMENT
|
||||||
|
# ==============================================================================
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# update_os()
|
||||||
|
#
|
||||||
|
# - Updates container OS via apt-get update and dist-upgrade
|
||||||
|
# - Configures APT cacher proxy if CACHER=yes (accelerates package downloads)
|
||||||
|
# - Removes Python EXTERNALLY-MANAGED restrictions for pip
|
||||||
|
# - Sources tools.func for additional setup functions after update
|
||||||
|
# - Uses $STD wrapper to suppress output unless VERBOSE=yes
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
update_os() {
|
||||||
|
msg_info "Updating Container OS"
|
||||||
|
if [[ "$CACHER" == "yes" ]]; then
|
||||||
|
echo "Acquire::http::Proxy-Auto-Detect \"/usr/local/bin/apt-proxy-detect.sh\";" >/etc/apt/apt.conf.d/00aptproxy
|
||||||
|
cat <<'EOF' >/usr/local/bin/apt-proxy-detect.sh
|
||||||
|
#!/bin/bash
|
||||||
|
if nc -w1 -z "${CACHER_IP}" 3142; then
|
||||||
|
echo -n "http://${CACHER_IP}:3142"
|
||||||
|
else
|
||||||
|
echo -n "DIRECT"
|
||||||
|
fi
|
||||||
|
EOF
|
||||||
|
chmod +x /usr/local/bin/apt-proxy-detect.sh
|
||||||
|
fi
|
||||||
|
$STD apt-get update
|
||||||
|
$STD apt-get -o Dpkg::Options::="--force-confold" -y dist-upgrade
|
||||||
|
rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED
|
||||||
|
msg_ok "Updated Container OS"
|
||||||
|
source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/tools.func)
|
||||||
|
}
|
||||||
|
|
||||||
|
# ==============================================================================
|
||||||
|
# SECTION 4: MOTD & SSH CONFIGURATION
|
||||||
|
# ==============================================================================
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# motd_ssh()
|
||||||
|
#
|
||||||
|
# - Configures Message of the Day (MOTD) with container information
|
||||||
|
# - Creates /etc/profile.d/00_lxc-details.sh with:
|
||||||
|
# * Application name
|
||||||
|
# * Warning banner (DEV repository)
|
||||||
|
# * OS name and version
|
||||||
|
# * Hostname and IP address
|
||||||
|
# * GitHub repository link
|
||||||
|
# - Disables executable flag on /etc/update-motd.d/* scripts
|
||||||
|
# - Enables root SSH access if SSH_ROOT=yes
|
||||||
|
# - Configures TERM environment variable for better terminal support
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
motd_ssh() {
|
||||||
|
grep -qxF "export TERM='xterm-256color'" /root/.bashrc || echo "export TERM='xterm-256color'" >>/root/.bashrc
|
||||||
|
|
||||||
|
if [ -f "/etc/os-release" ]; then
|
||||||
|
OS_NAME=$(grep ^NAME /etc/os-release | cut -d= -f2 | tr -d '"')
|
||||||
|
OS_VERSION=$(grep ^VERSION_ID /etc/os-release | cut -d= -f2 | tr -d '"')
|
||||||
|
elif [ -f "/etc/debian_version" ]; then
|
||||||
|
OS_NAME="Debian"
|
||||||
|
OS_VERSION=$(cat /etc/debian_version)
|
||||||
|
fi
|
||||||
|
|
||||||
|
PROFILE_FILE="/etc/profile.d/00_lxc-details.sh"
|
||||||
|
echo "echo -e \"\"" >"$PROFILE_FILE"
|
||||||
|
echo -e "echo -e \"${BOLD}${YW}${APPLICATION} LXC Container - DEV Repository${CL}\"" >>"$PROFILE_FILE"
|
||||||
|
echo -e "echo -e \"${RD}WARNING: This is a DEVELOPMENT version (ProxmoxVED). Do NOT use in production!${CL}\"" >>"$PROFILE_FILE"
|
||||||
|
echo -e "echo -e \"${YW} OS: ${GN}${OS_NAME} - Version: ${OS_VERSION}${CL}\"" >>"$PROFILE_FILE"
|
||||||
|
echo -e "echo -e \"${YW} Hostname: ${GN}\$(hostname)${CL}\"" >>"$PROFILE_FILE"
|
||||||
|
echo -e "echo -e \"${YW} IP Address: ${GN}\$(hostname -I | awk '{print \$1}')${CL}\"" >>"$PROFILE_FILE"
|
||||||
|
echo -e "echo -e \"${YW} Repository: ${GN}https://github.com/community-scripts/ProxmoxVED${CL}\"" >>"$PROFILE_FILE"
|
||||||
|
echo "echo \"\"" >>"$PROFILE_FILE"
|
||||||
|
|
||||||
|
chmod -x /etc/update-motd.d/*
|
||||||
|
|
||||||
|
if [[ "${SSH_ROOT}" == "yes" ]]; then
|
||||||
|
sed -i "s/#PermitRootLogin prohibit-password/PermitRootLogin yes/g" /etc/ssh/sshd_config
|
||||||
|
systemctl restart sshd
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# ==============================================================================
|
||||||
|
# SECTION 5: CONTAINER CUSTOMIZATION
|
||||||
|
# ==============================================================================
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# customize()
|
||||||
|
#
|
||||||
|
# - Customizes container for passwordless root login if PASSWORD is empty
|
||||||
|
# - Configures getty for auto-login via /etc/systemd/system/container-getty@1.service.d/override.conf
|
||||||
|
# - Creates /usr/bin/update script for easy application updates
|
||||||
|
# - Injects SSH authorized keys if SSH_AUTHORIZED_KEY variable is set
|
||||||
|
# - Sets proper permissions on SSH directories and key files
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
customize() {
|
||||||
|
if [[ "$PASSWORD" == "" ]]; then
|
||||||
|
msg_info "Customizing Container"
|
||||||
|
GETTY_OVERRIDE="/etc/systemd/system/container-getty@1.service.d/override.conf"
|
||||||
|
mkdir -p $(dirname $GETTY_OVERRIDE)
|
||||||
|
cat <<EOF >$GETTY_OVERRIDE
|
||||||
|
[Service]
|
||||||
|
ExecStart=
|
||||||
|
ExecStart=-/sbin/agetty --autologin root --noclear --keep-baud tty%I 115200,38400,9600 \$TERM
|
||||||
|
EOF
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl restart $(basename $(dirname $GETTY_OVERRIDE) | sed 's/\.d//')
|
||||||
|
msg_ok "Customized Container"
|
||||||
|
fi
|
||||||
|
echo "bash -c \"\$(curl -fsSL https://github.com/community-scripts/ProxmoxVED/raw/main/ct/${app}.sh)\"" >/usr/bin/update
|
||||||
|
chmod +x /usr/bin/update
|
||||||
|
if [[ -n "${SSH_AUTHORIZED_KEY}" ]]; then
|
||||||
|
mkdir -p /root/.ssh
|
||||||
|
echo "${SSH_AUTHORIZED_KEY}" >/root/.ssh/authorized_keys
|
||||||
|
chmod 700 /root/.ssh
|
||||||
|
chmod 600 /root/.ssh/authorized_keys
|
||||||
|
fi
|
||||||
|
}
|
||||||
@ -28,6 +28,17 @@
|
|||||||
# SECTION 1: INITIALIZATION
|
# SECTION 1: INITIALIZATION
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
|
|
||||||
|
# Ensure INSTALL_LOG is set (exported from build.func, but fallback if missing)
|
||||||
|
if [[ -z "${INSTALL_LOG:-}" ]]; then
|
||||||
|
INSTALL_LOG="/root/.install-${SESSION_ID:-unknown}.log"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Dev mode: Persistent logs directory
|
||||||
|
if [[ "${DEV_MODE_LOGS:-false}" == "true" ]]; then
|
||||||
|
mkdir -p /var/log/community-scripts
|
||||||
|
INSTALL_LOG="/var/log/community-scripts/install-${SESSION_ID:-unknown}-$(date +%Y%m%d_%H%M%S).log"
|
||||||
|
fi
|
||||||
|
|
||||||
if ! command -v curl >/dev/null 2>&1; then
|
if ! command -v curl >/dev/null 2>&1; then
|
||||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||||
apt-get update >/dev/null 2>&1
|
apt-get update >/dev/null 2>&1
|
||||||
@ -38,6 +49,9 @@ source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxV
|
|||||||
load_functions
|
load_functions
|
||||||
catch_errors
|
catch_errors
|
||||||
|
|
||||||
|
# Re-parse dev_mode in container context (flags exported from host)
|
||||||
|
parse_dev_mode
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
# SECTION 2: NETWORK & CONNECTIVITY
|
# SECTION 2: NETWORK & CONNECTIVITY
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
@ -108,20 +122,23 @@ network_check() {
|
|||||||
|
|
||||||
# Check IPv4 connectivity to Google, Cloudflare & Quad9 DNS servers.
|
# Check IPv4 connectivity to Google, Cloudflare & Quad9 DNS servers.
|
||||||
if ping -c 1 -W 1 1.1.1.1 &>/dev/null || ping -c 1 -W 1 8.8.8.8 &>/dev/null || ping -c 1 -W 1 9.9.9.9 &>/dev/null; then
|
if ping -c 1 -W 1 1.1.1.1 &>/dev/null || ping -c 1 -W 1 8.8.8.8 &>/dev/null || ping -c 1 -W 1 9.9.9.9 &>/dev/null; then
|
||||||
msg_ok "IPv4 Internet Connected"
|
|
||||||
ipv4_connected=true
|
ipv4_connected=true
|
||||||
|
ipv4_status="${GN}✔${CL} IPv4"
|
||||||
else
|
else
|
||||||
msg_error "IPv4 Internet Not Connected"
|
ipv4_status="${RD}✖${CL} IPv4"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check IPv6 connectivity to Google, Cloudflare & Quad9 DNS servers.
|
# Check IPv6 connectivity to Google, Cloudflare & Quad9 DNS servers.
|
||||||
if ping6 -c 1 -W 1 2606:4700:4700::1111 &>/dev/null || ping6 -c 1 -W 1 2001:4860:4860::8888 &>/dev/null || ping6 -c 1 -W 1 2620:fe::fe &>/dev/null; then
|
if ping6 -c 1 -W 1 2606:4700:4700::1111 &>/dev/null || ping6 -c 1 -W 1 2001:4860:4860::8888 &>/dev/null || ping6 -c 1 -W 1 2620:fe::fe &>/dev/null; then
|
||||||
msg_ok "IPv6 Internet Connected"
|
|
||||||
ipv6_connected=true
|
ipv6_connected=true
|
||||||
|
ipv6_status="${GN}✔${CL} IPv6"
|
||||||
else
|
else
|
||||||
msg_error "IPv6 Internet Not Connected"
|
ipv6_status="${RD}✖${CL} IPv6"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Show combined status
|
||||||
|
msg_ok "Internet: ${ipv4_status} ${ipv6_status}"
|
||||||
|
|
||||||
# If both IPv4 and IPv6 checks fail, prompt the user
|
# If both IPv4 and IPv6 checks fail, prompt the user
|
||||||
if [[ $ipv4_connected == false && $ipv6_connected == false ]]; then
|
if [[ $ipv4_connected == false && $ipv6_connected == false ]]; then
|
||||||
read -r -p "No Internet detected, would you like to continue anyway? <y/N> " prompt
|
read -r -p "No Internet detected, would you like to continue anyway? <y/N> " prompt
|
||||||
@ -239,10 +256,6 @@ motd_ssh() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# ==============================================================================
|
|
||||||
# SECTION 5: CONTAINER CUSTOMIZATION
|
|
||||||
# ==============================================================================
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# customize()
|
# customize()
|
||||||
#
|
#
|
||||||
@ -253,21 +266,33 @@ motd_ssh() {
|
|||||||
# - Sets proper permissions on SSH directories and key files
|
# - Sets proper permissions on SSH directories and key files
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
customize() {
|
customize() {
|
||||||
if [[ "$PASSWORD" == "" ]]; then
|
if [[ -z "${PASSWORD:-}" ]]; then
|
||||||
msg_info "Customizing Container"
|
msg_info "Configuring autologin for root"
|
||||||
|
|
||||||
|
# Enable root account (remove password lock)
|
||||||
|
passwd -d root >/dev/null 2>&1 || true
|
||||||
|
|
||||||
|
# Create getty override for container-getty@1.service
|
||||||
GETTY_OVERRIDE="/etc/systemd/system/container-getty@1.service.d/override.conf"
|
GETTY_OVERRIDE="/etc/systemd/system/container-getty@1.service.d/override.conf"
|
||||||
mkdir -p $(dirname $GETTY_OVERRIDE)
|
mkdir -p $(dirname $GETTY_OVERRIDE)
|
||||||
cat <<EOF >$GETTY_OVERRIDE
|
cat <<EOF >$GETTY_OVERRIDE
|
||||||
[Service]
|
[Service]
|
||||||
ExecStart=
|
ExecStart=
|
||||||
ExecStart=-/sbin/agetty --autologin root --noclear --keep-baud tty%I 115200,38400,9600 \$TERM
|
ExecStart=-/sbin/agetty --autologin root --noclear --keep-baud tty%I 115200,38400,9600 \$TERM
|
||||||
EOF
|
EOF
|
||||||
systemctl daemon-reload
|
|
||||||
systemctl restart $(basename $(dirname $GETTY_OVERRIDE) | sed 's/\.d//')
|
# Reload and restart getty service
|
||||||
msg_ok "Customized Container"
|
$STD systemctl daemon-reload
|
||||||
|
$STD systemctl restart $(basename $(dirname $GETTY_OVERRIDE) | sed 's/\.d//') || true
|
||||||
|
|
||||||
|
msg_ok "Autologin configured"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
msg_ok "Customized Container"
|
||||||
|
|
||||||
echo "bash -c \"\$(curl -fsSL https://github.com/community-scripts/ProxmoxVED/raw/main/ct/${app}.sh)\"" >/usr/bin/update
|
echo "bash -c \"\$(curl -fsSL https://github.com/community-scripts/ProxmoxVED/raw/main/ct/${app}.sh)\"" >/usr/bin/update
|
||||||
chmod +x /usr/bin/update
|
chmod +x /usr/bin/update
|
||||||
|
|
||||||
if [[ -n "${SSH_AUTHORIZED_KEY}" ]]; then
|
if [[ -n "${SSH_AUTHORIZED_KEY}" ]]; then
|
||||||
mkdir -p /root/.ssh
|
mkdir -p /root/.ssh
|
||||||
echo "${SSH_AUTHORIZED_KEY}" >/root/.ssh/authorized_keys
|
echo "${SSH_AUTHORIZED_KEY}" >/root/.ssh/authorized_keys
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user