-
-
Save gardart/02fece92b53b2c03dd371bd4215db1f6 to your computer and use it in GitHub Desktop.
A bash script to create many different VM templates across multiple distros for Proxmox VE.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Sources using Openstack images | |
declare -A sources | |
declare -A template_ids | |
declare -A result_ids | |
template_ids["debian"]=9000 | |
template_ids["ubuntu"]=9100 | |
template_ids["almalinux"]=9200 | |
template_ids["fedora"]=9300 | |
template_ids["centos"]=9400 | |
# Debian Versions | |
sources["debian-12"]="http://cdimage.debian.org/cdimage/cloud/bookworm/latest/debian-12-generic-amd64.qcow2" | |
sources["debian-11"]="http://cdimage.debian.org/cdimage/cloud/bullseye/latest/debian-11-generic-amd64.qcow2" | |
sources["debian-10"]="http://cdimage.debian.org/cdimage/openstack/current-10/debian-10-openstack-amd64.qcow2" | |
# Ubuntu Versions | |
# Here we use a kvm image, because they are smaller than the openstack images | |
sources["ubuntu-23.10"]="https://cloud-images.ubuntu.com/mantic/current/mantic-server-cloudimg-amd64-disk-kvm.img" | |
sources["ubuntu-23.04"]="https://cloud-images.ubuntu.com/lunar/current/lunar-server-cloudimg-amd64-disk-kvm.img" | |
sources["ubuntu-22.10"]="https://cloud-images.ubuntu.com/kinetic/current/kinetic-server-cloudimg-amd64-disk-kvm.img" | |
sources["ubuntu-22.04"]="https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64-disk-kvm.img" | |
sources["ubuntu-20.04"]="https://cloud-images.ubuntu.com/focal/current/focal-server-cloudimg-amd64-disk-kvm.img" | |
sources["ubuntu-18.04"]="https://cloud-images.ubuntu.com/bionic/current/bionic-server-cloudimg-amd64.img" | |
sources["ubuntu-16.04"]="https://cloud-images.ubuntu.com/xenial/current/xenial-server-cloudimg-amd64-disk1.img" | |
# AlmaLinux Versions | |
sources["almalinux-9"]="https://repo.almalinux.org/almalinux/9/cloud/x86_64/images/AlmaLinux-9-GenericCloud-latest.x86_64.qcow2" | |
sources["almalinux-8"]="https://repo.almalinux.org/almalinux/8/cloud/x86_64/images/AlmaLinux-8-GenericCloud-latest.x86_64.qcow2" | |
# Fedora Versions | |
sources["fedora-38"]="https://download.fedoraproject.org/pub/fedora/linux/releases/38/Cloud/x86_64/images/Fedora-Cloud-Base-38-1.6.x86_64.qcow2" | |
# CentOS Versions | |
sources["centos-stream-9"]="https://cloud.centos.org/centos/9-stream/x86_64/images/CentOS-Stream-GenericCloud-9-latest.x86_64.qcow2" | |
download_template() { | |
echo "[*] Downloading template $1..." | |
wget -q --show-progress -O "$2" "$1" | |
echo "[*] Download complete." | |
} | |
vm_exists() { | |
qm list | grep -q "$1" | |
} | |
echo " _ _ " | |
echo " | | | | " | |
echo " | |_ ______ ___ _ __ ___ __ _| |_ ___ " | |
echo " | __|______/ __| '__/ _ \\/ _\` | __/ _ \\" | |
echo " | |_ | (__| | | __/ (_| | || __/" | |
echo " \__| \___|_| \___|\__,_|\__\___|" | |
echo "" | |
echo " > Create Proxmox Templates <" | |
echo " by @masterjanic" | |
echo "" | |
# Check if script is run with root permissions | |
if [ "$(id -u)" != "0" ]; then | |
echo "[x] Please run this script with root privileges." | |
exit 1 | |
fi | |
# Check if Proxmox is installed | |
if ! [ -f /etc/pve/pve-root-ca.pem ]; then | |
echo "[x] Proxmox is not installed, please run this script in a Proxmox Environment." | |
exit 1 | |
fi | |
echo "[*] Installing dependencies..." | |
apt -qq install -y libguestfs-tools wget dialog &> /dev/null | |
# Let user enter a storage name | |
read -p "[?] Please enter a the name for the storage to save the template machines to (default=local-lvm): " -r storage | |
storage=${storage:-"local-lvm"} | |
# Let user choose whether to delete templates after creation | |
read -p "[?] Do you want to delete the downloaded images after creation? (y/n, default=y): " -r delete_templates | |
delete_templates=${delete_templates:-y} | |
read -p "[?] Do you want to delete existing templates? (y/n, default=n): " -r delete_previous | |
delete_previous=${delete_previous:-n} | |
read -p "[?] Use CPU type host instead of kvm64 by default? (y/n, default=y): " -r use_cpu_host | |
use_cpu_host=${use_cpu_host:-y} | |
clear | |
# Let user select distros to download | |
cmd=(dialog --separate-output --title "Distro Selection" --checklist "Select distros to create templates for:" 22 76 16) | |
options=( | |
$(for key in "${!sources[@]}"; do | |
echo "$key" | |
echo "$key" | |
echo "on" | |
done) | |
) | |
choices=$("${cmd[@]}" "${options[@]}" 2>&1 >/dev/tty) | |
clear | |
# Check if storage exists in Proxmox | |
if ! (pvesm list "$storage" | grep -q "$storage"); then | |
echo "[x] Storage does not exist in Proxmox or does not have any hosts, please choose another name." | |
exit 1 | |
fi | |
# Delete existing templates | |
if [ "$delete_previous" = "y" ]; then | |
echo "[*] Deleting existing templates..." | |
vm_list=$(qm list | grep template | awk '{print $1}') | |
for vm_id in "${template_ids[@]}"; do | |
for i in $(seq $vm_id $(($vm_id + ${#sources[@]}))); do | |
if echo "$vm_list" | grep -q "$i"; then | |
qm destroy "$i" | |
fi | |
done | |
done | |
echo "[*] Deletion complete." | |
fi | |
start=$(date +%s) | |
sorted=$(for i in "${!choices[@]}"; do echo "${choices[i]}"; done | sort) | |
for source in $sorted; do | |
if vm_exists "template-$source"; then | |
echo "[*] Template for $source already exists, skipping..." | |
continue | |
fi | |
distro=$(echo "$source" | cut -d'-' -f1) | |
vm_id=${template_ids[$distro]} | |
while vm_exists "$vm_id"; do | |
echo "[*] VM with ID $vm_id already exists, trying next id..." | |
vm_id=$(($vm_id + 1)) | |
done | |
echo "[*] Creating template for $source..." | |
extension="${sources[$source]##*.}" | |
image_path="/tmp/$source.$extension" | |
download_template "${sources[$source]}" "$image_path" | |
echo "[*] Customizing image, please wait..." | |
virt-customize -a "$image_path" \ | |
--install qemu-guest-agent \ | |
--run-command 'sed -i "s/ssh_pwauth:.*0/ssh_pwauth: 1/" /etc/cloud/cloud.cfg' \ | |
--run-command 'sed -i "s/ssh_pwauth:.*[Ff]alse/ssh_pwauth: true/" /etc/cloud/cloud.cfg' \ | |
--run-command 'sed -i "s/disable_root:.*[Tt]rue/disable_root: false/" /etc/cloud/cloud.cfg' \ | |
--run-command 'sed -i "s/disable_root:.*1/disable_root: 0/" /etc/cloud/cloud.cfg' \ | |
--run-command 'sed -i "s/lock_passwd:.*[Tt]rue/lock_passwd: false/" /etc/cloud/cloud.cfg' \ | |
--run-command 'sed -i "s/lock_passwd:.*1/lock_passwd: 0/" /etc/cloud/cloud.cfg' \ | |
--run-command 'sed -i "s/PasswordAuthentication no/PasswordAuthentication yes/" /etc/ssh/sshd_config' \ | |
--run-command 'sed -i "s/PermitRootLogin [Nn]o/PermitRootLogin yes/" /etc/ssh/sshd_config' \ | |
--run-command 'sed -i "s/#PermitRootLogin [Yy]es/PermitRootLogin yes/" /etc/ssh/sshd_config' \ | |
--run-command 'sed -i "s/#PermitRootLogin prohibit-password/PermitRootLogin yes/" /etc/ssh/sshd_config' \ | |
--run-command 'sed -i "s/KbdInteractiveAuthentication [Nn]o/#KbdInteractiveAuthentication no/" /etc/ssh/sshd_config' \ | |
--run-command 'sed -i "s/[#M]axAuthTries 6/MaxAuthTries 20/" /etc/ssh/sshd_config' \ | |
--no-logfile | |
echo "[*] Creating new VM with ID $vm_id..." | |
is_x86_64_v2=$(echo "${sources[$source]}" | grep -c "x86_64") | |
cpu_type="kvm64" | |
if [ "$use_cpu_host" = "y" ]; then | |
cpu_type="host" | |
fi | |
if [ "$is_x86_64_v2" -eq 1 ]; then | |
cpu_type="x86-64-v2" | |
fi | |
qm create $vm_id --name "template-$source" --memory 512 --cores 4 --net0 virtio,bridge=vmbr0,firewall=1 --agent enabled=1,fstrim_cloned_disks=1 --cpu $cpu_type | |
echo "[*] Importing template image..." | |
qm importdisk $vm_id "/tmp/$source.$extension" "$storage" -format qcow2 | |
echo "[*] Attaching disk to template..." | |
qm set $vm_id --scsihw virtio-scsi-pci --scsi0 "$storage:vm-$vm_id-disk-0" | |
echo "[*] Applying important settings..." | |
qm set $vm_id --ide2 "$storage:cloudinit" --boot c --bootdisk scsi0 --serial0 socket --vga serial0 | |
echo "[*] Resizing disk..." | |
qm resize $vm_id scsi0 +2G | |
echo "[*] Creating template from VM..." | |
qm template $vm_id | |
if [ "$delete_templates" = "y" ]; then | |
echo "[*] Deleting downloaded image file:" | |
rm -v $image_path | |
fi | |
result_ids[$source]="$vm_id" | |
template_ids[$distro]=$(($vm_id+1)) | |
echo "[*] Template creation for $source complete." | |
done | |
end=$(date +%s) | |
echo "[*] Script execution finished after $((($end-$start)/60)) min $((($end-$start)%60)) sec." | |
created_count=${#result_ids[@]} | |
if [ "$created_count" -eq 0 ]; then | |
echo "[!] No new templates were created." | |
exit 0 | |
else | |
echo "[*] The following templates were created:" | |
for source in "${!result_ids[@]}"; do | |
echo " - $source: ${result_ids[$source]}" | |
done | |
fi | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment