Terraform
Technically I use OpenTofu (Terraform-compatible) to create VMs in Proxmox.
Install
sudo snap install --classic opentofu
tofu -v
Provider
There is a Proxmox provider which calls PVE API to create VMs in Proxmox. To set it up, I pass in auth credentials via encrypted files. My secrets page has more details about how to set up secrets and pass them to the provider.
I also create a custom module from the provider, to reuse common configurations.
Example module usage
module "nas_server" {
  source = "./modules/ubuntu-vm"
  hostname     = var.nas_hostname
  username     = var.username
  pve_node     = var.nas_pve_node
  ipv4_address = var.nas_ipv4_address
  ipv4_gateway = var.nas_ipv4_gateway
  startup_order = "1"
  cpu_cores = 4
  memory    = 4096
  disk_datastore_id = "datapool"
  disk_size         = 500
  # downloaded Ubuntu cloud image
  cloud_image_file_id = proxmox_virtual_environment_download_file.cloud_images[var.nas_pve_node].id
  # cloud-init files saved as snippets in PVE
  user_data_file_id   = proxmox_virtual_environment_file.nas_user_data.id
  meta_data_file_id   = proxmox_virtual_environment_file.nas_meta_data.id
}
Outputs
The process generates inventory.yml file
with the IP address of the created VMs.
This file will be used in my ansible process.
Deployment
# check the plan and confirm
tofu apply
States
Terraform keeps the state of the infrastructure
in the terraform.tfstate and terraform.tfstate.backup files.
It's a good practice to backup these files.
I lost these local files while moving the project folder around,
so I'm looking into remote state storage.
At least, the process of recreating VMs is painless with tofu apply.