Co-authored-by: Cursor <cursoragent@cursor.com>
14 KiB
Create VM 9000 from Uploaded Image - CLI Workflow
⚠️ Troubleshooting I/O Errors
If you encounter I/O errors during VM creation (like qemu-img: error while reading at byte...), see TROUBLESHOOTING_VM_9000.md for:
- Diagnostic steps to check file integrity
- Solutions to fix corrupted images
- Alternative upload methods
- Storage health checks
Quick Fix: The most common solution is to re-upload the image. See Solution 1 in the troubleshooting guide.
✅ Image Uploaded Successfully!
- Location:
/var/lib/vz/template/iso/ubuntu-24.04-server-cloudimg-amd64.img - Size: 597 MB
Pre-Creation Verification (Recommended)
Before creating the VM, verify the image is valid:
On Proxmox host (SSH):
# Check file exists and size
ls -lh /var/lib/vz/template/iso/ubuntu-24.04-server-cloudimg-amd64.img
# Verify image integrity
qemu-img info /var/lib/vz/template/iso/ubuntu-24.04-server-cloudimg-amd64.img
The qemu-img info command should show:
- Format:
raworqcow2 - Virtual size: ~2.2 GB (or similar)
- No errors
If you see errors, follow the troubleshooting guide.
🚀 Proxmox: 5-Minute CLI Workflow to Create a VM from Any QCOW2/RAW Image
This workflow works for:
- Ubuntu cloud images
- Windows prepared images
- Turnkey appliances
- Custom images you built yourself
Reference: For official Proxmox VE documentation, see Proxmox VE Documentation Index
Quick Reference: 5-Minute CLI Workflow
On Proxmox host (SSH):
# Step 1: Create VM shell (no disk)
qm create 9000 --name "ubuntu-24.04-cloudinit" --memory 4096 --cores 2 --net0 virtio,bridge=vmbr0
# Step 2: Import disk from image
qm importdisk 9000 /var/lib/vz/template/iso/ubuntu-24.04-server-cloudimg-amd64.img local-lvm
# Step 3: Attach imported disk
qm set 9000 --scsihw virtio-scsi-pci --scsi0 local-lvm:vm-9000-disk-0
# Step 4: Configure boot order
qm set 9000 --boot order=scsi0
# Step 5: (Optional) Add UEFI support
qm set 9000 --bios ovmf --efidisk0 local-lvm:1
# Step 6: (Optional) Add Cloud-init support
qm set 9000 --ide2 local-lvm:cloudinit
qm set 9000 --serial0 socket --vga serial0
# Step 7: Start VM
qm start 9000
Done! You've created a VM from a raw disk image in 5 minutes.
Detailed Step-by-Step Instructions
Step 1: Upload Image to Proxmox Storage
Upload your .qcow2 or .raw image to:
/var/lib/vz/template/iso/(directory storage)- Or upload via Proxmox Web UI to your storage pool
Verify upload:
ls -lh /var/lib/vz/template/iso/ubuntu-24.04-server-cloudimg-amd64.img
qemu-img info /var/lib/vz/template/iso/ubuntu-24.04-server-cloudimg-amd64.img
Step 2: Create New VM Shell (No Disk Yet)
Pick an unused VMID (example uses 9000):
qm create 9000 \
--name "ubuntu-24.04-cloudinit" \
--memory 4096 \
--cores 2 \
--net0 virtio,bridge=vmbr0
Parameters:
--name: VM display name--memory: Memory in MB (4096 = 4 GB)--cores: Number of CPU cores--net0: Network interface (VirtIO for best performance)
Check available VMIDs:
qm list
Step 3: Import the QCOW2/RAW Disk into the VM
Import the disk image to your storage pool:
qm importdisk 9000 /var/lib/vz/template/iso/ubuntu-24.04-server-cloudimg-amd64.img local-lvm
Parameters:
9000: VM ID- Image path: Full path to your image file
local-lvm: Target storage pool (adjust for your environment)
Available storage pools:
pvesm status
Note: The output will tell you the volume name (usually vm-9000-disk-0).
Step 4: Attach the Imported Disk to the VM
Attach the imported disk as a VirtIO SCSI device:
qm set 9000 --scsihw virtio-scsi-pci --scsi0 local-lvm:vm-9000-disk-0
Why VirtIO SCSI?
- Best performance for virtualized storage
- Supports advanced features (discard, iothread)
- Recommended for production VMs
Alternative disk configurations:
# VirtIO block device (alternative)
qm set 9000 --virtio0 local-lvm:vm-9000-disk-0
# IDE device (legacy compatibility)
qm set 9000 --ide0 local-lvm:vm-9000-disk-0
Step 5: Configure Bootloader and Boot Disk
Set the boot order to use the attached disk:
qm set 9000 --boot order=scsi0
UEFI Configuration (Optional, Recommended for Modern Images):
If your image requires UEFI (most modern cloud images do):
# Enable UEFI/OVMF
qm set 9000 --bios ovmf
# Create EFI disk (if not using secure boot)
qm set 9000 --efidisk0 local-lvm:1,format=raw
BIOS Configuration (Legacy):
For older images that require BIOS:
qm set 9000 --bios seabios
Verify boot configuration:
qm config 9000 | grep -E "boot|bios|scsi0"
Step 6: (Optional) Add Cloud-Init Support
Enable Cloud-Init for automatic VM configuration:
# Add Cloud-Init drive
qm set 9000 --ide2 local-lvm:cloudinit
# Enable serial console (required for cloud-init)
qm set 9000 --serial0 socket --vga serial0
Configure Cloud-Init settings:
# Set Cloud-Init user
qm set 9000 --ciuser ubuntu
# Set SSH public key (recommended over password)
qm set 9000 --sshkey ~/.ssh/id_rsa.pub
# Or set password (less secure)
# qm set 9000 --cipassword "your-secure-password"
# Configure IP address (optional)
qm set 9000 --ipconfig0 ip=192.168.1.100/24,gw=192.168.1.1
# Configure DNS (optional)
qm set 9000 --nameserver "8.8.8.8 8.8.4.4"
# Configure search domains (optional)
qm set 9000 --searchdomain "example.com"
Multiple SSH keys:
# Read multiple keys from file
qm set 9000 --sshkey "$(cat ~/.ssh/id_rsa.pub ~/.ssh/id_ed25519.pub)"
Step 7: Enable QEMU Guest Agent (Recommended)
Enable the QEMU Guest Agent for better VM management:
qm set 9000 --agent 1
Benefits:
- Accurate CPU and memory reporting
- Proper shutdown/reboot from Proxmox UI
- File system freeze for backups
- Network statistics
Step 8: Configure Additional Options (Optional)
CPU Optimization:
# Use host CPU type for best performance
qm set 9000 --cpu host
# Set CPU limit (optional)
qm set 9000 --cpulimit 2
Memory Optimization:
# Enable balloon driver for dynamic memory
qm set 9000 --balloon 2048
# Enable memory hotplug
qm set 9000 --hotplug memory
Disk I/O Optimization:
# Enable IO thread for better I/O performance
qm set 9000 --iothread 1
# Set cache mode (none = best performance, safest)
qm set 9000 --cache none
# Enable discard (for thin provisioning)
qm set 9000 --discard on
Network Optimization:
# Enable multi-queue for high network loads
qm set 9000 --queues 2
# Configure VLAN tagging
qm set 9000 --net0 virtio,bridge=vmbr0,tag=20
Step 9: Start the VM
Start the VM:
qm start 9000
Monitor VM status:
# Check VM status
qm status 9000
# View VM console
qm terminal 9000
# View VM logs
journalctl -u qemu-server@9000 -f
🎯 Converting VM to Template
After installing and customizing the VM, convert it to a reusable template:
# Shutdown VM gracefully
qm shutdown 9000
# Wait for shutdown, then convert to template
qm template 9000
Now you can clone it in seconds:
Full Clone (Independent):
qm clone 9000 9100 --full --name "ubuntu-24.04-vm-1"
qm start 9100
Linked Clone (Space Efficient):
qm clone 9000 9100 --name "ubuntu-24.04-vm-1"
qm start 9100
Configure cloned VM:
# Set unique cloud-init settings for clone
qm set 9100 --ciuser ubuntu
qm set 9100 --sshkey ~/.ssh/id_rsa.pub
qm set 9100 --ipconfig0 ip=192.168.1.101/24,gw=192.168.1.1
🎯 Cloud-Init Template Best Practices
Create a production-ready cloud-init template:
# 1. Create and configure base VM (as above)
# 2. Configure Cloud-Init with best practices
qm set 9000 --ciuser ubuntu
qm set 9000 --cipassword "" # Leave empty, use SSH keys
qm set 9000 --sshkey "$(cat ~/.ssh/id_rsa.pub)"
qm set 9000 --ipconfig0 ip=dhcp # Or static IP per deployment
# 3. Add metadata tags
qm set 9000 --tags ubuntu,cloud-init,template
# 4. Optimize for cloning
qm set 9000 --description "Ubuntu 24.04 Cloud-Init Template - Created $(date +%Y-%m-%d)"
# 5. Shutdown and convert to template
qm shutdown 9000
qm template 9000
Clone with custom configuration:
# Clone template
qm clone 9000 9100 --name "production-web-1"
# Configure per-deployment settings
qm set 9100 \
--ciuser ubuntu \
--sshkey "$(cat ~/.ssh/id_rsa.pub)" \
--ipconfig0 ip=10.10.30.10/24,gw=10.10.30.1 \
--nameserver "10.10.30.1" \
--tags "production,web,app-tier"
# Start VM
qm start 9100
🎯 Complete Example: Production-Ready VM Creation
Complete command sequence for a production VM:
# Variables
VMID=9000
VMNAME="ubuntu-24.04-cloudinit"
IMAGE="/var/lib/vz/template/iso/ubuntu-24.04-server-cloudimg-amd64.img"
STORAGE="local-lvm"
MEMORY=4096
CORES=2
BRIDGE="vmbr0"
SSHKEY="$(cat ~/.ssh/id_rsa.pub)"
# Step 1: Create VM shell
qm create $VMID \
--name "$VMNAME" \
--memory $MEMORY \
--cores $CORES \
--net0 virtio,bridge=$BRIDGE \
--cpu host \
--agent 1
# Step 2: Import disk
qm importdisk $VMID "$IMAGE" $STORAGE
# Step 3: Attach disk
qm set $VMID \
--scsihw virtio-scsi-pci \
--scsi0 ${STORAGE}:vm-${VMID}-disk-0 \
--iothread 1 \
--cache none \
--discard on
# Step 4: Configure boot
qm set $VMID \
--boot order=scsi0 \
--bios ovmf \
--efidisk0 ${STORAGE}:1,format=raw
# Step 5: Configure Cloud-Init
qm set $VMID \
--ide2 ${STORAGE}:cloudinit \
--serial0 socket \
--vga serial0 \
--ciuser ubuntu \
--sshkey "$SSHKEY" \
--ipconfig0 ip=dhcp
# Step 6: Optimize memory
qm set $VMID --balloon $((MEMORY/2))
# Step 7: Start VM
qm start $VMID
# Step 8: Monitor
qm status $VMID
qm terminal $VMID
🎯 Network Configuration Examples
Basic Network (VLAN-unaware)
qm set 9000 --net0 virtio,bridge=vmbr0
VLAN Tagging
# Single VLAN
qm set 9000 --net0 virtio,bridge=vmbr0,tag=20
# Multiple network interfaces with different VLANs
qm set 9000 --net0 virtio,bridge=vmbr0,tag=20
qm set 9000 --net1 virtio,bridge=vmbr0,tag=30
Project-Specific VLANs
According to project architecture:
# Storage VLAN (10.10.10.0/24)
qm set 9000 --net0 virtio,bridge=vmbr0,tag=10
# Compute VLAN (10.10.20.0/24)
qm set 9000 --net0 virtio,bridge=vmbr0,tag=20
# App Tier VLAN (10.10.30.0/24)
qm set 9000 --net0 virtio,bridge=vmbr0,tag=30
# Observability VLAN (10.10.40.0/24)
qm set 9000 --net0 virtio,bridge=vmbr0,tag=40
# Dev/Test VLAN (10.10.50.0/24)
qm set 9000 --net0 virtio,bridge=vmbr0,tag=50
# Management VLAN (10.10.60.0/24)
qm set 9000 --net0 virtio,bridge=vmbr0,tag=60
# DMZ VLAN (10.10.99.0/24)
qm set 9000 --net0 virtio,bridge=vmbr0,tag=99
🎯 Storage Options
Different Storage Types
# Local LVM (fast, thin-provisioned)
qm importdisk 9000 "$IMAGE" local-lvm
# Local directory storage
qm importdisk 9000 "$IMAGE" local
# NFS shared storage
qm importdisk 9000 "$IMAGE" nfs-shared
# Ceph distributed storage
qm importdisk 9000 "$IMAGE" ceph-storage
Disk Format Choices
# Raw format (best performance)
qm importdisk 9000 "$IMAGE" local-lvm --format raw
# qcow2 format (advanced features)
qm importdisk 9000 "$IMAGE" local-lvm --format qcow2
# vmdk format (VMware compatibility)
qm importdisk 9000 "$IMAGE" local-lvm --format vmdk
🎯 Automation Script
For automated VM creation, use the provided script:
./scripts/create-vm-from-image.sh \
--vmid 9000 \
--name "ubuntu-24.04-cloudinit" \
--image /var/lib/vz/template/iso/ubuntu-24.04-server-cloudimg-amd64.img \
--storage local-lvm \
--memory 4096 \
--cores 2 \
--cloud-init \
--uefi \
--template \
--ciuser ubuntu \
--sshkey "$(cat ~/.ssh/id_rsa.pub)"
See scripts/create-vm-from-image.sh for full documentation.
✅ Done!
Once template is created, the monitoring script will automatically:
- Detect the template
- Destroy existing VMs
- Recreate them from template
- Auto-configure everything
Or run manually:
./scripts/recreate-vms-from-template.sh
📚 Additional Resources
Official Proxmox VE Documentation
- Proxmox VE Documentation Index: Complete documentation (Version 9.1.1)
- QEMU/KVM Virtual Machines: VM management guide (Chapter 10)
- qm(1) Manual Page: Complete qm command reference
- Proxmox VE Storage: Storage management (Chapter 7)
- qm.conf(5) Configuration: VM configuration file format
- High Availability: HA configuration (Chapter 15)
- Backup and Restore: Backup strategies (Chapter 16)
- FAQ: Frequently asked questions (Chapter 26)
Project-Specific Documentation
- Azure Arc Onboarding: Azure Arc integration guide
- Network Topology: Network design and VLAN configuration
- Proxmox Operations: General Proxmox operations runbook
- Deployment Guide: Complete deployment instructions
Troubleshooting
- TROUBLESHOOTING_VM_9000.md: Troubleshooting I/O errors and image issues
- Common issues and solutions are documented in the troubleshooting guide above
Scripts and Automation
scripts/create-vm-from-image.sh: Automated VM creation scriptscripts/create-vm-template.sh: Cloud-init template creation scriptscripts/recreate-vms-from-template.sh: Clone VMs from templatescripts/verify-proxmox-image.sh: Image verification script
🎯 Next Steps
- Verify VM creation: Check that VM starts successfully
- Configure Azure Arc agent: Install Arc agent for Azure integration
./scripts/azure-arc/onboard-vms.sh - Configure monitoring: Set up Prometheus/Grafana monitoring
- Create backup: Schedule regular backups
vzdump 9000 --storage backup-storage --compress zstd
Happy Deploying! 🚀