diff --git a/vm/unifi-os-vm.sh b/vm/unifi-os-vm.sh index b43c6d53..61a79fbe 100644 --- a/vm/unifi-os-vm.sh +++ b/vm/unifi-os-vm.sh @@ -2,11 +2,9 @@ # Copyright (c) 2021-2025 community-scripts ORG # Author: MickLesk (CanbiZ) -# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE +# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE -source /dev/stdin <<<$(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/api.func) -source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/vm-core.func) -load_functions +source /dev/stdin <<<$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) function header_info { clear @@ -31,6 +29,39 @@ UOS_VERSION="4.2.23" UOS_URL="https://fw-download.ubnt.com/data/unifi-os-server/8b93-linux-x64-4.2.23-158fa00b-6b2c-4cd8-94ea-e92bc4a81369.23-x64" UOS_INSTALLER="unifi-os-server-${UOS_VERSION}.bin" +YW=$(echo "\033[33m") +BL=$(echo "\033[36m") +RD=$(echo "\033[01;31m") +BGN=$(echo "\033[4;92m") +GN=$(echo "\033[1;92m") +DGN=$(echo "\033[32m") +CL=$(echo "\033[m") + +CL=$(echo "\033[m") +BOLD=$(echo "\033[1m") +BFR="\\r\\033[K" +HOLD=" " +TAB=" " + +CM="${TAB}✔️${TAB}${CL}" +CROSS="${TAB}✖️${TAB}${CL}" +INFO="${TAB}💡${TAB}${CL}" +OS="${TAB}🖥️${TAB}${CL}" +CONTAINERTYPE="${TAB}📦${TAB}${CL}" +DISKSIZE="${TAB}💾${TAB}${CL}" +CPUCORE="${TAB}🧠${TAB}${CL}" +RAMSIZE="${TAB}🛠️${TAB}${CL}" +CONTAINERID="${TAB}🆔${TAB}${CL}" +HOSTNAME="${TAB}🏠${TAB}${CL}" +BRIDGE="${TAB}🌉${TAB}${CL}" +GATEWAY="${TAB}🌐${TAB}${CL}" +DEFAULT="${TAB}⚙️${TAB}${CL}" +MACADDRESS="${TAB}🔗${TAB}${CL}" +VLANTAG="${TAB}🏷️${TAB}${CL}" +CREATING="${TAB}🚀${TAB}${CL}" +ADVANCED="${TAB}🧩${TAB}${CL}" +CLOUD="${TAB}☁️${TAB}${CL}" + THIN="discard=on,ssd=1," set -e trap 'error_handler $LINENO "$BASH_COMMAND"' ERR @@ -47,28 +78,136 @@ function error_handler() { cleanup_vmid } -get_valid_nextid -cleanup_vmid -cleanup -post_update_to_api "done" "none" -[[ -n "${TEMP_DIR:-}" && -d "$TEMP_DIR" ]] && rm -rf "$TEMP_DIR" -check_root -arch_check -ssh_check +function get_valid_nextid() { + local try_id + try_id=$(pvesh get /cluster/nextid) + while true; do + if [ -f "/etc/pve/qemu-server/${try_id}.conf" ] || [ -f "/etc/pve/lxc/${try_id}.conf" ]; then + try_id=$((try_id + 1)) + continue + fi + if lvs --noheadings -o lv_name | grep -qE "(^|[-_])${try_id}($|[-_])"; then + try_id=$((try_id + 1)) + continue + fi + break + done + echo "$try_id" +} + +function cleanup_vmid() { + if qm status $VMID &>/dev/null; then + qm stop $VMID &>/dev/null + qm destroy $VMID &>/dev/null + fi +} + +function cleanup() { + popd >/dev/null + post_update_to_api "done" "none" + rm -rf $TEMP_DIR +} TEMP_DIR=$(mktemp -d) pushd $TEMP_DIR >/dev/null if whiptail --backtitle "Proxmox VE Helper Scripts" --title "Debian 12 VM" --yesno "This will create a New Debian 12 VM. Proceed?" 10 58; then : else - header_info && exit_script + header_info && echo -e "${CROSS}${RD}User exited script${CL}\n" && exit fi +function msg_info() { + local msg="$1" + echo -ne "${TAB}${YW}${HOLD}${msg}${HOLD}" +} + +function msg_ok() { + local msg="$1" + echo -e "${BFR}${CM}${GN}${msg}${CL}" +} + +function msg_error() { + local msg="$1" + echo -e "${BFR}${CROSS}${RD}${msg}${CL}" +} + +function check_root() { + if [[ "$(id -u)" -ne 0 || $(ps -o comm= -p $PPID) == "sudo" ]]; then + clear + msg_error "Please run this script as root." + echo -e "\nExiting..." + sleep 2 + exit + fi +} + +pve_check() { + local PVE_VER + PVE_VER="$(pveversion | awk -F'/' '{print $2}' | awk -F'-' '{print $1}')" + + # Check for Proxmox VE 8.x + if [[ "$PVE_VER" =~ ^8\.([0-9]+) ]]; then + local MINOR="${BASH_REMATCH[1]}" + if ((MINOR < 1 || MINOR > 4)); then + msg_error "This version of Proxmox VE is not supported." + echo -e "Required: Proxmox VE version 8.1 – 8.4" + exit 1 + fi + return 0 + fi + + # Check for Proxmox VE 9.x (Beta) — require confirmation + if [[ "$PVE_VER" =~ ^9\.([0-9]+) ]]; then + if whiptail --title "Proxmox 9.x Detected (Beta)" \ + --yesno "You are using Proxmox VE $PVE_VER, which is currently in Beta state.\n\nThis version is experimentally supported.\n\nDo you want to proceed anyway?" 12 70; then + msg_ok "Confirmed: Continuing with Proxmox VE $PVE_VER" + return 0 + else + msg_error "Aborted by user: Proxmox VE 9.x was not confirmed." + exit 1 + fi + fi + + # All other unsupported versions + msg_error "This version of Proxmox VE is not supported." + echo -e "Supported versions: Proxmox VE 8.1 – 8.4 or 9.x (Beta, with confirmation)" + exit 1 +} + +function arch_check() { + if [ "$(dpkg --print-architecture)" != "amd64" ]; then + echo -e "\n ${INFO}${YWB}This script will not work with PiMox! \n" + echo -e "\n ${YWB}Visit https://github.com/asylumexp/Proxmox for ARM64 support. \n" + echo -e "Exiting..." + sleep 2 + exit + fi +} + +function ssh_check() { + if command -v pveversion >/dev/null 2>&1; then + if [ -n "${SSH_CLIENT:+x}" ]; then + if whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "SSH DETECTED" --yesno "It's suggested to use the Proxmox shell instead of SSH, since SSH can create issues while gathering variables. Would you like to proceed with using SSH?" 10 62; then + echo "you've been warned" + else + clear + exit + fi + fi + fi +} + +function exit-script() { + clear + echo -e "\n${CROSS}${RD}User exited script${CL}\n" + exit +} + function default_settings() { VMID=$(get_valid_nextid) FORMAT=",efitype=4m" MACHINE="" - DISK_SIZE="32G" + DISK_SIZE="8G" DISK_CACHE="" HN="debian" CPU_TYPE="" @@ -79,6 +218,7 @@ function default_settings() { VLAN="" MTU="" START_VM="yes" + CLOUD_INIT="no" METHOD="default" echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}${VMID}${CL}" echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}i440fx${CL}" @@ -92,6 +232,7 @@ function default_settings() { echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}${MAC}${CL}" echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}Default${CL}" echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}Default${CL}" + echo -e "${CLOUD}${BOLD}${DGN}Configure Cloud-init: ${BGN}no${CL}" echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}" echo -e "${CREATING}${BOLD}${DGN}Creating a Debian 12 VM using the above default settings${CL}" } @@ -112,7 +253,7 @@ function advanced_settings() { echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}$VMID${CL}" break else - exit_script + exit-script fi done @@ -130,7 +271,7 @@ function advanced_settings() { MACHINE="" fi else - exit_script + exit-script fi if DISK_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Disk Size in GiB (e.g., 10, 20)" 8 58 "$DISK_SIZE" --title "DISK SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then @@ -142,10 +283,10 @@ function advanced_settings() { echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}" else echo -e "${DISKSIZE}${BOLD}${RD}Invalid Disk Size. Please use a number (e.g., 10 or 10G).${CL}" - exit_script + exit-script fi else - exit_script + exit-script fi if DISK_CACHE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISK CACHE" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \ @@ -160,7 +301,7 @@ function advanced_settings() { DISK_CACHE="" fi else - exit_script + exit-script fi if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 debian --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then @@ -172,7 +313,7 @@ function advanced_settings() { echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}" fi else - exit_script + exit-script fi if CPU_TYPE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU MODEL" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \ @@ -187,7 +328,7 @@ function advanced_settings() { CPU_TYPE="" fi else - exit_script + exit-script fi if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 2 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then @@ -198,7 +339,7 @@ function advanced_settings() { echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}" fi else - exit_script + exit-script fi if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 2048 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then @@ -209,7 +350,7 @@ function advanced_settings() { echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}" fi else - exit_script + exit-script fi if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Bridge" 8 58 vmbr0 --title "BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then @@ -220,7 +361,7 @@ function advanced_settings() { echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}" fi else - exit_script + exit-script fi if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a MAC Address" 8 58 $GEN_MAC --title "MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then @@ -232,7 +373,7 @@ function advanced_settings() { echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC1${CL}" fi else - exit_script + exit-script fi if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Vlan(leave blank for default)" 8 58 --title "VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then @@ -245,7 +386,7 @@ function advanced_settings() { echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}" fi else - exit_script + exit-script fi if MTU1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default)" 8 58 --title "MTU SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then @@ -258,7 +399,15 @@ function advanced_settings() { echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}" fi else - exit_script + exit-script + fi + + if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "CLOUD-INIT" --yesno "Configure the VM with Cloud-init?" --defaultno 10 58); then + echo -e "${CLOUD}${BOLD}${DGN}Configure Cloud-init: ${BGN}yes${CL}" + CLOUD_INIT="yes" + else + echo -e "${CLOUD}${BOLD}${DGN}Configure Cloud-init: ${BGN}no${CL}" + CLOUD_INIT="no" fi if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then @@ -290,7 +439,12 @@ function start_script() { fi } +check_root +arch_check +pve_check +ssh_check start_script + post_to_api_vm msg_info "Validating Storage" @@ -314,18 +468,22 @@ elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then else while [ -z "${STORAGE:+x}" ]; do STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \ - "Which storage pool you would like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \ + "Which storage pool would you like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \ 16 $(($MSG_MAX_LENGTH + 23)) 6 \ - "${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3) || exit + "${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3) done fi msg_ok "Using ${CL}${BL}$STORAGE${CL} ${GN}for Storage Location." msg_ok "Virtual Machine ID is ${CL}${BL}$VMID${CL}." msg_info "Retrieving the URL for the Debian 12 Qcow2 Disk Image" -URL=https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-nocloud-amd64.qcow2 +if [ "$CLOUD_INIT" == "yes" ]; then + URL=https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-genericcloud-amd64.qcow2 +else + URL=https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-nocloud-amd64.qcow2 +fi sleep 2 msg_ok "${CL}${BL}${URL}${CL}" -curl -f#SL "$URL" -O +curl -f#SL -o "$(basename "$URL")" "$URL" echo -en "\e[1A\e[0K" FILE=$(basename $URL) msg_ok "Downloaded ${CL}${BL}${FILE}${CL}"