diff --git a/misc/build.func b/misc/build.func
index 706e5b57c..16bebd782 100644
--- a/misc/build.func
+++ b/misc/build.func
@@ -3425,6 +3425,9 @@ start() {
set_std_mode
ensure_profile_loaded
get_lxc_ip
+ if [[ "$(dpkg --print-architecture)" == "arm64" ]] && declare -f update_script_arm64 >/dev/null 2>&1; then
+ update_script_arm64
+ fi
update_script
update_motd_ip
cleanup_lxc
@@ -3453,6 +3456,9 @@ start() {
esac
ensure_profile_loaded
get_lxc_ip
+ if [[ "$(dpkg --print-architecture)" == "arm64" ]] && declare -f update_script_arm64 >/dev/null 2>&1; then
+ update_script_arm64
+ fi
update_script
update_motd_ip
cleanup_lxc
@@ -4096,7 +4102,16 @@ EOF'
# that sends "configuring" status AFTER the host already reported "failed"
export CONTAINER_INSTALLING=true
- lxc-attach -n "$CTID" -- bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/install/${var_install}.sh)"
+ local _install_script
+ _install_script="$(curl -fsSL "https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/install/${var_install}.sh")"
+ if [[ "$ARCH" == "arm64" ]]; then
+ local _arm_script
+ _arm_script="$(curl -fsSL "https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/install/arm/${var_install}.sh" 2>/dev/null || true)"
+ if [[ -n "$_arm_script" ]]; then
+ _install_script="${_arm_script}"$'\n'"${_install_script}"
+ fi
+ fi
+ lxc-attach -n "$CTID" -- bash -c "$_install_script"
local lxc_exit=$?
unset CONTAINER_INSTALLING
@@ -4474,7 +4489,16 @@ EOF'
# Re-run install script in existing container (don't destroy/recreate)
set +Eeuo pipefail
trap - ERR
- lxc-attach -n "$CTID" -- bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/install/${var_install}.sh)"
+ local _install_script
+ _install_script="$(curl -fsSL "https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/install/${var_install}.sh")"
+ if [[ "$ARCH" == "arm64" ]]; then
+ local _arm_script
+ _arm_script="$(curl -fsSL "https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/install/arm/${var_install}.sh" 2>/dev/null || true)"
+ if [[ -n "$_arm_script" ]]; then
+ _install_script="${_arm_script}"$'\n'"${_install_script}"
+ fi
+ fi
+ lxc-attach -n "$CTID" -- bash -c "$_install_script"
local apt_retry_exit=$?
set -Eeuo pipefail
trap 'error_handler' ERR
@@ -4993,6 +5017,64 @@ create_lxc_container() {
esac
}
+ ARCH="$(dpkg --print-architecture)"
+
+ # Maps OS type + version to the release variant name used by ARM64 template sources.
+ arm64_template_variant() {
+ case "$1" in
+ debian)
+ case "$2" in
+ 11 | 11.*) echo "bullseye" ;; 12 | 12.*) echo "bookworm" ;;
+ 13 | 13.*) echo "trixie" ;; *) echo "trixie" ;;
+ esac ;;
+ alpine) echo "3.22" ;;
+ ubuntu)
+ case "$2" in
+ 20.04* | focal) echo "focal" ;; 24.04* | noble) echo "noble" ;;
+ 24.10* | oracular) echo "oracular" ;; *) echo "jammy" ;;
+ esac ;;
+ *) return 1 ;;
+ esac
+ }
+
+ # Downloads an ARM64 LXC rootfs template to $1.
+ # Debian: fetches latest release from asylumexp/debian-ifupdown2-lxc on GitHub.
+ # Others: fetches from jenkins.linuxcontainers.org.
+ download_arm64_template() {
+ local dest="$1" url
+
+ mkdir -p "$(dirname "$dest")" || { msg_error "Cannot create template dir."; exit 207; }
+
+ if [[ "$PCT_OSTYPE" == "debian" ]]; then
+ url=$(curl -fsSL "https://api.github.com/repos/asylumexp/debian-ifupdown2-lxc/releases/latest" \
+ | grep -Eo "https://[^\"]*debian-${CUSTOM_TEMPLATE_VARIANT}-arm64-rootfs\.tar\.xz" | head -n1)
+ [[ -n "$url" ]] || { msg_error "Could not find Debian ${CUSTOM_TEMPLATE_VARIANT} ARM64 template URL."; exit 207; }
+ else
+ url="https://jenkins.linuxcontainers.org/job/image-${PCT_OSTYPE}/architecture=arm64,release=${CUSTOM_TEMPLATE_VARIANT},variant=default/lastStableBuild/artifact/rootfs.tar.xz"
+ fi
+
+ msg_info "Downloading ${PCT_OSTYPE^} ${CUSTOM_TEMPLATE_VARIANT} ARM64 template"
+ if ! curl -fsSL -o "$dest" "$url"; then
+ msg_error "Failed to download ARM64 template from: $url"
+ exit 208
+ fi
+ msg_ok "Downloaded ARM64 LXC template"
+ }
+
+ # Architecture-aware template download wrapper.
+ # Optional $1 overrides destination path (for local-storage fallback).
+ download_template() {
+ local dest="${1:-$TEMPLATE_PATH}"
+ if [[ "$ARCH" == "arm64" ]]; then
+ download_arm64_template "$dest"
+ else
+ pveam download "$TEMPLATE_STORAGE" "$TEMPLATE" >>"${BUILD_LOG:-/dev/null}" 2>&1 || {
+ msg_error "Failed to download template '$TEMPLATE' to storage '$TEMPLATE_STORAGE'"
+ exit 222
+ }
+ fi
+ }
+
# ------------------------------------------------------------------------------
# Required input variables
# ------------------------------------------------------------------------------
@@ -5129,153 +5211,116 @@ create_lxc_container() {
# ------------------------------------------------------------------------------
# Template discovery & validation
# ------------------------------------------------------------------------------
- TEMPLATE_SEARCH="${PCT_OSTYPE}-${PCT_OSVERSION:-}"
- case "$PCT_OSTYPE" in
- debian | ubuntu) TEMPLATE_PATTERN="-standard_" ;;
- alpine | fedora | rocky | centos) TEMPLATE_PATTERN="-default_" ;;
- *) TEMPLATE_PATTERN="" ;;
- esac
+ CUSTOM_TEMPLATE_VARIANT=""
- msg_info "Searching for template '$TEMPLATE_SEARCH'"
+ if [[ "$ARCH" == "arm64" ]]; then
+ # ARM64: use custom template download from linuxcontainers.org / GitHub
+ msg_info "Preparing ARM64 template"
- # Initialize variables
- ONLINE_TEMPLATE=""
- ONLINE_TEMPLATES=()
+ CUSTOM_TEMPLATE_VARIANT=$(arm64_template_variant "$PCT_OSTYPE" "${PCT_OSVERSION:-}") || {
+ msg_error "No ARM64 template mapping for ${PCT_OSTYPE} ${PCT_OSVERSION:-latest}"
+ exit 207
+ }
- # Step 1: Check local templates first (instant)
- mapfile -t LOCAL_TEMPLATES < <(
- pveam list "$TEMPLATE_STORAGE" 2>/dev/null |
- awk -v search="${TEMPLATE_SEARCH}" -v pattern="${TEMPLATE_PATTERN}" '$1 ~ search && $1 ~ pattern {print $1}' |
- sed 's|.*/||' | sort -t - -k 2 -V
- )
+ TEMPLATE="${PCT_OSTYPE}-${CUSTOM_TEMPLATE_VARIANT}-rootfs.tar.xz"
+ TEMPLATE_SOURCE="custom-arm64"
- # Step 2: If local template found, use it immediately (skip pveam update)
- if [[ ${#LOCAL_TEMPLATES[@]} -gt 0 ]]; then
- TEMPLATE="${LOCAL_TEMPLATES[-1]}"
- TEMPLATE_SOURCE="local"
- msg_ok "Template search completed"
- else
- # Step 3: No local template - need to check online (this may be slow)
- msg_info "No local template found, checking online catalog..."
-
- # Update catalog with timeout to prevent long hangs
- if command -v timeout &>/dev/null; then
- if ! timeout 30 pveam update >/dev/null 2>&1; then
- msg_warn "Template catalog update timed out (possible network/DNS issue). Run 'pveam update' manually to diagnose."
- fi
- else
- pveam update >/dev/null 2>&1 || msg_warn "Could not update template catalog (pveam update failed)"
+ # Resolve template path: pvesm â storage.cfg fallback â default
+ TEMPLATE_PATH="$(pvesm path "${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE}" 2>/dev/null || true)"
+ if [[ -z "$TEMPLATE_PATH" ]]; then
+ local _tpl_base
+ _tpl_base=$(awk -v s="$TEMPLATE_STORAGE" '$1==s {f=1} f && /path/ {print $2; exit}' /etc/pve/storage.cfg)
+ TEMPLATE_PATH="${_tpl_base:-/var/lib/vz}/template/cache/$TEMPLATE"
fi
+ # Download if missing, too small, or corrupt (single pass)
+ if [[ ! -f "$TEMPLATE_PATH" ]]; then
+ download_arm64_template "$TEMPLATE_PATH"
+ elif [[ "$(stat -c%s "$TEMPLATE_PATH")" -lt 1000000 ]] || ! tar -tf "$TEMPLATE_PATH" &>/dev/null; then
+ msg_warn "Local template invalid â re-downloading."
+ rm -f "$TEMPLATE_PATH"
+ download_arm64_template "$TEMPLATE_PATH"
+ else
+ msg_ok "Template ${BL}$TEMPLATE${CL} found locally."
+ fi
+
+ else
+ TEMPLATE_SEARCH="${PCT_OSTYPE}-${PCT_OSVERSION:-}"
+ case "$PCT_OSTYPE" in
+ debian | ubuntu) TEMPLATE_PATTERN="-standard_" ;;
+ alpine | fedora | rocky | centos) TEMPLATE_PATTERN="-default_" ;;
+ *) TEMPLATE_PATTERN="" ;;
+ esac
+
+ msg_info "Searching for template '$TEMPLATE_SEARCH'"
+
+ # Initialize variables
+ ONLINE_TEMPLATE=""
ONLINE_TEMPLATES=()
- mapfile -t ONLINE_TEMPLATES < <(pveam available -section system 2>/dev/null | grep -E '\.(tar\.zst|tar\.xz|tar\.gz)$' | awk '{print $2}' | grep -E "^${TEMPLATE_SEARCH}.*${TEMPLATE_PATTERN}" | sort -t - -k 2 -V 2>/dev/null || true)
- [[ ${#ONLINE_TEMPLATES[@]} -gt 0 ]] && ONLINE_TEMPLATE="${ONLINE_TEMPLATES[-1]}"
- TEMPLATE="$ONLINE_TEMPLATE"
- TEMPLATE_SOURCE="online"
- msg_ok "Template search completed"
- fi
-
- # If still no template, try to find alternatives
- if [[ -z "$TEMPLATE" ]]; then
- msg_warn "No template found for ${PCT_OSTYPE} ${PCT_OSVERSION}, searching for alternatives..."
-
- # Get all available versions for this OS type
- AVAILABLE_VERSIONS=()
- mapfile -t AVAILABLE_VERSIONS < <(
- pveam available -section system 2>/dev/null |
- grep -E '\.(tar\.zst|tar\.xz|tar\.gz)$' |
- awk -F'\t' '{print $1}' |
- grep "^${PCT_OSTYPE}-" |
- sed -E "s/.*${PCT_OSTYPE}-([0-9]+(\.[0-9]+)?).*/\1/" |
- sort -u -V 2>/dev/null
+ # Step 1: Check local templates first (instant)
+ mapfile -t LOCAL_TEMPLATES < <(
+ pveam list "$TEMPLATE_STORAGE" 2>/dev/null |
+ awk -v search="${TEMPLATE_SEARCH}" -v pattern="${TEMPLATE_PATTERN}" '$1 ~ search && $1 ~ pattern {print $1}' |
+ sed 's|.*/||' | sort -t - -k 2 -V
)
- if [[ ${#AVAILABLE_VERSIONS[@]} -gt 0 ]]; then
- echo ""
- echo "${BL}Available ${PCT_OSTYPE} versions:${CL}"
- for i in "${!AVAILABLE_VERSIONS[@]}"; do
- echo " [$((i + 1))] ${AVAILABLE_VERSIONS[$i]}"
- done
- echo ""
- read -p "Select version [1-${#AVAILABLE_VERSIONS[@]}] or press Enter to cancel: " choice /dev/null |
- grep -E '\.(tar\.zst|tar\.xz|tar\.gz)$' |
- awk '{print $2}' |
- grep -E "^${TEMPLATE_SEARCH}-.*${TEMPLATE_PATTERN}" |
- sort -t - -k 2 -V 2>/dev/null || true
- )
-
- if [[ ${#ONLINE_TEMPLATES[@]} -gt 0 ]]; then
- TEMPLATE="${ONLINE_TEMPLATES[-1]}"
- TEMPLATE_SOURCE="online"
- else
- msg_error "No templates available for ${PCT_OSTYPE} ${PCT_OSVERSION}"
- exit 225
+ # Update catalog with timeout to prevent long hangs
+ if command -v timeout &>/dev/null; then
+ if ! timeout 30 pveam update >/dev/null 2>&1; then
+ msg_warn "Template catalog update timed out (possible network/DNS issue). Run 'pveam update' manually to diagnose."
fi
else
- msg_custom "đĢ" "${YW}" "Installation cancelled"
- exit 0
+ pveam update >/dev/null 2>&1 || msg_warn "Could not update template catalog (pveam update failed)"
fi
- else
- msg_error "No ${PCT_OSTYPE} templates available at all"
- exit 225
+
+ ONLINE_TEMPLATES=()
+ mapfile -t ONLINE_TEMPLATES < <(pveam available -section system 2>/dev/null | grep -E '\.(tar\.zst|tar\.xz|tar\.gz)$' | awk '{print $2}' | grep -E "^${TEMPLATE_SEARCH}.*${TEMPLATE_PATTERN}" | sort -t - -k 2 -V 2>/dev/null || true)
+ [[ ${#ONLINE_TEMPLATES[@]} -gt 0 ]] && ONLINE_TEMPLATE="${ONLINE_TEMPLATES[-1]}"
+
+ TEMPLATE="$ONLINE_TEMPLATE"
+ TEMPLATE_SOURCE="online"
+ msg_ok "Template search completed"
fi
- fi
- TEMPLATE_PATH="$(pvesm path $TEMPLATE_STORAGE:vztmpl/$TEMPLATE 2>/dev/null || true)"
- if [[ -z "$TEMPLATE_PATH" ]]; then
- TEMPLATE_BASE=$(awk -v s="$TEMPLATE_STORAGE" '$1==s {f=1} f && /path/ {print $2; exit}' /etc/pve/storage.cfg)
- [[ -n "$TEMPLATE_BASE" ]] && TEMPLATE_PATH="$TEMPLATE_BASE/template/cache/$TEMPLATE"
- fi
-
- # If we still don't have a path but have a valid template name, construct it
- if [[ -z "$TEMPLATE_PATH" && -n "$TEMPLATE" ]]; then
- TEMPLATE_PATH="/var/lib/vz/template/cache/$TEMPLATE"
- fi
-
- [[ -n "$TEMPLATE_PATH" ]] || {
+ # If still no template, try to find alternatives
if [[ -z "$TEMPLATE" ]]; then
- msg_error "Template ${PCT_OSTYPE} ${PCT_OSVERSION} not available"
+ msg_warn "No template found for ${PCT_OSTYPE} ${PCT_OSVERSION}, searching for alternatives..."
- # Get available versions
+ # Get all available versions for this OS type
+ AVAILABLE_VERSIONS=()
mapfile -t AVAILABLE_VERSIONS < <(
pveam available -section system 2>/dev/null |
+ grep -E '\.(tar\.zst|tar\.xz|tar\.gz)$' |
+ awk -F'\t' '{print $1}' |
grep "^${PCT_OSTYPE}-" |
- sed -E 's/.*'"${PCT_OSTYPE}"'-([0-9]+\.[0-9]+).*/\1/' |
- grep -E '^[0-9]+\.[0-9]+$' |
- sort -u -V 2>/dev/null || sort -u
+ sed -E "s/.*${PCT_OSTYPE}-([0-9]+(\.[0-9]+)?).*/\1/" |
+ sort -u -V 2>/dev/null
)
if [[ ${#AVAILABLE_VERSIONS[@]} -gt 0 ]]; then
- echo -e "\n${BL}Available versions:${CL}"
+ echo ""
+ echo "${BL}Available ${PCT_OSTYPE} versions:${CL}"
for i in "${!AVAILABLE_VERSIONS[@]}"; do
echo " [$((i + 1))] ${AVAILABLE_VERSIONS[$i]}"
done
-
echo ""
- read -p "Select version [1-${#AVAILABLE_VERSIONS[@]}] or Enter to exit: " choice /dev/null |
- awk -v search="${TEMPLATE_SEARCH}-" -v pattern="${TEMPLATE_PATTERN}" '$1 ~ search && $1 ~ pattern {print $1}' |
- sed 's|.*/||' | sort -t - -k 2 -V
- )
+ ONLINE_TEMPLATES=()
mapfile -t ONLINE_TEMPLATES < <(
pveam available -section system 2>/dev/null |
grep -E '\.(tar\.zst|tar\.xz|tar\.gz)$' |
@@ -5283,109 +5328,181 @@ create_lxc_container() {
grep -E "^${TEMPLATE_SEARCH}-.*${TEMPLATE_PATTERN}" |
sort -t - -k 2 -V 2>/dev/null || true
)
- ONLINE_TEMPLATE=""
- [[ ${#ONLINE_TEMPLATES[@]} -gt 0 ]] && ONLINE_TEMPLATE="${ONLINE_TEMPLATES[-1]}"
- if [[ ${#LOCAL_TEMPLATES[@]} -gt 0 ]]; then
- TEMPLATE="${LOCAL_TEMPLATES[-1]}"
- TEMPLATE_SOURCE="local"
- else
- TEMPLATE="$ONLINE_TEMPLATE"
+ if [[ ${#ONLINE_TEMPLATES[@]} -gt 0 ]]; then
+ TEMPLATE="${ONLINE_TEMPLATES[-1]}"
TEMPLATE_SOURCE="online"
+ else
+ msg_error "No templates available for ${PCT_OSTYPE} ${PCT_OSVERSION}"
+ exit 225
fi
-
- TEMPLATE_PATH="$(pvesm path $TEMPLATE_STORAGE:vztmpl/$TEMPLATE 2>/dev/null || true)"
- if [[ -z "$TEMPLATE_PATH" ]]; then
- TEMPLATE_BASE=$(awk -v s="$TEMPLATE_STORAGE" '$1==s {f=1} f && /path/ {print $2; exit}' /etc/pve/storage.cfg)
- [[ -n "$TEMPLATE_BASE" ]] && TEMPLATE_PATH="$TEMPLATE_BASE/template/cache/$TEMPLATE"
- fi
-
- # If we still don't have a path but have a valid template name, construct it
- if [[ -z "$TEMPLATE_PATH" && -n "$TEMPLATE" ]]; then
- TEMPLATE_PATH="/var/lib/vz/template/cache/$TEMPLATE"
- fi
-
- [[ -n "$TEMPLATE_PATH" ]] || {
- msg_error "Template still not found after version change"
- exit 220
- }
else
msg_custom "đĢ" "${YW}" "Installation cancelled"
exit 0
fi
else
- msg_error "No ${PCT_OSTYPE} templates available"
- exit 220
+ msg_error "No ${PCT_OSTYPE} templates available at all"
+ exit 225
fi
fi
- }
- # Validate that we found a template
- if [[ -z "$TEMPLATE" ]]; then
- msg_error "No template found for ${PCT_OSTYPE} ${PCT_OSVERSION}"
- msg_custom "âšī¸" "${YW}" "Please check:"
- msg_custom " âĸ" "${YW}" "Is pveam catalog available? (run: pveam available -section system)"
- msg_custom " âĸ" "${YW}" "Does the template exist for your OS version?"
- exit 225
- fi
-
- msg_ok "Template ${BL}$TEMPLATE${CL} [$TEMPLATE_SOURCE]"
- msg_debug "Resolved TEMPLATE_PATH=$TEMPLATE_PATH"
-
- NEED_DOWNLOAD=0
- if [[ ! -f "$TEMPLATE_PATH" ]]; then
- msg_info "Template not present locally â will download."
- NEED_DOWNLOAD=1
- elif [[ ! -r "$TEMPLATE_PATH" ]]; then
- msg_error "Template file exists but is not readable â check permissions."
- exit 221
- elif [[ "$(stat -c%s "$TEMPLATE_PATH")" -lt 1000000 ]]; then
- if [[ -n "$ONLINE_TEMPLATE" ]]; then
- msg_warn "Template file too small (<1MB) â re-downloading."
- NEED_DOWNLOAD=1
- else
- msg_warn "Template looks too small, but no online version exists. Keeping local file."
+ TEMPLATE_PATH="$(pvesm path $TEMPLATE_STORAGE:vztmpl/$TEMPLATE 2>/dev/null || true)"
+ if [[ -z "$TEMPLATE_PATH" ]]; then
+ TEMPLATE_BASE=$(awk -v s="$TEMPLATE_STORAGE" '$1==s {f=1} f && /path/ {print $2; exit}' /etc/pve/storage.cfg)
+ [[ -n "$TEMPLATE_BASE" ]] && TEMPLATE_PATH="$TEMPLATE_BASE/template/cache/$TEMPLATE"
fi
- elif ! tar -tf "$TEMPLATE_PATH" &>/dev/null; then
- if [[ -n "$ONLINE_TEMPLATE" ]]; then
- msg_warn "Template appears corrupted â re-downloading."
- NEED_DOWNLOAD=1
- else
- msg_warn "Template appears corrupted, but no online version exists. Keeping local file."
- fi
- else
- $STD msg_ok "Template $TEMPLATE is present and valid."
- fi
- if [[ "$TEMPLATE_SOURCE" == "local" && -n "$ONLINE_TEMPLATE" && "$TEMPLATE" != "$ONLINE_TEMPLATE" ]]; then
- msg_warn "Local template is outdated: $TEMPLATE (latest available: $ONLINE_TEMPLATE)"
- if whiptail --yesno "A newer template is available:\n$ONLINE_TEMPLATE\n\nDo you want to download and use it instead?" 12 70; then
- TEMPLATE="$ONLINE_TEMPLATE"
- NEED_DOWNLOAD=1
- else
- msg_custom "âšī¸" "${BL}" "Continuing with local template $TEMPLATE"
+ # If we still don't have a path but have a valid template name, construct it
+ if [[ -z "$TEMPLATE_PATH" && -n "$TEMPLATE" ]]; then
+ TEMPLATE_PATH="/var/lib/vz/template/cache/$TEMPLATE"
fi
- fi
- if [[ "$NEED_DOWNLOAD" -eq 1 ]]; then
- [[ -f "$TEMPLATE_PATH" ]] && rm -f "$TEMPLATE_PATH"
- for attempt in {1..3}; do
- msg_info "Attempt $attempt: Downloading template $TEMPLATE to $TEMPLATE_STORAGE"
- if pveam download "$TEMPLATE_STORAGE" "$TEMPLATE" >>"${BUILD_LOG:-/dev/null}" 2>&1; then
- msg_ok "Template download successful."
- break
+ [[ -n "$TEMPLATE_PATH" ]] || {
+ if [[ -z "$TEMPLATE" ]]; then
+ msg_error "Template ${PCT_OSTYPE} ${PCT_OSVERSION} not available"
+
+ # Get available versions
+ mapfile -t AVAILABLE_VERSIONS < <(
+ pveam available -section system 2>/dev/null |
+ grep "^${PCT_OSTYPE}-" |
+ sed -E 's/.*'"${PCT_OSTYPE}"'-([0-9]+\.[0-9]+).*/\1/' |
+ grep -E '^[0-9]+\.[0-9]+$' |
+ sort -u -V 2>/dev/null || sort -u
+ )
+
+ if [[ ${#AVAILABLE_VERSIONS[@]} -gt 0 ]]; then
+ echo -e "\n${BL}Available versions:${CL}"
+ for i in "${!AVAILABLE_VERSIONS[@]}"; do
+ echo " [$((i + 1))] ${AVAILABLE_VERSIONS[$i]}"
+ done
+
+ echo ""
+ read -p "Select version [1-${#AVAILABLE_VERSIONS[@]}] or Enter to exit: " choice /dev/null |
+ awk -v search="${TEMPLATE_SEARCH}-" -v pattern="${TEMPLATE_PATTERN}" '$1 ~ search && $1 ~ pattern {print $1}' |
+ sed 's|.*/||' | sort -t - -k 2 -V
+ )
+ mapfile -t ONLINE_TEMPLATES < <(
+ pveam available -section system 2>/dev/null |
+ grep -E '\.(tar\.zst|tar\.xz|tar\.gz)$' |
+ awk '{print $2}' |
+ grep -E "^${TEMPLATE_SEARCH}-.*${TEMPLATE_PATTERN}" |
+ sort -t - -k 2 -V 2>/dev/null || true
+ )
+ ONLINE_TEMPLATE=""
+ [[ ${#ONLINE_TEMPLATES[@]} -gt 0 ]] && ONLINE_TEMPLATE="${ONLINE_TEMPLATES[-1]}"
+
+ if [[ ${#LOCAL_TEMPLATES[@]} -gt 0 ]]; then
+ TEMPLATE="${LOCAL_TEMPLATES[-1]}"
+ TEMPLATE_SOURCE="local"
+ else
+ TEMPLATE="$ONLINE_TEMPLATE"
+ TEMPLATE_SOURCE="online"
+ fi
+
+ TEMPLATE_PATH="$(pvesm path $TEMPLATE_STORAGE:vztmpl/$TEMPLATE 2>/dev/null || true)"
+ if [[ -z "$TEMPLATE_PATH" ]]; then
+ TEMPLATE_BASE=$(awk -v s="$TEMPLATE_STORAGE" '$1==s {f=1} f && /path/ {print $2; exit}' /etc/pve/storage.cfg)
+ [[ -n "$TEMPLATE_BASE" ]] && TEMPLATE_PATH="$TEMPLATE_BASE/template/cache/$TEMPLATE"
+ fi
+
+ # If we still don't have a path but have a valid template name, construct it
+ if [[ -z "$TEMPLATE_PATH" && -n "$TEMPLATE" ]]; then
+ TEMPLATE_PATH="/var/lib/vz/template/cache/$TEMPLATE"
+ fi
+
+ [[ -n "$TEMPLATE_PATH" ]] || {
+ msg_error "Template still not found after version change"
+ exit 220
+ }
+ else
+ msg_custom "đĢ" "${YW}" "Installation cancelled"
+ exit 0
+ fi
+ else
+ msg_error "No ${PCT_OSTYPE} templates available"
+ exit 220
+ fi
fi
- if [[ $attempt -eq 3 ]]; then
- msg_error "Failed after 3 attempts. Please check network access, permissions, or manually run:\n pveam download $TEMPLATE_STORAGE $TEMPLATE"
- exit 222
- fi
- sleep $((attempt * 5))
- done
- fi
+ }
- if ! pveam list "$TEMPLATE_STORAGE" 2>/dev/null | grep -q "$TEMPLATE"; then
- msg_error "Template $TEMPLATE not available in storage $TEMPLATE_STORAGE after download."
- exit 223
+ # Validate that we found a template
+ if [[ -z "$TEMPLATE" ]]; then
+ msg_error "No template found for ${PCT_OSTYPE} ${PCT_OSVERSION}"
+ msg_custom "âšī¸" "${YW}" "Please check:"
+ msg_custom " âĸ" "${YW}" "Is pveam catalog available? (run: pveam available -section system)"
+ msg_custom " âĸ" "${YW}" "Does the template exist for your OS version?"
+ exit 225
+ fi
+
+ msg_ok "Template ${BL}$TEMPLATE${CL} [$TEMPLATE_SOURCE]"
+ msg_debug "Resolved TEMPLATE_PATH=$TEMPLATE_PATH"
+
+ NEED_DOWNLOAD=0
+ if [[ ! -f "$TEMPLATE_PATH" ]]; then
+ msg_info "Template not present locally â will download."
+ NEED_DOWNLOAD=1
+ elif [[ ! -r "$TEMPLATE_PATH" ]]; then
+ msg_error "Template file exists but is not readable â check permissions."
+ exit 221
+ elif [[ "$(stat -c%s "$TEMPLATE_PATH")" -lt 1000000 ]]; then
+ if [[ -n "$ONLINE_TEMPLATE" ]]; then
+ msg_warn "Template file too small (<1MB) â re-downloading."
+ NEED_DOWNLOAD=1
+ else
+ msg_warn "Template looks too small, but no online version exists. Keeping local file."
+ fi
+ elif ! tar -tf "$TEMPLATE_PATH" &>/dev/null; then
+ if [[ -n "$ONLINE_TEMPLATE" ]]; then
+ msg_warn "Template appears corrupted â re-downloading."
+ NEED_DOWNLOAD=1
+ else
+ msg_warn "Template appears corrupted, but no online version exists. Keeping local file."
+ fi
+ else
+ $STD msg_ok "Template $TEMPLATE is present and valid."
+ fi
+
+ if [[ "$TEMPLATE_SOURCE" == "local" && -n "$ONLINE_TEMPLATE" && "$TEMPLATE" != "$ONLINE_TEMPLATE" ]]; then
+ msg_warn "Local template is outdated: $TEMPLATE (latest available: $ONLINE_TEMPLATE)"
+ if whiptail --yesno "A newer template is available:\n$ONLINE_TEMPLATE\n\nDo you want to download and use it instead?" 12 70; then
+ TEMPLATE="$ONLINE_TEMPLATE"
+ NEED_DOWNLOAD=1
+ else
+ msg_custom "âšī¸" "${BL}" "Continuing with local template $TEMPLATE"
+ fi
+ fi
+
+ if [[ "$NEED_DOWNLOAD" -eq 1 ]]; then
+ [[ -f "$TEMPLATE_PATH" ]] && rm -f "$TEMPLATE_PATH"
+ for attempt in {1..3}; do
+ msg_info "Attempt $attempt: Downloading template $TEMPLATE to $TEMPLATE_STORAGE"
+ if pveam download "$TEMPLATE_STORAGE" "$TEMPLATE" >>"${BUILD_LOG:-/dev/null}" 2>&1; then
+ msg_ok "Template download successful."
+ break
+ fi
+ if [[ $attempt -eq 3 ]]; then
+ msg_error "Failed after 3 attempts. Please check network access, permissions, or manually run:\n pveam download $TEMPLATE_STORAGE $TEMPLATE"
+ exit 222
+ fi
+ sleep $((attempt * 5))
+ done
+ fi
+
+ if ! pveam list "$TEMPLATE_STORAGE" 2>/dev/null | grep -q "$TEMPLATE"; then
+ msg_error "Template $TEMPLATE not available in storage $TEMPLATE_STORAGE after download."
+ exit 223
+ fi
fi
# ------------------------------------------------------------------------------
@@ -5464,19 +5581,13 @@ create_lxc_container() {
if [[ ! -s "$TEMPLATE_PATH" || "$(stat -c%s "$TEMPLATE_PATH" 2>/dev/null || echo 0)" -lt 1000000 ]]; then
msg_info "Template file missing or too small â downloading"
rm -f "$TEMPLATE_PATH"
- pveam download "$TEMPLATE_STORAGE" "$TEMPLATE" >>"${BUILD_LOG:-/dev/null}" 2>&1 || {
- msg_error "Failed to download template '$TEMPLATE' to storage '$TEMPLATE_STORAGE'"
- exit 222
- }
+ download_template
msg_ok "Template downloaded"
elif ! tar -tf "$TEMPLATE_PATH" &>/dev/null; then
- if [[ -n "$ONLINE_TEMPLATE" ]]; then
+ if [[ "$ARCH" == "arm64" || -n "$ONLINE_TEMPLATE" ]]; then
msg_info "Template appears corrupted â re-downloading"
rm -f "$TEMPLATE_PATH"
- pveam download "$TEMPLATE_STORAGE" "$TEMPLATE" >>"${BUILD_LOG:-/dev/null}" 2>&1 || {
- msg_error "Failed to re-download template '$TEMPLATE'"
- exit 222
- }
+ download_template
msg_ok "Template re-downloaded"
else
msg_warn "Template appears corrupted, but no online version exists. Skipping re-download."
@@ -5497,7 +5608,7 @@ create_lxc_container() {
if grep -qiE 'unable to open|corrupt|invalid' "$LOGFILE"; then
msg_info "Template may be corrupted â re-downloading"
rm -f "$TEMPLATE_PATH"
- pveam download "$TEMPLATE_STORAGE" "$TEMPLATE" >>"${BUILD_LOG:-/dev/null}" 2>&1
+ download_template
msg_ok "Template re-downloaded"
fi
@@ -5510,7 +5621,11 @@ create_lxc_container() {
if [[ ! -f "$LOCAL_TEMPLATE_PATH" ]]; then
msg_ok "Trying local storage fallback"
msg_info "Downloading template to local"
- pveam download local "$TEMPLATE" >>"${BUILD_LOG:-/dev/null}" 2>&1
+ if [[ "$ARCH" == "arm64" ]]; then
+ download_arm64_template "$LOCAL_TEMPLATE_PATH"
+ else
+ pveam download local "$TEMPLATE" >>"${BUILD_LOG:-/dev/null}" 2>&1
+ fi
msg_ok "Template downloaded to local"
else
msg_ok "Trying local storage fallback"
@@ -5646,15 +5761,15 @@ description() {
- GitHub
+ GitHub
- Discussions
+ Discussions
- Issues
+ Issues
EOF
diff --git a/misc/core.func b/misc/core.func
index e3b9d2cff..980dfe111 100644
--- a/misc/core.func
+++ b/misc/core.func
@@ -344,9 +344,10 @@ pve_check() {
# - Provides link to ARM64-compatible scripts
# ------------------------------------------------------------------------------
arch_check() {
- if [ "$(dpkg --print-architecture)" != "amd64" ]; then
- msg_error "This script will not work with PiMox (ARM architecture detected)."
- msg_warn "Visit https://github.com/asylumexp/Proxmox for ARM64 support."
+ local arch
+ arch="$(dpkg --print-architecture)"
+ if [[ "$arch" != "amd64" && "$arch" != "arm64" ]]; then
+ msg_error "This script requires amd64 or arm64 (detected: $arch)."
sleep 2
exit 106
fi
diff --git a/misc/install.func b/misc/install.func
index 94f005b26..4e39b69da 100644
--- a/misc/install.func
+++ b/misc/install.func
@@ -235,6 +235,7 @@ EOF
fi
apt_update_safe
$STD apt-get -o Dpkg::Options::="--force-confold" -y dist-upgrade
+ $STD apt-get install -y sudo curl mc gnupg2 openssh-server wget gcc
rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED
msg_ok "Updated Container OS"
post_progress_to_api
diff --git a/misc/tools.func b/misc/tools.func
index cce5f303b..c4de1036c 100644
--- a/misc/tools.func
+++ b/misc/tools.func
@@ -3267,7 +3267,7 @@ function fetch_and_deploy_gh_release() {
fi
if [[ -z "$url_match" ]]; then
for u in $assets; do
- if [[ "$u" =~ ($arch|amd64|x86_64|aarch64|arm64).*\.deb$ ]]; then
+ if [[ "$u" =~ ($arch|aarch64|arm64).*\.deb$ ]]; then
url_match="$u"
break
fi