Provision Ubuntu VMs with NoCloud on Proxmox
Creating repeatable and secure VM templates in Proxmox has been a game-changer in refining and scaling my homelab environment.
In this post, I’ll show you how to:
- Use the NoCloud datasource with Ubuntu Cloud Images
- Inject SSH keys from your admin box
- Enable and verify the Proxmox guest agent
- Clone pre-configured VMs using Proxmox CLI
Let’s walk through the whole process—from image preparation to SSH-ready VM deployment.
For the latest Ubuntu Cloud images, you can check Ubuntu Cloud Images.
Step 1: Download the Ubuntu Cloud Image
From your Proxmox server, download the latest Ubuntu 24.04 cloud image:
wget -P /var/lib/vz/template/iso/ \
https://cloud-images.ubuntu.com/daily/server/releases/24.04/release/ubuntu-24.04-server-cloudimg-amd64.img
Then verify:
ls /var/lib/vz/template/iso/ | grep -i ubuntu-
You should see the ubuntu-24.04-server-cloudimg-amd64.img
file listed.
Step 2: Create a Base VM Template
2.1 Create the VM
First, create the base VM that will serve as your Ubuntu template. We’re using ID 501
, but you can choose any unused ID.
qm create 501 \
--name ubuntu-cloud-init-template \
--memory 2048 \
--cores 2 \
--net0 virtio,bridge=vmbr0
2.2 Import the disk
Next, import the Ubuntu cloud image as a virtual disk into your Proxmox storage (in this case, local-zfs
).
qm importdisk 501 /var/lib/vz/template/iso/ubuntu-24.04-server-cloudimg-amd64.img local-zfs
2.3 Set the VM disk and boot options
qm set 501 \
--scsihw virtio-scsi-pci \
--scsi0 local-zfs:vm-501-disk-0 \
--boot c \
--bootdisk scsi0
2.4 Attach Cloud-init disk
qm set 501 --ide2 local-zfs:cloudinit
2.5 Enable the qemu-guest-agent
qm set 501 --agent enabled=1
Step 3: Generate SSH Keys & NoCloud ISO
I’ll generate the ssh-keys
from my Mac, but any admin workstation will do.
3.1 Generate a dedicated SSH key
ssh-keygen -t ed25519 -C "ubuntu-template" -f ~/.ssh/id_ed25519_ubuntu_template
This creates:
~/.ssh/id_ed25519_ubuntu_template
~/.ssh/id_ed25519_ubuntu_template.pub
3.2 Copy the public key
pbcopy < ~/.ssh/id_ed25519_ubuntu_template.pub
3.3 Create user-data
and meta-data
(cloud-init)
I’ll create the cloud-init configuration files that tell the VM how to initialize on first boot—things like hostname, users, and packages. The user-data
file contains most of the logic, while meta-data
just defines identity info for the instance.
mkdir -p /root/cloudinit/ubuntu-template
cd /root/cloudinit/ubuntu-template
Create the following files:user-data
#cloud-config
hostname: ubuntu-template
users:
- name: ubuntu
ssh-authorized-keys:
- paste_the_public_key_you_copied_earlier
sudo: ALL=(ALL) NOPASSWD:ALL
shell: /bin/bash
package_update: true
package_upgrade: true
packages:
- qemu-guest-agent
runcmd:
- systemctl enable qemu-guest-agent
- systemctl start qemu-guest-agent
meta-data
instance-id: ubuntu-template
local-hostname: ubuntu-template
3.4 Generate the ISO (on Proxmox)
Make sure you have cloud-image-utils
installed:
apt update
apt install cloud-image-utils
This gives you access to the
cloud-localds
command you need.
Then, generate the iso:
cloud-localds nocloud.iso user-data meta-data
3.5 Move ISO to /var/lib/vz/template/iso/
mv nocloud.iso /var/lib/vz/template/iso/
If your Proxmox storage uses
local-lvm
instead oflocal-zfs
, adjust the path accordingly.
You can check available storage with:pvesm status
3.6 Attach ISO to VM
qm set 501 --ide2 local:iso/nocloud.iso,media=cdrom
Replace
local
if your ISO storage is named differently — usepvesm status
to check.
Step 4: Convert to a Template
Once your base VM is configured, convert it to a Proxmox template so you can quickly clone new VMs from it.
qm template 501
Step 5: Clone and Deploy
5.1 Clone the template
qm clone 501 105 --name "ubuntu-vm01"
5.2 Customize the new VM
qm set 105 --memory 4096 --cores 4
5.3 Start up the VM
qm start 105

Remember to update the new IP address of the server in your
~/.ssh/config
file, as shown below.
~/.ssh/config
Host ubuntu
HostName 10.160.0.64
User ubuntu
IdentityFile ~/.ssh/id_ed25519_ubuntu_template
Now you can type ssh ubuntu
to connect to your newly created VM.

I use this setup regularly when provisioning dev servers or test environments—it saves a ton of time.
You now have a clean and SSH-ready NoCloud Ubuntu template:
- Ideal for hands-off provisioning
- Cloud-init friendly
- Guest agent enabled out of the box
Found this helpful? Check out more tech tutorials or follow my GitHub, where I share homelab setups, automation tools, and real-world projects from my day-to-day work as an IT consultant.