A fast, interactive CLI tool for deploying KVM virtual machines from cloud images.
kdeploy automates the creation of KVM virtual machines using cloud-init enabled cloud images (qcow2 format). What used to take 15-30 minutes of GUI installation now takes under 2 minutes.
- Speed: Deploy a VM in under 2 minutes
- No GUI Needed: Fully automated, command-line driven
- Cloud-Init Integration: Automatic SSH key injection, user setup, and package installation
- Multiple Distros: Support for Rocky Linux (10, 9, 8), Ubuntu (24.04, 22.04, 20.04), Debian (13, 12, 11), and more
- Interactive: Guided setup with sensible defaults
- Open Source: Released under the Waqf Public License
This tool was born out of frustration with slow VM installations. After 5 years of using traditional GUI-based VM installations, I discovered:
- Cloud Images: Pre-configured, minimal OS images in qcow2 format
- Overlay Images: Copy-on-write snapshots that don't modify the base image
- Cloud-Init: Automatic VM configuration (users, SSH keys, packages) at first boot
The combination of these three technologies completely changed how I work with VMs. No more clicking through installation wizards, no more waiting for packages to download, no more manual SSH configuration.
kdeploy creates VMs in three simple steps:
-
Download a Cloud Image: Fetch a pre-configured minimal OS image in qcow2 format (~1GB) from upstream providers like Rocky Linux, Ubuntu, Debian, or Fedora.
-
Create an Overlay: Generate a copy-on-write snapshot that references the base image. This is fast to create and leaves the original image untouched.
-
Cloud-Init Configuration: On first boot, cloud-init automatically injects your SSH key, creates your user account, and installs any packages you specify.
Total time: ~30 seconds from start to SSH access.
This is essentially how AWS, DigitalOcean, and other cloud providers create VMs instantly. Now you can do the same locally.
- Speed: Deploy a VM in 14 seconds (with
-yflag) - Interactive Setup: Guided configuration with sensible defaults
- Smart Path Handling: User-owned or system-managed storage paths
- Image Download: Built-in catalog of popular cloud images
- Automatic OS Detection: Detects Rocky, Ubuntu, Debian, Alpine Linux from filename
- Resource Selection: Choose RAM, vCPUs, and disk size
- SSH Config Management: Automatic SSH host configuration
- Fast IP Discovery: Uses DHCP leases (no qemu-guest-agent needed)
- Dependency Management: Auto-detects and offers to install missing packages
- Pre-flight Checks: KVM, libvirt, network, storage pool, disk space
- Permission Handling: Auto-detects and offers to add user to libvirt group
- UTC Timezone: Enforces UTC timezone for cloud-native standardization
| Distribution | Packages |
|---|---|
| Arch/CachyOS | libvirt virt-install qemu-img cloud-utils openssl wget curl |
| Debian/Ubuntu | libvirt-daemon-system virtinst qemu-utils cloud-image-utils openssl wget curl |
| Fedora/Rocky | libvirt virt-install qemu-img cloud-utils openssl wget curl |
- KVM virtualization enabled in BIOS/UEFI
- SSH public key at
~/.ssh/id_rsa.pub - Write access to chosen storage path
# Clone or download the script
git clone https://github.com/hazembook/kdeploy.git
cd kdeploy
# Make executable
chmod +x kdeploy
# Run - first run will guide you through setup
./kdeployTo run kdeploy from anywhere without ./ prefix:
mkdir -p ~/.local/bin
cp kdeploy ~/.local/bin/kdeploy
chmod +x ~/.local/bin/kdeploy
# Add to PATH if needed (add to ~/.bashrc or ~/.zshrc)
export PATH="$HOME/.local/bin:$PATH"
# Now you can run from anywhere
kdeploy myvm# Basic deployment (follow interactive prompts)
./kdeploy myvm
# Fast deployment (skip all confirmations, ~14 seconds!)
./kdeploy myvm -y
# Specify disk size
./kdeploy myvm 50G
# Override resources
./kdeploy myvm -r 4096 -c 4
# Use custom paths (one-time override)
./kdeploy myvm -i /path/to/images -s /path/to/storage
# Fully non-interactive (custom paths + skip confirmations)
./kdeploy myvm -i /path/to/images -s /path/to/storage -y
# Use custom virtual network
./kdeploy myvm -n my-custom-network
# Destroy a VM (quick teardown)
./kdeploy destroy myvm
# Reconfigure default paths
./kdeploy --reconfig
# Show current configuration
./kdeploy --show-configπ― First-time setup - configuring paths...
π Image Library Path
[1] ~/VM/cloud_images (user-owned, recommended)
[2] /var/lib/libvirt/images (system-managed)
[3] Custom path
Choice [1]: 1
πΎ VM Storage Path
[1] /var/lib/libvirt/images (libvirt standard)
[2] ~/VM/disks (user-owned)
[3] Custom path
Choice [1]: 2
β
Configuration saved to ~/.config/kdeploy.conf
Configuration is stored in ~/.config/kdeploy.conf:
IMAGE_PATH=/home/user/VM/cloud_images
STORAGE_PATH=/home/user/VM/disks
DEFAULT_VM_SIZE=20G
DEFAULT_RAM=2048
DEFAULT_CPUS=2
DEFAULT_PASSWORD=linuxQuickly spin up VMs to practice:
- Systemd and services
- Network configuration
- User and group management
- LVM and storage
- Container orchestration
Create isolated dev environments in seconds:
- Database servers
- Web application stacks
- Kubernetes nodes
| Method | Time to First Boot | Manual Config |
|---|---|---|
| GUI (Virt-Manager) | 15-30 min | Yes |
| Text Installer | 10-20 min | Yes |
| kdeploy (interactive) | ~30 sec | No |
kdeploy (-y flag) |
~14 sec | No |
If deployment times out while waiting for DHCP/IP:
- Connect to console:
virsh console <vm-name>(login: cloud-user/rocky/ubuntu/debian) - Check network:
virsh net-dhcp-leases default - For slow DHCP (wireless/bridged), increase timeout in script if needed
If you get permission errors:
sudo usermod -aG libvirt $USER
# Log out and back inEnsure virtualization is enabled in BIOS/UEFI, then load module:
sudo modprobe kvm
sudo modprobe kvm_intel # for Intel CPUs
sudo modprobe kvm_amd # for AMD CPUs- Machine: Lenovo ideapad 320-15IKB Touch
- CPU: Intel Core i7-8550U (4 cores, 8 threads) @ 4.00 GHz
- RAM: 20 GB DDR4
- Storage: 477GB SSD (512MB boot + 128GB root + 348GB home)
| Mode | Time to First Boot | Notes |
|---|---|---|
| Interactive | 18-30 sec | With prompts |
Non-interactive (-y) |
14-18 sec | Fully automated |
| GUI (Virt-Manager) | 15-30 min | Manual install |
Here are the aliases that I use to manage VMs efficiently (Left-Handed V-Set).
Add these to your ~/.bashrc or ~/.zshrc:
## Virsh (Left-Handed V-Set)
alias vv='virsh list --all'
alias vs='virsh start'
alias vq='virsh shutdown'
alias vc='virsh console'
alias vd='virsh destroy'
alias vr='virsh reboot'
alias ve='virsh edit'
function va() {
virsh domifaddr "$1" | awk '/ipv4/ {print $4}' | cut -d/ -f1
}
function vxx() {
echo "Destroying and Undefining: $1"
virsh destroy "$1" 2>/dev/null
virsh undefine "$1" --remove-all-storage
}Add these to your ~/.config/fish/config.fish:
## Virsh (Left-Handed V-Set)
alias vv 'virsh list --all'
alias vs 'virsh start'
alias vq 'virsh shutdown'
alias vc 'virsh console'
alias vd 'virsh destroy'
alias vr 'virsh reboot'
alias ve 'virsh edit'
function va; virsh domifaddr $argv[1] | awk '/ipv4/ {print $4}' | cut -d/ -f1; end
function vxx
echo "Destroying and Undefining: $argv[1]"
virsh destroy $argv[1] 2>/dev/null
virsh undefine $argv[1] --remove-all-storage
end This project is licensed under the Waqf Public License 2.0.
The Waqf license is an Islamic-inspired, business-friendly, permissive license that:
- Allows free use, modification, and redistribution
- Requires attribution
- Does not restrict commercial use
- Has no time limit on the license
See the LICENSE file for full text.