Setting up a VM on TrueNAS Scale using cloud-init
How to use cloud-init under TrueNAS Scale to spin up preconfigured virtual machines.
1-Download a cloud-init image
https://cloud-images.ubuntu.com/releases/22.04/

Download the .img version of the latest cloud image.
2-Prepare the VM disk
Create the Zvol for the VM

Or from the command line:
zfs create -V 20G vms/cloud-init-test
Copy the cloud image into the Zvol
qemu-img convert -O raw /downloads/ISOs/ubuntu-22.04-server-cloudimg-amd64.img /dev/zvol/vms/cloud-init-test
3-Create the cloud-init seed image
Use a different system (or the same TrueNAS system if the cloud-image-utils package is installed).
Create the user-data.yaml file
#cloud-config
chpasswd:
list: |
ubuntu:12345
expire: False
hostname: cloud-init-test
ssh_authorized_keys:
- ssh-rsa AAAAB3Nza...
- ssh-rsa AAAAB3Nza...
Create cloud-init seed image
cloud-localds --verbose --vendor-data cloud-init-test-seed.qcow2 user-data.yaml
Copy the cloud-init seed image to TrueNAS
scp cloud-init-test-seed.qcow2 root@truenas:/mnt/vms/
4-Create the VM







Add cloud-init seed image as a CDROM
Set as order 1004 to avoid attempting to boot from the CDROM.



The same process of creating the VM and attaching the devices using the command line:
#!/bin/sh
# Create the VM
RESULT=`midclt call vm.create '{"name": "cloud_init_test", "cpu_mode": "HOST-MODEL", "bootloader": "UEFI_CSM", "threads": 2, "memory": 1024}'`
VM_ID=`echo ${RESULT} | jq '.id'`
# Add the display
midclt call vm.device.create '{"vm": '${VM_ID}', "dtype": "DISPLAY", "order": 1002, "attributes": {"web": true, "type": "VNC", "bind": "0.0.0.0", "wait": false}}'
# Obtain a random MAC address
MAC_ADDRESS=`midclt call vm.random_mac`
# Add the NIC
midclt call vm.device.create '{"vm": '${VM_ID}', "dtype": "NIC", "order": 1003, "attributes": {"type": "VIRTIO", "nic_attach": "br0", "mac": "'${MAC_ADDRESS}'"}}'
# Add the disk
midclt call vm.device.create '{"vm": '${VM_ID}', "dtype": "DISK", "order": 1001, "attributes": {"path": "/dev/zvol/vms/cloud-init-test","type": "VIRTIO"}}'
# Add the CDROM
midclt call vm.device.create '{"vm": '${VM_ID}', "dtype": "CDROM", "order": 1004, "attributes": {"path":"/mnt/vms/cloud-init-test-seed.qcow2"}}'
5-Start VM

Or using the command line:
midclt call vm.start '{"vm": '${VM_ID}'}'