Automating VM Provisioning with Bash, Kickstart & PXE
July 19, 2026 ยท Ahmad M. Waddah ยท 19 reads
๐งฉ Stack: Bash ยท KVM/QEMU ยท Kickstart ยท PXE ยท Linux
โ The Problem
Setting up a KVM virtual machine manually involves:
- Creating the disk image
- Installing the OS (click through the installer)
- Configuring networking, SSH, users
- Applying baseline security
- Installing required packages
For one VM, it's tedious. For a dozen, it's unsustainable.
๐ ๏ธ The Solution: Modular Bash Architecture
The automation tool is organised as a set of specialised Bash modules:
kvm-spin-ups/
โโโ kvm-spin-up.sh # Entry point โ parses args, orchestrates
โโโ lib/
โ โโโ disk.sh # qemu-img, disk sizing, storage pools
โ โโโ network.sh # bridge setup, NAT, port forwarding
โ โโโ install.sh # kickstart integration
โ โโโ post-install.sh # SSH keys, users, security hardening
โ โโโ validate.sh # Pre-flight checks
โโโ templates/
โโโ minimal.ks # Minimal kickstart config
โโโ server.ks # Server with LAMP stack
โโโ docker-host.ks # Docker-ready VM
๐ Kickstart for Unattended OS Installation
# install.sh โ generates kickstart config dynamically
generate_kickstart() {
local hostname=$1
local disk=$2
cat > /tmp/"${hostname}".ks <<EOF
#version=RHEL8
text
url --url="http://mirror.centos.org/8/BaseOS/x86_64/os/"
lang en_US.UTF-8
keyboard us
timezone UTC --isUtc
rootpw --locked
user --name=deploy --groups=wheel --password=${DEFAULT_PASS}
# Disk layout
clearpart --all --initlabel
autopart --type=lvm
# Minimal package set
%packages
@core
openssh-server
vim
%end
%post
systemctl enable sshd
echo "deploy ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/deploy
%end
EOF
}
๐ Automation Flow
# kvm-spin-up.sh
main() {
validate_env # Check KVM, libvirt, permissions
generate_kickstart # Create OS config
create_disk # qemu-img create -f qcow2
launch_vm # virt-install with kickstart
wait_for_boot # Poll SSH until ready
run_post_install # Security, packages, monitoring
print_summary # IP, credentials, next steps
}
A single command replaces 45 minutes of manual work:
./kvm-spin-up.sh --name web-01 --ram 4096 --cpus 4 --disk 50G --template server
๐ Results
| Step | Manual | Automated |
|---|---|---|
| OS installation | 25 min (clickthrough) | 3 min (unattended) |
| Network config | 5 min | automatic |
| Security hardening | 10 min | 30 seconds |
| Total per VM | ~45 min | ~5 min |
| 10 VMs | 7.5 hours | 50 minutes |
๐ก Key Takeaways
- Kickstart turns OS installation into a config file โ reproducible and version-controlled
- Modular Bash (one task per file) keeps the codebase maintainable as it grows
- Pre-flight validation catches missing dependencies before they fail mid-way
- This approach works for any libvirt-compatible hypervisor โ not just KVM
๐ See the full tool at KVM Spin Ups.