Overview
Cloud-Init is a powerful cloud instance initialization framework that automates the configuration of instances during boot. In Proxmox VE, Cloud-Init enables templated VM deployment with automatic user provisioning, SSH key configuration, network setup, and custom initialization scripts. This approach is industry-standard for Infrastructure as Code (IaC) workflows and significantly reduces manual VM configuration time.
Key Benefits of Cloud-Init in Proxmox
- Automated Provisioning: Configure VMs at boot time without manual intervention
- Reproducibility: Create consistent instances across multiple deployments
- Scalability: Easily provision multiple VMs with identical configurations
- Security: Manage SSH keys and user credentials programmatically
- Network Configuration: Automatically configure network interfaces and DNS settings
- Custom Initialization: Run arbitrary scripts or commands during first boot
Creating the Cloud-Init Template
Step 1: Download Ubuntu Cloud Image
1wget https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img2qm create 8000 --memory 2048 --core 2 --name ubuntu-cloud --net0 virtio,bridge=vmbr03qm disk import 8000 noble-server-cloudimg-amd64.img local-lvm4qm set 8000 --scsihw virtio-scsi-pci --scsi0 local-lvm:vm-8000-disk-05qm set 8000 --ide2 local-lvm:cloudinit6qm set 8000 --boot c --bootdisk scsi07qm set 8000 --serial0 socket --vga serial08qm template 80009qm clone 8000 135 --name ubuntu-cloud --fullTechnical Details of Each Step
Download Stage
The official Ubuntu cloud images from Canonical are optimized for cloud deployments. They contain:
- Minimal filesystem (reduced bloat compared to standard ISOs)
- Pre-installed Cloud-Init agent
- Network device drivers optimized for hypervisors (virtio)
- No package manager cached data to minimize image size
Available Ubuntu Versions: focal (20.04 LTS), jammy (22.04 LTS), noble (24.04 LTS), oracular (24.10)
VM Creation (qm create)
--memory 2048 : Base memory allocation in MB (can be adjusted per deployment)
--core 2 : CPU cores (scales with workload requirements)
--name : Logical identifier for the template
--net0 : Network configuration (virtio driver for performance, vmbr0 = bridge)
Disk Import (qm disk import)
This step converts the downloaded cloud image to Proxmox's storage format:
- Imports into local-lvm storage backend
- Creates a dedicated volume for the VM
- Initializes the disk with proper permissions and metadata
Storage Configuration (qm set --scsihw)
--scsihw virtio-scsi-pci : SCSI controller (modern alternative to IDE)
--scsi0 local-lvm:... : Primary disk assignment using virtio-scsi
Performance Note: virtio-scsi provides better performance and scalability compared to IDE, supporting hot-plug operations and higher IOPS.
Cloud-Init ISO Setup (--ide2)
--ide2 local-lvm:cloudinit : IDE channel 2 for Cloud-Init data disk
This creates a read-only CD-ROM containing Cloud-Init metadata, user-data, and vendor-data. The Cloud-Init agent inside the VM reads this during boot.
Boot Configuration
--boot c : Boot order (c = disk, n = network, a = floppy, d = cdrom)
--bootdisk scsi0 : Designate primary boot disk
--serial0 socket : Serial console for troubleshooting (essential for headless VMs)
--vga serial0 : Direct console output to serial port
Template Conversion
qm template 8000 : Converts VM to template (disables further direct modifications)
Templates in Proxmox are read-only VMs that serve as base images for cloning. This prevents accidental modifications to the base configuration.
Cloning from Template
Full Clone vs. Linked Clone
The provided command uses --full to create a full clone (independent copy of all disk data):
1qm clone 8000 135 --name ubuntu-cloud --fullFull Clone:
- Independent disk copy (complete storage isolation)
- Higher storage overhead (~2GB+ per clone)
- Better for production VMs that require stability
- No dependency on parent template
Linked Clone (without --full):
1qm clone 8000 135 --name ubuntu-cloud- Shared backing data with copy-on-write (CoW)
- ~90% storage savings
- Faster clone creation
- Suitable for development/testing
- Lower performance compared to full clones
Cloud-Init Configuration Options
After cloning, you can customize Cloud-Init behavior using these parameters:
User Configuration
1qm set 135 --ciuser ubuntu --cipassword password123ciuser: Specifies which user account should receive SSH keys and password configuration. Default depends on image (ubuntu for Ubuntu images, debian for Debian, etc.)
Network Configuration
1qm set 135 --ipconfig0 ip=192.168.1.100/24,gw=192.168.1.12qm set 135 --ipconfig1 ip=192.168.2.100/24ipconfig: Static IP configuration in netplan/cloud-init format:
ip=<address>/<cidr>: IPv4 address and netmaskgw=<gateway>: Default gatewayip6=<address>/<cidr>: IPv6 configurationip6gw=<gateway>: IPv6 gateway
Custom Cloud-Init Script
1qm set 135 --cicustom "user=local:snippets/custom-cloud-init.yaml"This allows injecting custom initialization logic (package installation, service configuration, etc.)
Hostname and Domain Configuration
1qm set 135 --hostname prod-app-01 --searchdomain example.comVerification Commands
After creating the template, verify its configuration:
1# List template details2qm config 80003
4# Show template status5qm status 80006
7# List all clones from this template8qm list | grep -E "^[0-9]+" | awk '{print $1, $2}' | grep -v "8000"9
10# Verify Cloud-Init disk attachment11qm config 8000 | grep ide2