DEV Community

Kjetil Furås
Kjetil Furås

Posted on • Originally published at kjetilfuras.com

Provision Ubuntu VMs with NoCloud on Proxmox

Creatingrepeatable and secure VM templatesin 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 checkUbuntu Cloud Images.

Step 1: Download the Ubuntu Cloud Image

From yourProxmox 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
Enter fullscreen mode Exit fullscreen mode
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
Enter fullscreen mode Exit fullscreen mode

Then verify:

ls /var/lib/vz/template/iso/ | grep -i ubuntu-
Enter fullscreen mode Exit fullscreen mode
ls /var/lib/vz/template/iso/ | grep -i ubuntu-
Enter fullscreen mode Exit fullscreen mode

You should see theubuntu-24.04-server-cloudimg-amd64.imgfile listed.

ubuntu-24.04-server-cloudimg-amd64.img
Enter fullscreen mode Exit fullscreen mode

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 ID501, but you can choose any unused ID.

501
Enter fullscreen mode Exit fullscreen mode
qm create 501 \
  --name ubuntu-cloud-init-template \
  --memory 2048 \
  --cores 2 \
  --net0 virtio,bridge=vmbr0
Enter fullscreen mode Exit fullscreen mode
qm create 501 \
  --name ubuntu-cloud-init-template \
  --memory 2048 \
  --cores 2 \
  --net0 virtio,bridge=vmbr0
Enter fullscreen mode Exit fullscreen mode

2.2 Import the disk

Next, import the Ubuntu cloud image as a virtual disk into your Proxmox storage (in this case,local-zfs).

local-zfs
Enter fullscreen mode Exit fullscreen mode
qm importdisk 501 /var/lib/vz/template/iso/ubuntu-24.04-server-cloudimg-amd64.img local-zfs
Enter fullscreen mode Exit fullscreen mode
qm importdisk 501 /var/lib/vz/template/iso/ubuntu-24.04-server-cloudimg-amd64.img local-zfs
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode
qm set 501 \
  --scsihw virtio-scsi-pci \
  --scsi0 local-zfs:vm-501-disk-0 \
  --boot c \
  --bootdisk scsi0
Enter fullscreen mode Exit fullscreen mode

2.4 Attach Cloud-init disk

qm set 501 --ide2 local-zfs:cloudinit
Enter fullscreen mode Exit fullscreen mode
qm set 501 --ide2 local-zfs:cloudinit
Enter fullscreen mode Exit fullscreen mode

2.5 Enable the qemu-guest-agent

qm set 501 --agent enabled=1
Enter fullscreen mode Exit fullscreen mode
qm set 501 --agent enabled=1
Enter fullscreen mode Exit fullscreen mode

Step 3: Generate SSH Keys & NoCloud ISO

I’ll generate thessh-keysfrom myMac, but any admin workstation will do.

ssh-keys
Enter fullscreen mode Exit fullscreen mode

3.1 Generate a dedicated SSH key

ssh-keygen -t ed25519 -C "ubuntu-template" -f ~/.ssh/id_ed25519_ubuntu_template
Enter fullscreen mode Exit fullscreen mode
ssh-keygen -t ed25519 -C "ubuntu-template" -f ~/.ssh/id_ed25519_ubuntu_template
Enter fullscreen mode Exit fullscreen mode

This creates:

  • ~/.ssh/id_ed25519_ubuntu_template
~/.ssh/id_ed25519_ubuntu_template
Enter fullscreen mode Exit fullscreen mode
  • ~/.ssh/id_ed25519_ubuntu_template.pub
~/.ssh/id_ed25519_ubuntu_template.pub
Enter fullscreen mode Exit fullscreen mode

3.2 Copy the public key

pbcopy < ~/.ssh/id_ed25519_ubuntu_template.pub
Enter fullscreen mode Exit fullscreen mode
pbcopy < ~/.ssh/id_ed25519_ubuntu_template.pub
Enter fullscreen mode Exit fullscreen mode

3.3 Createuser-dataandmeta-data(cloud-init)

user-data
Enter fullscreen mode Exit fullscreen mode
meta-data
Enter fullscreen mode Exit fullscreen mode

I’ll create the cloud-init configuration files that tell the VM how to initialize on first boot—things like hostname, users, and packages. Theuser-datafile contains most of the logic, whilemeta-datajust defines identity info for the instance.

user-data
Enter fullscreen mode Exit fullscreen mode
meta-data
Enter fullscreen mode Exit fullscreen mode
mkdir -p /root/cloudinit/ubuntu-template
cd /root/cloudinit/ubuntu-template
Enter fullscreen mode Exit fullscreen mode
mkdir -p /root/cloudinit/ubuntu-template
cd /root/cloudinit/ubuntu-template
Enter fullscreen mode Exit fullscreen mode

