Introduction
Cloud-init is a powerful industry-standard tool for automating the initial configuration of virtual machines. Instead of manually setting up each new VM with network settings, user accounts, and SSH keys, cloud-init templates let you deploy pre-configured VMs in seconds.
This guide shows you how to create a cloud-init template VM in Proxmox that you can clone repeatedly, with each clone automatically configured with unique settings like IP addresses, hostnames, and SSH keys.
Why use cloud-init templates?
- Speed: Deploy fully-configured VMs in under a minute
- Consistency: Every VM starts with identical base configuration
- Automation: Perfect for Infrastructure as Code (Terraform, Ansible)
- Flexibility: Customize network, users, and SSH keys per-instance
Common use cases:
- Kubernetes cluster nodes that need identical base configurations
- Development/staging environments that mirror production
- Test VMs that can be quickly created and destroyed
- Automated CI/CD pipeline runners
Prerequisites
Before you begin, ensure you have:
- Proxmox VE 6.x or later with root or administrative access
- Storage space for the template VM (minimum 10GB recommended)
- Ubuntu server ISO or cloud image (see note below)
- Basic Linux command-line knowledge
- SSH access to the Proxmox host
Proxmox versions tested: This guide works with Proxmox VE 6.x, 7.x, and 8.x
Recommended Ubuntu versions:
- Ubuntu 20.04 LTS (Focal)
- Ubuntu 22.04 LTS (Jammy)
- Ubuntu 24.04 LTS (Noble)
Cloud Image vs. Installer ISO
Important distinction:
- Cloud images (
.imgfiles): Pre-built, minimal OS images specifically designed for cloud-init. Recommended for this guide. - Installer ISOs: Traditional installation media requiring manual OS installation
For this guide, we’ll use a standard Ubuntu Server ISO, but you can adapt the process for cloud images. If using cloud images, skip Step 2 (OS installation) and import the image directly.
Part 1: Create and Configure the Base VM
Step 1: Create the Virtual Machine
We’ll create a new VM that will become our template. You can use either the Proxmox Web UI or CLI.
Using Proxmox Web UI:
- General Settings:
- VM ID: Choose a high number to keep templates separate from regular VMs (e.g.,
900) - Name:
ubuntu-cloud-templateor similar descriptive name - Resource Pool: (optional) Create a “Templates” pool for organization
- VM ID: Choose a high number to keep templates separate from regular VMs (e.g.,
OS Settings:
- ISO Image: Select your uploaded Ubuntu Server ISO (e.g.,
ubuntu-22.04-server-amd64.iso) - Guest OS Type:
Linux - Version: Select the appropriate Ubuntu version
- ISO Image: Select your uploaded Ubuntu Server ISO (e.g.,
System Settings:
- BIOS:
OVMF (UEFI)for modern systems, orSeaBIOSfor compatibility - Machine Type:
q35(recommended) ori440fx(legacy) - SCSI Controller:
VirtIO SCSI(for best performance) - Qemu Agent: Enable (important for cloud-init integration)
- BIOS:
Disks:
- Bus/Device:
SCSI 0(recommended for performance) - Storage: Select your storage pool (e.g.,
local-lvm) - Disk Size:
10 GBminimum (expand after cloning if needed) - Cache:
Default (No cache)orWrite backfor better performance - Discard: Enable (enables thin provisioning on SSD storage)
- SSD Emulation: Enable if using SSD storage
- Bus/Device:
CPU:
- Sockets:
1 - Cores:
2(minimum; can be increased when cloning) - Type:
host(provides best performance by exposing all CPU features)
- Sockets:
Memory:
- RAM:
2048 MB(2GB minimum for Ubuntu Server) - Ballooning Device: Disable for templates (prevents memory issues)
- RAM:
Network:
- Model:
VirtIO (paravirtualized)for best network performance - Bridge:
vmbr0(your default bridge, adjust if using custom networking) - Firewall: Enable if desired
- Model:
Confirm:
- Review all settings carefully
- Click Finish to create the VM
- Do not start the VM yet
Using Proxmox CLI:
qm create 900 \
--name ubuntu-cloud-template \
--memory 2048 \
--cores 2 \
--net0 virtio,bridge=vmbr0 \
--scsihw virtio-scsi-pci \
--scsi0 local-lvm:10 \
--ide2 local:iso/ubuntu-22.04-server-amd64.iso,media=cdrom \
--boot order=scsi0 \
--agent enabled=1
Step 2: Install Ubuntu Server
Start the VM:
- From Proxmox UI, select the VM and click Start
- Open the Console to access the VM
Install Ubuntu:
- Language: Select your preferred language
- Keyboard: Choose your keyboard layout
- Installation type: Ubuntu Server (minimized)
- Network: Accept DHCP configuration (we’ll configure static IPs via cloud-init later)
- Storage: Use entire disk with default partitioning
- Profile setup:
- Your name:
ubuntu(this is temporary, cloud-init will manage users) - Server name:
ubuntu-template - Username:
ubuntu - Password: Set a secure password (you can disable this user later)
- Your name:
- SSH: Install OpenSSH server (check this option)
- Featured snaps: Leave unchecked (keep template minimal)
Complete Installation:
- Wait for installation to finish
- When prompted, Reboot the VM
- Let the VM boot into the fresh Ubuntu installation
Update the System:
ssh ubuntu@<vm-ip> sudo apt update && sudo apt upgrade -y
Part 2: Install and Configure Cloud-Init
Now we’ll install cloud-init and configure it for Proxmox’s cloud-init integration.
Step 3: Install Cloud-Init Package
sudo apt update
sudo apt install -y cloud-init qemu-guest-agent
Installed packages:
cloud-init: Handles initial VM configurationqemu-guest-agent: Allows Proxmox to communicate with the VM
Step 4: Configure Cloud-Init Datasource
Cloud-init needs to know where to get its configuration. For Proxmox, we use the NoCloud datasource.
Create or edit the datasource configuration:
sudo nano /etc/cloud/cloud.cfg.d/99_pve.cfgAdd the following content:
datasource_list: [ NoCloud, ConfigDrive ]Save and exit (Ctrl+X, then Y, then Enter)
Step 5: Clean Existing Network Configuration
To allow cloud-init to fully manage networking, remove existing netplan configurations:
sudo rm -f /etc/netplan/*.yaml
Why this step?
- Prevents conflicts between static network config and cloud-init
- Allows each cloned VM to get unique networking from cloud-init
- Ensures DHCP works initially if no cloud-init network config is provided
Step 6: Clean Cloud-Init State
Before converting to a template, clean cloud-init’s state so each clone starts fresh:
sudo cloud-init clean
sudo cloud-init clean --logs
What this does:
- Removes instance-specific data from this VM
- Clears cloud-init cache and logs
- Ensures each clone runs cloud-init as if it’s a first boot
Step 7: Shut Down the VM
Before converting to a template, properly shut down the VM:
sudo shutdown -h now
Or from Proxmox shell:
qm shutdown 900
Wait for the VM to fully power off (status should show “stopped”).
Part 3: Configure Proxmox Cloud-Init Integration
Now we’ll add Proxmox-specific cloud-init features to the VM.
Step 8: Add Cloud-Init Drive
From the Proxmox shell (SSH into your Proxmox host), run:
qm set 900 --ide2 local-lvm:cloudinit
What this does:
- Attaches a special cloud-init configuration drive as
ide2 - Proxmox uses this drive to pass cloud-init configuration to the VM
- This drive appears in the VM’s hardware as a CD-ROM device
Verify: Check the VM’s Hardware tab in the Proxmox UI - you should see “CloudInit Drive (ide2)”
Step 9: Configure Boot Settings
Set proper boot order so the VM boots from the OS disk, not the cloud-init drive:
qm set 900 --boot order=scsi0 --bootdisk scsi0
Step 10: Configure SCSI Controller (if not already set)
Ensure the SCSI controller is set to VirtIO for best performance:
qm set 900 --scsihw virtio-scsi-pci
Step 11: Enable Hot-Plugging (Optional)
Allow hot-plugging of network, disk, and USB devices:
qm set 900 --hotplug network,disk,usb
Benefits:
- Add/remove network interfaces without rebooting
- Resize disks without downtime
- Useful for dynamic cloud environments
Part 4: Convert to Template
Step 12: Convert VM to Template
Once everything is configured, convert the VM to a template:
qm template 900
What happens:
- VM is marked as a template in Proxmox
- VM can no longer be started directly
- VM can only be cloned to create new VMs
- Template is read-only (protects against accidental changes)
Verify: In the Proxmox UI, the VM should now have a template icon and show “Template” in its description.
Part 5: Clone and Configure New VMs
Now you can create new VMs from your template.
Step 13: Clone the Template
Using Proxmox Web UI:
- Right-click the template (VM 900)
- Select Clone
- Configuration:
- Target node: Select destination Proxmox node
- VM ID: Enter unique ID (e.g.,
101) - Name: Descriptive name (e.g.,
web-server-01) - Mode:
- Full Clone (recommended): Creates independent copy
- Linked Clone: Faster but depends on template
- Target Storage: Select where to store the new VM
- Click Clone
Using Proxmox CLI:
# Full clone (recommended)
qm clone 900 101 --name web-server-01 --full
# Linked clone (faster, but dependent on template)
qm clone 900 101 --name web-server-01
Step 14: Configure Cloud-Init Settings
After cloning, configure the instance-specific settings via cloud-init.
Using Proxmox Web UI:
- Select the newly cloned VM (e.g., VM 101)
- Go to Hardware → CloudInit Drive
- Click “Edit” to configure:
- User:
admin(username for SSH login) - Password: Set a password (or leave blank to use SSH keys only)
- DNS domain:
example.local(optional) - DNS servers:
8.8.8.8 8.8.4.4(or your preferred DNS) - SSH public key: Paste your public SSH key for password-less login
- IP Config (net0):
- IPv4:
192.168.1.100/24(static IP) - Gateway:
192.168.1.1 - OR select DHCP for automatic IP assignment
- IPv4:
- User:
- Click OK to save
Important: Any changes to cloud-init settings require the VM to be powered off first.
Using Proxmox CLI:
# Configure basic settings
qm set 101 --ciuser admin --cipassword SecurePassword123
# Configure static IP networking
qm set 101 --ipconfig0 ip=192.168.1.100/24,gw=192.168.1.1
# Configure DNS
qm set 101 --nameserver 8.8.8.8 --searchdomain example.local
# Add SSH public key (recommended over passwords)
qm set 101 --sshkeys /root/.ssh/authorized_keys
# Or specify inline:
# qm set 101 --sshkeys "ssh-rsa AAAAB3NzaC1yc2EA... user@host"
Example realistic configuration:
# Web server with static IP
qm set 101 \
--ciuser admin \
--cipassword MySecurePass123 \
--ipconfig0 ip=192.168.1.100/24,gw=192.168.1.1 \
--nameserver 8.8.8.8 \
--searchdomain mycompany.local \
--sshkeys "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC7H... admin@workstation"
Step 15: Start the Cloned VM
Start the new VM and let cloud-init apply the configuration:
qm start 101
First boot process:
- VM boots from the OS disk
- Cloud-init detects this is the first boot
- Cloud-init reads configuration from the CloudInit drive
- Cloud-init applies user, network, and SSH settings
- VM is ready for use (usually within 30-60 seconds)
Part 6: Verify and Test
Step 16: Verify Cloud-Init Worked
Check VM IP address:
- In Proxmox UI, look at the VM’s Summary tab
- The IP address should match what you configured
- Qemu guest agent must be running for IP to display
SSH into the VM:
If you configured SSH keys, you should log in without a password.
Check cloud-init logs:
sudo tail -f /var/log/cloud-init-output.logLook for:
Cloud-init v. 24.1.3-0ubuntu1 finished at <timestamp>. Datasource DataSourceNoCloudVerify networking:
ip addr show hostnameShould show your configured IP address and hostname.
Check cloud-init status:
sudo cloud-init statusExpected output:
status: done
Troubleshooting
Issue: VM has no network connectivity
Causes:
- Cloud-init network configuration didn’t apply
- Incorrect gateway or netmask
- Bridge configuration issue in Proxmox
Solutions:
- Check cloud-init logs:
sudo cat /var/log/cloud-init.log - Verify IP config in Proxmox CloudInit settings
- Try rebooting the VM:
qm reboot 101 - Check Proxmox network bridge is up:
ip link show vmbr0
Issue: Can’t SSH into VM (connection refused)
Causes:
- SSH keys not configured correctly
- Cloud-init user creation failed
- Firewall blocking port 22
Solutions:
- Use Proxmox console to log in directly
- Check if user exists:
cat /etc/passwd | grep admin - Verify SSH is running:
sudo systemctl status ssh - Check SSH configuration:
sudo sshd -T | grep -i permitroot - Review cloud-init user-data:
sudo cloud-init query userdata
Issue: Cloud-init doesn’t run on first boot
Causes:
- Cloud-init wasn’t cleaned before template conversion
- CloudInit drive not attached
- Datasource configuration missing
Solutions:
- Verify CloudInit drive exists: Check VM Hardware tab for
ide2 - Check datasource config exists:
cat /etc/cloud/cloud.cfg.d/99_pve.cfg - Re-clean cloud-init (if still mutable):
sudo cloud-init clean --logs --reboot
Issue: Changes to cloud-init settings don’t apply
Cause: Cloud-init only runs on first boot. Subsequent boots skip cloud-init unless you manually trigger it.
Solutions:
Force cloud-init to run again:
sudo cloud-init clean sudo rebootFor new changes: Shut down VM, modify cloud-init settings in Proxmox, then start VM
Advanced Configuration
Using Custom Cloud-Init User-Data
For more advanced configurations (installing packages, running scripts), you can provide custom user-data:
Create a user-data file:
#cloud-config package_update: true package_upgrade: true packages: - docker.io - git - htop runcmd: - systemctl enable docker - usermod -aG docker adminSave as
user-data.yamlApply to VM:
qm set 101 --cicustom "user=local:snippets/user-data.yaml"
Note: This requires the snippets directory to be configured in Proxmox storage.
Next Steps
Now that you have a working cloud-init template, you can:
Automate VM creation with Terraform:
- Use the Proxmox Terraform provider
- Define infrastructure as code
- Deploy entire environments automatically
Integrate with Ansible:
- Use cloud-init to bootstrap Ansible connectivity
- Automate post-deployment configuration
- Manage fleet of VMs
Create multiple templates:
- Ubuntu 20.04, 22.04, and 24.04 variants
- Different server roles (web, database, etc.)
- Pre-configured software stacks
Explore cloud images:
- Download official Ubuntu cloud images
- Import directly without OS installation
- Faster template creation
Best Practices
Template Management:
- Use high VM IDs (900+) to separate templates from regular VMs
- Document template versions and creation dates
- Regularly update templates with security patches
- Test template changes on clones before converting to template
Security:
- Always use SSH keys instead of passwords
- Disable password authentication in SSH config
- Keep cloud-init and qemu-agent updated
- Review cloud-init logs after first boot
Networking:
- Use static IPs for production servers
- Use DHCP for development/test environments
- Document IP allocation to avoid conflicts
- Configure proper DNS for hostname resolution
Related Guides
- How to resize VM disks in Proxmox
- Automating Proxmox VM deployments with Terraform
- Setting up Kubernetes clusters with cloud-init templates
- Proxmox networking best practices
Last updated: December 2024