2023-09-23 07:39:53 -04:00
#!/usr/bin/env bash
2026-08-04 21:02:03 +02:00
2026-01-06 13:28:12 +01:00
# Copyright (c) 2021-2026 tteck
2023-09-23 07:39:53 -04:00
# Author: tteck (tteckster)
2026-08-04 21:02:03 +02:00
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
2023-09-23 07:39:53 -04:00
2026-08-04 21:02:03 +02:00
APP = "all-templates"
APP_TYPE = "addon"
2026-02-17 16:36:20 +01:00
2026-08-04 21:02:03 +02:00
if ! command -v curl & >/dev/null; then
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >& 2
if [[ -f /etc/alpine-release ]] ; then
apk update >/dev/null 2>& 1
apk add --no-cache curl >/dev/null 2>& 1
else
apt-get update >/dev/null 2>& 1
apt-get install -y curl >/dev/null 2>& 1
fi
fi
2026-10-01 08:15:12 +02:00
source <( curl -fsSL " ${ COMMUNITY_SCRIPTS_CORE_URL :- https ://raw.githubusercontent.com/community-scripts/core/main } /core/core.func" )
source <( curl -fsSL " ${ COMMUNITY_SCRIPTS_CORE_URL :- https ://raw.githubusercontent.com/community-scripts/core/main } /lib/tools.func" )
source <( curl -fsSL " ${ COMMUNITY_SCRIPTS_CORE_URL :- https ://raw.githubusercontent.com/community-scripts/core/main } /core/error_handler.func" )
source <( curl -fsSL " ${ COMMUNITY_SCRIPTS_CORE_URL :- https ://raw.githubusercontent.com/community-scripts/core/main } /api/api.func" ) 2>/dev/null || true
2026-02-18 10:24:06 +01:00
declare -f init_tool_telemetry & >/dev/null && init_tool_telemetry "all-templates" "addon"
2026-02-17 16:36:20 +01:00
2026-08-04 21:02:03 +02:00
# Enable error handling; destroy any partially-created container before reporting the error
set -Eeuo pipefail
function _cleanup_on_error() {
local ec = $? cmd = " $BASH_COMMAND "
[[ -n " ${ CTID :- } " ]] && cleanup_ctid
error_handler " $ec " " $cmd "
}
trap '_cleanup_on_error' ERR
# Initialize all core functions (colors, formatting, icons, STD mode)
load_functions
2026-01-12 14:04:28 +01:00
function validate_container_id() {
local ctid = " $1 "
# Check if ID is numeric
if ! [[ " $ctid " = ~ ^[ 0-9] +$ ]] ; then
return 1
fi
# Check if config file exists for VM or LXC
if [[ -f "/etc/pve/qemu-server/ ${ ctid } .conf" ]] || [[ -f "/etc/pve/lxc/ ${ ctid } .conf" ]] ; then
return 1
fi
# Check if ID is used in LVM logical volumes
if lvs --noheadings -o lv_name 2>/dev/null | grep -qE "(^|[-_]) ${ ctid } ( $|[-_])" ; then
return 1
fi
return 0
}
function get_valid_container_id() {
local suggested_id = " ${ 1 :-$( pvesh get /cluster/nextid) } "
while ! validate_container_id " $suggested_id " ; do
suggested_id = $(( suggested_id + 1 ))
done
echo " $suggested_id "
}
2023-09-23 07:39:53 -04:00
function cleanup_ctid() {
if pct status $CTID & >/dev/null; then
if [ " $( pct status $CTID | awk '{print $2}' ) " == "running" ] ; then
pct stop $CTID
fi
pct destroy $CTID
fi
}
2026-08-04 21:02:03 +02:00
header_info
require_pve_host
2023-09-23 07:39:53 -04:00
# Stop Proxmox VE Monitor-All if running
if systemctl is-active -q ping-instances.service; then
systemctl stop ping-instances.service
fi
2026-09-29 15:17:27 +02:00
msg_info "Updating template list"
2023-09-23 07:39:53 -04:00
pveam update >/dev/null 2>& 1
2026-09-29 15:17:27 +02:00
msg_ok "Updated template list"
2025-04-15 15:20:46 +02:00
whiptail --backtitle "Proxmox VE Helper Scripts" --title "All Templates" --yesno "This will allow for the creation of one of the many Template LXC Containers. Proceed?" 10 68
2023-10-06 23:38:34 -04:00
TEMPLATE_MENU =()
2023-09-23 07:39:53 -04:00
MSG_MAX_LENGTH = 0
2026-09-29 15:17:27 +02:00
HOST_ARCH = $( dpkg --print-architecture)
while read -r TAG ITEM ARCH; do
[[ -n " $ARCH " && " $ARCH " != "unknown" && " $ARCH " != " $HOST_ARCH " ]] && continue
2023-09-23 07:39:53 -04:00
OFFSET = 2
(( ${# ITEM } + OFFSET > MSG_MAX_LENGTH)) && MSG_MAX_LENGTH = ${# ITEM } +OFFSET
2023-10-06 23:38:34 -04:00
TEMPLATE_MENU +=( " $ITEM " " $TAG " "OFF" )
2023-09-23 07:39:53 -04:00
done < <( pveam available)
2025-04-15 15:20:46 +02:00
TEMPLATE = $( whiptail --backtitle "Proxmox VE Helper Scripts" --title "All Template LXCs" --radiolist "\nSelect a Template LXC to create:\n" 16 $(( MSG_MAX_LENGTH + 58 )) 10 " ${ TEMPLATE_MENU [@] } " 3>& 1 1>& 2 2>& 3 | tr -d '"' )
2023-09-23 07:39:53 -04:00
[ -z " $TEMPLATE " ] && {
whiptail --backtitle "Proxmox VE Helper Scripts" --title "No Template LXC Selected" --msgbox "It appears that no Template LXC container was selected" 10 68
2026-08-04 21:02:03 +02:00
echo "Done"
exit 0
2023-09-23 07:39:53 -04:00
}
# Setup script environment
NAME = $( echo " $TEMPLATE " | grep -oE '^[^-]+-[^-]+' )
2026-10-03 08:19:10 +02:00
PASS = " $( random_password 16) "
2026-01-12 14:04:28 +01:00
# Get valid Container ID
2023-09-23 07:39:53 -04:00
CTID = $( pvesh get /cluster/nextid)
2026-01-12 14:04:28 +01:00
if ! validate_container_id " $CTID " ; then
2026-08-04 21:02:03 +02:00
msg_warn "Container ID $CTID is already in use."
2026-01-12 14:04:28 +01:00
CTID = $( get_valid_container_id " $CTID " )
2026-09-29 15:17:27 +02:00
msg_ok "Using next available ID: $CTID "
2026-01-12 14:04:28 +01:00
fi
2023-09-23 07:39:53 -04:00
PCT_OPTIONS = "
-features keyctl=1,nesting=1
-hostname $NAME
2026-03-24 20:50:40 +01:00
-tags community-script
2023-09-23 07:39:53 -04:00
-onboot 0
-cores 2
-memory 2048
-password $PASS
2023-09-23 08:00:12 -04:00
-net0 name=eth0,bridge=vmbr0,ip=dhcp
2023-09-23 07:39:53 -04:00
-unprivileged 1
"
DEFAULT_PCT_OPTIONS =(
-arch $( dpkg --print-architecture)
)
# Set the CONTENT and CONTENT_LABEL variables
function select_storage() {
local CLASS = $1
local CONTENT
local CONTENT_LABEL
case $CLASS in
container)
CONTENT = 'rootdir'
CONTENT_LABEL = 'Container'
;;
template)
CONTENT = 'vztmpl'
CONTENT_LABEL = 'Container template'
;;
2026-08-04 21:02:03 +02:00
*)
msg_error "Invalid storage class."
exit 112
;;
2023-09-23 07:39:53 -04:00
esac
# Query all storage locations
local -a MENU
while read -r line; do
local TAG = $( echo $line | awk '{print $1}' )
local TYPE = $( echo $line | awk '{printf "%-10s", $2}' )
local FREE = $( echo $line | numfmt --field 4-6 --from-unit= K --to= iec --format %.2f | awk '{printf( "%9sB", $6)}' )
local ITEM = " Type: $TYPE Free: $FREE "
local OFFSET = 2
if [[ $(( ${# ITEM } + $OFFSET )) -gt ${ MSG_MAX_LENGTH :- } ]] ; then
local MSG_MAX_LENGTH = $(( ${# ITEM } + $OFFSET ))
fi
MENU +=( " $TAG " " $ITEM " "OFF" )
done < <( pvesm status -content $CONTENT | awk 'NR>1' )
# Select storage location
if [ $(( ${# MENU [@] } / 3 )) -eq 0 ] ; then
2026-08-04 21:02:03 +02:00
msg_warn "' $CONTENT_LABEL ' needs to be selected for at least one storage location."
msg_error "Unable to detect valid storage location."
if [[ " $CONTENT " == "rootdir" ]] ; then exit 119; else exit 120; fi
2023-09-23 07:39:53 -04:00
elif [ $(( ${# MENU [@] } / 3 )) -eq 1 ] ; then
printf ${ MENU [0] }
else
local STORAGE
while [ -z " ${ STORAGE :+x } " ] ; do
STORAGE = $( whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
2025-04-17 02:49:55 -04:00
"Which storage pool would you like to use for the ${ CONTENT_LABEL ,, } ?\n\n" \
2023-09-23 07:39:53 -04:00
16 $(( $MSG_MAX_LENGTH + 23 )) 6 \
2026-08-04 21:02:03 +02:00
" ${ MENU [@] } " 3>& 1 1>& 2 2>& 3) || {
msg_error "Menu aborted."
exit 254
}
2023-09-23 07:39:53 -04:00
done
printf $STORAGE
fi
}
2026-08-04 21:02:03 +02:00
2023-09-23 07:39:53 -04:00
# Get template storage
2025-04-15 15:20:46 +02:00
TEMPLATE_STORAGE = $( select_storage template)
2026-09-29 15:17:27 +02:00
msg_ok "Using ' $TEMPLATE_STORAGE ' for template storage."
2023-09-23 07:39:53 -04:00
# Get container storage
2025-04-15 15:20:46 +02:00
CONTAINER_STORAGE = $( select_storage container)
2026-09-29 15:17:27 +02:00
msg_ok "Using ' $CONTAINER_STORAGE ' for container storage."
2023-09-23 07:39:53 -04:00
# Download template
2026-08-04 21:02:03 +02:00
msg_info "Downloading LXC template (Patience)"
2026-09-29 15:17:27 +02:00
pveam download " $TEMPLATE_STORAGE " " $TEMPLATE " >/dev/null || {
2026-08-04 21:02:03 +02:00
msg_error "A problem occured while downloading the LXC template."
exit 222
}
msg_ok "Downloaded LXC template"
2023-09-23 07:39:53 -04:00
# Create variable for 'pct' options
PCT_OPTIONS =( ${ PCT_OPTIONS [@] :- ${ DEFAULT_PCT_OPTIONS [@] }} )
2026-08-04 21:02:03 +02:00
[[ " ${ PCT_OPTIONS [*] } " = ~ " -rootfs " ]] || PCT_OPTIONS +=( -rootfs $CONTAINER_STORAGE :${ PCT_DISK_SIZE :- 8 } )
2023-09-23 07:39:53 -04:00
# Create LXC
2026-08-04 21:02:03 +02:00
msg_info "Creating LXC container"
pct create $CTID ${ TEMPLATE_STORAGE } :vztmpl/${ TEMPLATE } " ${ PCT_OPTIONS [@] } " >/dev/null || {
msg_error "A problem occured while trying to create container."
exit 209
}
msg_ok "Created LXC container"
2023-09-23 07:39:53 -04:00
# Save password
echo " $NAME password: ${ PASS } " >>~/$NAME .creds # file is located in the Proxmox root directory
# Start container
2026-08-04 21:02:03 +02:00
msg_info "Starting LXC Container"
2023-09-23 07:39:53 -04:00
pct start " $CTID "
sleep 5
2026-08-04 21:02:03 +02:00
msg_ok "Started LXC Container"
2023-09-23 07:39:53 -04:00
# Get container IP
2026-08-04 21:02:03 +02:00
set +Eeuo pipefail
2023-09-23 07:39:53 -04:00
max_attempts = 5
attempt = 1
IP = ""
while [[ $attempt -le $max_attempts ]] ; do
IP = $( pct exec $CTID ip a show dev eth0 | grep -oP 'inet \K[^/]+' )
if [[ -n $IP ]] ; then
break
else
2026-08-04 21:02:03 +02:00
msg_warn "Attempt $attempt : IP address not found. Pausing for 5 seconds..."
2023-09-23 07:39:53 -04:00
sleep 5
(( attempt++))
fi
done
if [[ -z $IP ]] ; then
2026-08-04 21:02:03 +02:00
msg_warn "Maximum number of attempts reached. IP address not found."
2023-09-23 07:39:53 -04:00
IP = "NOT FOUND"
fi
2026-08-04 21:02:03 +02:00
set -Eeuo pipefail
2023-09-23 07:39:53 -04:00
# Start Proxmox VE Monitor-All if available
if [[ -f /etc/systemd/system/ping-instances.service ]] ; then
systemctl start ping-instances.service
fi
# Success message
echo
2026-08-04 21:02:03 +02:00
msg_ok "LXC container ' $CTID ' was successfully created, and its IP address is ${ IP } ."
2023-09-23 07:39:53 -04:00
echo
2026-08-04 21:02:03 +02:00
echo -e " ${ YW } Proceed to the LXC console to complete the setup. ${ CL } "
2023-09-23 07:39:53 -04:00
echo
2026-08-04 21:02:03 +02:00
echo -e " ${ YW } login: root ${ CL } "
echo -e " ${ YW } password: $PASS ${ CL } "
2023-09-23 07:39:53 -04:00
echo