Create the following files:user-data

user-data
Enter fullscreen mode Exit fullscreen mode
#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
Enter fullscreen mode Exit fullscreen mode
#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
Enter fullscreen mode Exit fullscreen mode

meta-data

meta-data
Enter fullscreen mode Exit fullscreen mode
instance-id: ubuntu-template
local-hostname: ubuntu-template
Enter fullscreen mode Exit fullscreen mode
instance-id: ubuntu-template
local-hostname: ubuntu-template
Enter fullscreen mode Exit fullscreen mode

3.4 Generate the ISO (on Proxmox)

Make sure you havecloud-image-utilsinstalled:

cloud-image-utils
Enter fullscreen mode Exit fullscreen mode
apt update
apt install cloud-image-utils
Enter fullscreen mode Exit fullscreen mode
apt update
apt install cloud-image-utils
Enter fullscreen mode Exit fullscreen mode

This gives you access to thecloud-localdscommand you need.

This gives you access to thecloud-localdscommand you need.

cloud-localds
Enter fullscreen mode Exit fullscreen mode

Then, generate the iso:

cloud-localds nocloud.iso user-data meta-data
Enter fullscreen mode Exit fullscreen mode
cloud-localds nocloud.iso user-data meta-data
Enter fullscreen mode Exit fullscreen mode

3.5 Move ISO to/var/lib/vz/template/iso/

/var/lib/vz/template/iso/
Enter fullscreen mode Exit fullscreen mode
mv nocloud.iso /var/lib/vz/template/iso/
Enter fullscreen mode Exit fullscreen mode
mv nocloud.iso /var/lib/vz/template/iso/
Enter fullscreen mode Exit fullscreen mode

If your Proxmox storage useslocal-lvminstead oflocal-zfs, adjust the path accordingly.You can check available storage with:pvesm status

If your Proxmox storage useslocal-lvminstead oflocal-zfs, adjust the path accordingly.You can check available storage with:pvesm status

local-lvm
Enter fullscreen mode Exit fullscreen mode
local-zfs
Enter fullscreen mode Exit fullscreen mode
pvesm status
Enter fullscreen mode Exit fullscreen mode

3.6 Attach ISO to VM

qm set 501 --ide2 local:iso/nocloud.iso,media=cdrom
Enter fullscreen mode Exit fullscreen mode
qm set 501 --ide2 local:iso/nocloud.iso,media=cdrom
Enter fullscreen mode Exit fullscreen mode

Replacelocalif your ISO storage is named differently — usepvesm statusto check.

Replacelocalif your ISO storage is named differently — usepvesm statusto check.

local
Enter fullscreen mode Exit fullscreen mode
pvesm status
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode
qm template 501
Enter fullscreen mode Exit fullscreen mode

Step 5: Clone and Deploy

5.1 Clone the template

qm clone 501 105 --name "ubuntu-vm01"
Enter fullscreen mode Exit fullscreen mode
qm clone 501 105 --name "ubuntu-vm01"
Enter fullscreen mode Exit fullscreen mode

5.2 Customize the new VM

qm set 105 --memory 4096 --cores 4
Enter fullscreen mode Exit fullscreen mode
qm set 105 --memory 4096 --cores 4
Enter fullscreen mode Exit fullscreen mode

5.3 Start up the VM

qm start 105
Enter fullscreen mode Exit fullscreen mode
qm start 105
Enter fullscreen mode Exit fullscreen mode

Remember to update the new IP address of the server in your~/.ssh/configfile, as shown below.

Remember to update the new IP address of the server in your~/.ssh/configfile, as shown below.

~/.ssh/config
Enter fullscreen mode Exit fullscreen mode

~/.ssh/config

~/.ssh/config
Enter fullscreen mode Exit fullscreen mode
Host ubuntu
  HostName 10.160.0.64
  User ubuntu
  IdentityFile ~/.ssh/id_ed25519_ubuntu_template
Enter fullscreen mode Exit fullscreen mode
Host ubuntu
  HostName 10.160.0.64
  User ubuntu
  IdentityFile ~/.ssh/id_ed25519_ubuntu_template
Enter fullscreen mode Exit fullscreen mode

Now you can typessh ubuntuto connect to your newly created VM.

ssh ubuntu
Enter fullscreen mode Exit fullscreen mode

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 moretech tutorialsor follow myGitHub, where I share homelab setups, automation tools, and real-world projects from my day-to-day work as an IT consultant.

Originally published at https://kjetilfuras.com/provision-ubuntu-vms-with-nocloud-on-proxmox/

Top comments (0)