Create a cloud init vm using API only

Zernox

New Member
Jan 8, 2026
3
0
1
Hello there.
I am attempting to create a vm or rather vm template using the proxmox api via proxmoxxer.
But I run into multiple issues.
1. Creating a template does not work at all via api or rather creating a bootable vm with cloudinit
2. Cloud init it self from template does not work using api. (it creates a vm from the template but cloud init does not set password, ip nor any other param)

Here is how I create (or attempt to) the vm. Anyone notice an issue? I oriented myself at the help article of proxmox and clone it to api calls.
Python:
def _create_cloud_init_vm(
        proxmox: ProxmoxInterface,
        node: str,
        vmid: int,
        order: dict[str, Any],
        image: dict[str, Any],
        storage_name: str,
) -> str:
        #STORAGE:import/TEST-noble-server-cloudimg-amd64.img.raw
        image_path = image.get("imagepath")
        
        public_key, private_key_path = _generate_ssh_key_pair(
            vmid=vmid,
            system_name=order["systemName"],
        )

        connection = proxmox.connection
        vm_created = False

        try:
            # Create the VM and Cloud-Init drive
            task = connection.nodes(node).qemu.create(
                vmid=vmid,
                name=order["systemName"],
                cores=int(order["cpu"]),
                memory=int(order["ram"]) * 1024,
                cpu="x86-64-v2-AES",
                net0=_build_vm_network(order),
                agent="enabled=1",
                ostype="l26",
                description=genereate_documentation(order),
                tags=_build_tags(order),
            )
            _wait_for_task(connection, node, task)
            vm_created = True
            connection.nodes(node).qemu(vmid).config.put(
                scsihw="virtio-scsi-single",
                scsi0=(
                    f"{storage_name}:0,"
                    f"import-from={image_path},"
                    "discard=on,"
                    "ssd=1,"
                    "iothread=1"
                ),
            )

            # PUT /nodes/{node}/qemu/{vmid}/resize
            task = connection.nodes(node).qemu(vmid).resize.put(
                disk="scsi0",
                size=f"{int(order['storage'])}G",
            )
            if task:
                _wait_for_task(connection, node, task)

            # PUT /nodes/{node}/qemu/{vmid}/config
            connection.nodes(node).qemu(vmid).config.put(
                ide2=f"{storage_name}:cloudinit",
                boot="order=scsi0",
                tablet=0,
                localtime=0,
                sshkeys=quote(public_key.strip(), safe=""),
                ipconfig0="ip=dhcp",
            )


            # Start the VM
            task = connection.nodes(node).qemu(vmid).status.start.post()
            if task:
                _wait_for_task(connection, node, task)

            return private_key_path

        except Exception:
            # Remove the incomplete VM
            if vm_created:
                try:
                    task = connection.nodes(node).qemu(vmid).delete(
                        purge=1,
                        destroy_unreferenced_disks=1,
                    )
                    if task:
                        _wait_for_task(connection, node, task)
                except Exception:
                    pass
            raise

The vm of this function seems to have cloud init and a drive with right size but bootloops. (no bootable media)
And when I create a vm from a template created like in the proxmox guide. It boots alright but no cloudinit function or setup is ran.
 
Hi,
could you share the resulting VM configurations for your attempts, i.e. qm config ID? Which image do you import from?
 
Hi @Zernox,
I am attempting to create a vm or rather vm template using the proxmox api via proxmoxxer.
Your post is confusing because you seem to jump between the VM and Template but the connection is not there.

For example, in your Proxmoxer config (btw this is a 3rd party tool and if you really have questions/issues with it - you should reach out to the authors): you are not setting template flag anywhere I can see.

You are mentioning that password is not set, yet there is no indication in your post where the password would be set. An ssh-key is added.

Is the file you are importing really a RAW file or is it QCOW? (qemu-img info [file]). Additionally, sometimes resize is not handled gracefully by certain kernels/images.

I would recommend that you pare down your configuration, remove resize, keep the calls to the minimum. There is very unlikely an error in PVE in this operation. Perhaps, skip the Proxmoxer - use pvesh to get the basic configuration working.


Blockbridge : Ultra low latency all-NVME shared storage for Proxmox - https://www.blockbridge.com/proxmox