<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: widely</title>
    <description>The latest articles on DEV Community by widely (@widely).</description>
    <link>https://dev.to/widely</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3980762%2Ff6206343-d385-46a3-9769-85a1f1fb911a.png</url>
      <title>DEV Community: widely</title>
      <link>https://dev.to/widely</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/widely"/>
    <language>en</language>
    <item>
      <title>Automating Proxmox Virtual Machine Deployment Using Terraform and Cloud-Init Templates</title>
      <dc:creator>widely</dc:creator>
      <pubDate>Fri, 12 Jun 2026 08:55:24 +0000</pubDate>
      <link>https://dev.to/widely/automating-proxmox-virtual-machine-deployment-using-terraform-and-cloud-init-templates-2p19</link>
      <guid>https://dev.to/widely/automating-proxmox-virtual-machine-deployment-using-terraform-and-cloud-init-templates-2p19</guid>
      <description>&lt;p&gt;The Problem:&amp;nbsp;I had been manually creating Ubuntu Virtual Machines within my Proxmox Home Lab. This included looking through the UI, uploading the Cloud Image, re-typing the same SSH keys multiple times, etc. The process was time consuming, and prone to human error and it was impossible to automate or replicate. Each Virtual Machine I created was a "15-minute job".&lt;/p&gt;

&lt;p&gt;The Constraints:&amp;nbsp;My goal was to create an entirely Infrastructure as Code-based workflow that would have no dependency upon PXE boot or any large orchestration tools. Only one node on my Proxmox was to be used, and I wanted each VM to be fully configured (hostname, user, sshkey and packages) upon their initial start; I also wanted to configure the VMs without ever having to log into the console.&lt;/p&gt;

&lt;p&gt;The Solution:&amp;nbsp;I am using Terraform with the Telmate Proxmox provider, in addition to cloud-init templates. Once I create my template, I can create a fully functioning VM in under a minute. Within this guide, I will describe the exact configurations I have used, the mistakes that I made which resulted in losing many hours of my time, and the checks I have established to ensure that a similar situation does not happen again.&lt;/p&gt;

&lt;p&gt;Quick Summary&lt;br&gt;
Provision Ubuntu 22.04 Cloud-Init VMs on Proxmox VE v8.2.&lt;br&gt;
Use a dedicated API Token with minimum privileges assigned — Not ROOT.&lt;br&gt;
Attach a Cloud-Init ISO to the&amp;nbsp;ide2, rather than a SCSI slot; otherwise, your Clone will fail without warning.&lt;br&gt;
Pin your providers to specific versions and use variables so you can spawn many VMs off a single Root Module.&lt;/p&gt;

&lt;p&gt;Tested On: Proxmox VE v8.2 (kernel 6.8.12-2-pve), Terraform v1.8.4, Ubuntu 22.04 LTS Cloud Image. Everything outlined in this document was tested in my single-node Homelab using Local Disk Storage.&lt;/p&gt;

&lt;p&gt;In order to allow Terraform to interact with your Proxmox virtual machines you must prepare four items prior to beginning: a clean cloud-init template; a Proxmox API token with restricted permissions; selecting where to store and how to track your resource state; and setting the pinned versions for your Terraform templates.&lt;/p&gt;

&lt;p&gt;Prerequisites &amp;amp; Planning&lt;br&gt;
Prepare the Proxmox Template Clone&lt;/p&gt;

&lt;p&gt;To create your Ubuntu cloud image template follow these steps: Download the Ubuntu Cloud Image from the official website and run it on a new tiny virtual machine. An agent must be installed in the virtual machine so that Terraform can receive the IP address via cloud-init and continue executing the command successfully.&amp;nbsp;Do not modify the template or configuration of the image without creating a backup!&lt;/p&gt;

&lt;h1&gt;
  
  
  If you already have a VM you’re turning into a template, clone it first
&lt;/h1&gt;

&lt;p&gt;qm clone 9000 9999 --name backup-before-template --full&lt;/p&gt;

&lt;p&gt;You may want to keep a second shell session open on your Proxmox host while executing commands for backup and recovery.&lt;/p&gt;

&lt;p&gt;Download the image and import it into a new virtual machine.&lt;br&gt;
wget &lt;a href="https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img" rel="noopener noreferrer"&gt;https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img&lt;/a&gt;&lt;br&gt;
qm create 9000 --name ubuntu-2204-cloudinit-template --memory 2048 --cores 2 --net0 virtio,bridge=vmbr0&lt;br&gt;
qm importdisk 9000 jammy-server-cloudimg-amd64.img local-lvm&lt;br&gt;
qm set 9000 --scsihw virtio-scsi-single --scsi0 local-lvm:vm-9000-disk-0&lt;br&gt;
qm set 9000 --ide2 local-lvm:cloudinit&lt;br&gt;
qm set 9000 --boot c --bootdisk scsi0&lt;br&gt;
qm set 9000 --serial0 socket --vga serial0&lt;br&gt;
qm set 9000 --agent enabled=1&lt;br&gt;
Boot the virtual machine once, install the agent, and power off.&lt;br&gt;
qm start 9000&lt;/p&gt;

&lt;h1&gt;
  
  
  Inside the VM:
&lt;/h1&gt;

&lt;p&gt;sudo apt update &amp;amp;&amp;amp; sudo apt install -y qemu-guest-agent&lt;br&gt;
sudo systemctl enable --now qemu-guest-agent&lt;br&gt;
sudo shutdown -h now&lt;br&gt;
Select the virtual machine and Convert to Template.&lt;br&gt;
qm template 9000&lt;br&gt;
Verify the virtual machine is set as a template.&lt;br&gt;
qm status 9000&lt;/p&gt;

&lt;h1&gt;
  
  
  Output: status: stopped (template)
&lt;/h1&gt;

&lt;p&gt;The&amp;nbsp;Proxmox VE Administration Guide on VM Templates and Clones&amp;nbsp;has instructions on how to complete these procedures with the appropriate configuration flags if you want to replicate exactly what I have done here.&lt;/p&gt;

&lt;p&gt;API Token and Permissions for the Proxmox Terraform Provider&lt;/p&gt;

&lt;p&gt;Never provide your Terraform instance with a root password. Configure your API token to be as restricted as possible. In the Proxmox web interface, go to&amp;nbsp;Datacenter&amp;nbsp;&amp;gt;&amp;nbsp;Permissions&amp;nbsp;&amp;gt;&amp;nbsp;API Tokens&amp;nbsp;and add a new token to a user that has the&amp;nbsp;PVEVMAdmin&amp;nbsp;permission role on that particular path (i.e.&amp;nbsp;/nodes/pve). Also grant&amp;nbsp;Sys.Audit&amp;nbsp;permission for&amp;nbsp;/; otherwise you will not be able to list any resources using the provider and will receive a 401 error. The path is case-sensitive;&amp;nbsp;PVEUser@realm!token&amp;nbsp;must match exactly.&lt;/p&gt;

&lt;p&gt;You will need to save the Token ID and Secret for later use; you will provide these values to Terraform by specifying them as environment variables or as part of the Provider Block.&lt;/p&gt;

&lt;p&gt;Version Pinning and Remote State Planning&lt;/p&gt;

&lt;p&gt;I keep my State files locally on my laptop for my homelab, but if you're sharing this configuration with anyone else, you should consider using an S3-compatible backend to store your State files. You should also hardpin your Provider to a specific version from the start, as the Telmate Provider has had Breaking Changes between each version 2.x release.&lt;/p&gt;

&lt;p&gt;Core Setup: Terraform Proxmox VM Provisioning Cloud-Init&lt;br&gt;
Bootstrapping the Proxmox Terraform Provider&lt;/p&gt;

&lt;p&gt;You need to create a&amp;nbsp;provider.tf&amp;nbsp;that looks similar to this:&lt;/p&gt;

&lt;p&gt;terraform {&lt;br&gt;
  required_version = "~&amp;gt; 1.8"&lt;br&gt;
  required_providers {&lt;br&gt;
    proxmox = {&lt;br&gt;
      source  = "Telmate/proxmox"&lt;br&gt;
      version = "2.9.14"&lt;br&gt;
    }&lt;br&gt;
  }&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;provider "proxmox" {&lt;br&gt;
  pm_api_url          = "&lt;a href="https://pve.example.com:8006/api2/json" rel="noopener noreferrer"&gt;https://pve.example.com:8006/api2/json&lt;/a&gt;"&lt;br&gt;
  pm_api_token_id     = var.proxmox_token_id&lt;br&gt;
  pm_api_token_secret = var.proxmox_token_secret&lt;br&gt;
  pm_tls_insecure     = true   # only for homelabs with self‑signed certs&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;This establishes the Provider and locks it to Version 2.9.14. Use the&amp;nbsp;Terraform Registry page for the Proxmox provider&amp;nbsp;as a point of reference whenever your Provider Versions begin to drift from Version 2.9.14.&lt;/p&gt;

&lt;p&gt;You can initialize your Provider and verify connectivity by using the following command:&lt;/p&gt;

&lt;p&gt;terraform init&lt;br&gt;
terraform plan&lt;br&gt;
Crafting the Terraform Proxmox QEMU Resource with Cloud-Init Drive&lt;/p&gt;

&lt;p&gt;Now let's look at the VM Resource. This is where you will determine whether your Cloud-Init drive mapping is functional or not. This code is placed in&amp;nbsp;main.tf:&lt;/p&gt;

&lt;p&gt;resource "proxmox_vm_qemu" "cloudinit_vm" {&lt;br&gt;
  name        = "lab-ubuntu-01"&lt;br&gt;
  target_node = "pve"&lt;br&gt;
  clone       = "ubuntu-2204-cloudinit-template"&lt;br&gt;
  full_clone  = false&lt;/p&gt;

&lt;p&gt;cores   = 2&lt;br&gt;
  memory  = 2048&lt;br&gt;
  sockets = 1&lt;/p&gt;

&lt;p&gt;scsihw = "virtio-scsi-single"&lt;/p&gt;

&lt;p&gt;disk {&lt;br&gt;
    type    = "scsi"&lt;br&gt;
    storage = "local-lvm"&lt;br&gt;
    size    = "20G"&lt;br&gt;
  }&lt;/p&gt;

&lt;p&gt;network {&lt;br&gt;
    model  = "virtio"&lt;br&gt;
    bridge = var.vm_network_bridge&lt;br&gt;
  }&lt;/p&gt;

&lt;p&gt;# Cloud‑init drive MUST be on ide2&lt;br&gt;
  cloudinit_cdrom_storage = "local-lvm"&lt;br&gt;
  os_type                 = "cloud-init"&lt;/p&gt;

&lt;p&gt;sshkeys = var.ssh_public_key&lt;br&gt;
  ciuser  = var.vm_user&lt;/p&gt;

&lt;p&gt;ipconfig0 = "ip=dhcp"&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;The first line of&amp;nbsp;cloudinit_cdrom_storage&amp;nbsp;tells Terraform to create a Cloud-Init ISO on the target storage and attach it to this&amp;nbsp;ide2. If you do not include this line, or you try to put a Cloud-Init drive in&amp;nbsp;scsi0, Terraform will still create a clone of your VM; however, the Cloud-Init data will be silently ignored. I will go into more detail about this point in the Pitfalls.&lt;/p&gt;

&lt;p&gt;You can read about why the Cloud-Init Drive must appear as a CD-ROM drive in the&amp;nbsp;cloud‑init NoCloud datasource reference. As specified, the NoCloud data source will require the following volume label:&amp;nbsp;cidata, using Proxmox to handle that for you.&lt;/p&gt;

&lt;p&gt;The following commands will help you run a plan so you know exactly what Terraform is going to do with all of your hardware, including the creation of the cloud-init drive from scratch.&lt;/p&gt;

&lt;p&gt;$ terraform plan&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;resource "proxmox_vm_qemu" "cloudinit_vm" {

&lt;ul&gt;
&lt;li&gt;name                         = "lab-ubuntu-01"&lt;/li&gt;
&lt;li&gt;target_node                  = "pve"&lt;/li&gt;
&lt;li&gt;clone                        = "ubuntu-2204-cloudinit-template"&lt;/li&gt;
&lt;li&gt;scsihw                       = "virtio-scsi-single"&lt;/li&gt;
&lt;li&gt;cloudinit_cdrom_storage      = "local-lvm"              &amp;lt;-- cloud‑init ISO created here&lt;/li&gt;
&lt;li&gt;ipconfig0                    = "ip=dhcp"&lt;/li&gt;
&lt;li&gt;sshkeys                      = (sensitive value)
...
}&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using the above commands, you will see that all of the entries listed above will be created by Terraform when you run the plan.&lt;/p&gt;

&lt;p&gt;Running and Verifying the Automated Deployment&lt;/p&gt;

&lt;p&gt;You should create a backup of the Proxmox node configuration before applying the configuration. At minimum, dump your running VM list with&amp;nbsp;qm list&amp;nbsp;so you have a record to revert to if the state gets tangled.&amp;nbsp;Also, you should have a second root shell open in the Proxmox host.&lt;/p&gt;

&lt;p&gt;To apply the configuration:&lt;/p&gt;

&lt;p&gt;$ terraform apply --auto-approve&lt;/p&gt;

&lt;p&gt;proxmox_vm_qemu.cloudinit_vm: Creating...&lt;br&gt;
proxmox_vm_qemu.cloudinit_vm: Still creating... [10s elapsed]&lt;br&gt;
proxmox_vm_qemu.cloudinit_vm: Creation complete after 15s [id=qemu/100]&lt;br&gt;
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.&lt;/p&gt;

&lt;p&gt;Outputs:&lt;br&gt;
vm_ip = 192.168.10.143 &amp;lt;-- that’s your new VM ready for SSH&lt;/p&gt;

&lt;p&gt;Once the stack has been applied, you will want to verify that cloud-init has finished running on the VM:&lt;/p&gt;

&lt;p&gt;ssh &lt;a href="mailto:ubuntu@192.168.10.143"&gt;ubuntu@192.168.10.143&lt;/a&gt; cloud-init status --wait&lt;/p&gt;

&lt;h1&gt;
  
  
  Output: status: done
&lt;/h1&gt;

&lt;p&gt;You can also verify that the guest agent is still working:&lt;/p&gt;

&lt;p&gt;ssh &lt;a href="mailto:ubuntu@192.168.10.143"&gt;ubuntu@192.168.10.143&lt;/a&gt; systemctl is-active qemu-guest-agent&lt;/p&gt;

&lt;h1&gt;
  
  
  Output: active
&lt;/h1&gt;

&lt;p&gt;If cloud-init does not have a successful run,&amp;nbsp;status: not run&amp;nbsp;will be displayed during deployment and you will not be able to use SSH keys to log in. That is the best time to follow the troubleshooting guide below.&lt;/p&gt;

&lt;p&gt;Optimization and Best Practices&lt;br&gt;
Using Terraform Proxmox Variables for Reusable Stacks&lt;/p&gt;

&lt;p&gt;Instead of hard-coding tunable values such as VM specifications, template names, network bridges, SSH keys, and users in your root module, create a folder containing all of the variable files for each of your different environments and use those files as your input files. Example:&lt;/p&gt;

&lt;p&gt;variable "vm_count" { default = 1 }&lt;br&gt;
variable "vm_name_prefix" { default = "lab-ubuntu" }&lt;br&gt;
variable "template_name" { default = "ubuntu-2204-cloudinit-template" }&lt;br&gt;
variable "vm_network_bridge" { default = "vmbr0" }&lt;br&gt;
variable "vm_user" { default = "ubuntu" }&lt;br&gt;
variable "ssh_public_key" { sensitive = true }&lt;/p&gt;

&lt;p&gt;To create the same VM on all environments, you can use the variable file loaded into a resource block, which allows you to make one change to the template name in your variable file and automatically update every VM in that environment.&lt;/p&gt;

&lt;p&gt;Pin Provider Versions and Avoid Drift&lt;/p&gt;

&lt;p&gt;Hash the provider binary with&amp;nbsp;terraform init&amp;nbsp;and commit the&amp;nbsp;.terraform.lock.hcl&amp;nbsp;file. When you upgrade, always run&amp;nbsp;terraform init -upgrade&amp;nbsp;in a branch, then&amp;nbsp;plan, and diff the lock file. State locking matters even for local state — if you ever move to a remote backend, enable DynamoDB‑style locking immediately.&lt;/p&gt;

&lt;p&gt;Real‑World Pitfalls and Debugging&lt;br&gt;
What Didn’t Work For Me&lt;/p&gt;

&lt;p&gt;The first&amp;nbsp;terraform apply&amp;nbsp;I created timed out saying that "vm is locked (clone)... no cloud-initialization disk found." I completed the clone, but my VM failed to get the user-data when I connected to it using SSH with the default password (which I never set). I found a completely blank&amp;nbsp;/var/lib/cloud/instance.&lt;/p&gt;

&lt;p&gt;I grabbed the configuration for the VM on the Hypervisor:&lt;/p&gt;

&lt;p&gt;qm config 100 | grep ide&lt;/p&gt;

&lt;h1&gt;
  
  
  Only showed an empty ide2 entry — no ISO attached.
&lt;/h1&gt;

&lt;p&gt;I set&amp;nbsp;disk { type = "scsi" storage = "local-lvm" size = "10G" }, but then I misread the schema and added&amp;nbsp;disk&amp;nbsp;again as&amp;nbsp;type = "scsi"&amp;nbsp;for cloud-init. The provider created an SCSI raw disk for me, but cloud-init needs to see a CD-ROM device in&amp;nbsp;ide2. The answer to this problem was to delete the&amp;nbsp;disk&amp;nbsp;block for the extra raw disk and use&amp;nbsp;cloudinit_cdrom_storage = "local-lvm". After doing that,&amp;nbsp;terraform taint&amp;nbsp;and&amp;nbsp;apply&amp;nbsp;reinstantiated the VM, and the drive was instantly visible. I soon verified with a&amp;nbsp;qm config 100 | grep ide2&amp;nbsp;that&amp;nbsp;ide2: local-lvm:vm-100-cloudinit,media=cdrom&amp;nbsp;was now mounted. That’s when I tattooed “Cloud-Init ISO” on ide2 in my memory.&lt;/p&gt;

&lt;p&gt;Debugging a Stalled Cloud-Init: NoCloud Datasource Mismatch&lt;/p&gt;

&lt;p&gt;Even if the ISO attaches correctly, cloud-init sometimes ignores it completely, and the reason was due to the datasource within the template. While Ubuntu Cloud images typically include&amp;nbsp;DataSourceNone&amp;nbsp;as a backup boot, in cases where a pre‑seeded template contains only the instance of&amp;nbsp;OpenStack&amp;nbsp;for&amp;nbsp;datasource_list, the NoCloud storage (drive) will not be consulted.&lt;/p&gt;

&lt;p&gt;This can be verified by accessing the VM.&lt;/p&gt;

&lt;p&gt;grep -r datasource_list /etc/cloud/cloud.cfg*&lt;/p&gt;

&lt;p&gt;If the only materials visible are those referenced in&amp;nbsp;[ OpenStack ], Cloud-Init will avoid utilizing the CD-ROM drive for booting. Two solutions to this problem include modifying the template to remove the restriction prior to conversion, or inserting a&amp;nbsp;user-data&amp;nbsp;into the image that will supersede the image provided in the original instance.&lt;/p&gt;

&lt;h1&gt;
  
  
  cloud-config
&lt;/h1&gt;

&lt;p&gt;datasource_list: [ NoCloud, None ]&lt;/p&gt;

&lt;p&gt;With the template updated to reference the IDE drive, all deployments worked successfully on the first attempt.&lt;/p&gt;

&lt;p&gt;Common Mistakes and Edge Cases&lt;br&gt;
Ignoring the Cloud-Init Template Example With the Wrong SCSI Controller&lt;/p&gt;

&lt;p&gt;If the original template used the Stock LSI SCSI controller instead of&amp;nbsp;virtio-scsi-single, Cloud-Init may not be able to mount the Cloud-init Volume if the kernel does not recognize the Device (i.e. The SCSI Controller). Always confirm that you are using&amp;nbsp;virtio-scsi-single&amp;nbsp;to build the template, and ensure that the Terraform resource is referenced in the same way. A mismatch in the Template and Clone VM is likely to result in an erratic boot process or boot hang.&lt;/p&gt;

&lt;p&gt;Home Lab Infrastructure as Code: Network Bridge Mismatch in Terraform Variables&lt;/p&gt;

&lt;p&gt;My Terraform Configuration referenced&amp;nbsp;vmbr0&amp;nbsp;however, My Proxmox Host had been configured to use&amp;nbsp;vmbr1&amp;nbsp;as its Lab Network. As a result, the VM booted without an IP Address, leading to me blaming DHCP for about 10 minutes. To find your actual bridge name, go to the Proxmox web UI and click on&amp;nbsp;Datacenter&amp;nbsp;&amp;gt;&amp;nbsp;pve&amp;nbsp;&amp;gt;&amp;nbsp;System&amp;nbsp;&amp;gt;&amp;nbsp;Network, and then check the&amp;nbsp;Name&amp;nbsp;column for the information you need. Use that bridge name as a string to populate a variable, rather than hardcoding the value. If you change the location of your physical NICs in the future, this allows you to easily update the bridge name without having to edit your entire Terraform config file.&lt;/p&gt;

&lt;p&gt;Terraform Proxmox Cloud‑Init Drive Not Attached After Clone&lt;/p&gt;

&lt;h1&gt;
  
  
  Terraform Proxmox Cloud‑Init Drive Not Attached After Clone
&lt;/h1&gt;

&lt;p&gt;If you are cloning a disk image of a template where the disk image type is &lt;code&gt;raw&lt;/code&gt; and you clone it to a storage location that can only accept &lt;code&gt;qcow2&lt;/code&gt;, you will successfully clone the disk, but the cloud‑init ISO creation process may fail silently because the provider cannot determine how much space is available to allocate the cloudinit ISO.&lt;/p&gt;

&lt;p&gt;Always use &lt;code&gt;raw&lt;/code&gt; as your disk image type for the template and use a backend storage location that accepts that disk image type. For step-by-step documentation, production playbooks, and platform configurations, check out &lt;a href="https://howtosoftware.online/" rel="noopener noreferrer"&gt;How To Software&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If in doubt, check the provider logs using &lt;code&gt;TF_LOG=DEBUG terraform apply&lt;/code&gt; to see if you can find an error message like “unable to create cloudinit drive”.&lt;/p&gt;

&lt;p&gt;Frequently Asked Questions&lt;br&gt;
Why does the Terraform Proxmox provider return a “401 permission denied” error when I use the correct API token?&lt;/p&gt;

&lt;p&gt;The token path is case-sensitive and must match&amp;nbsp;User@realm!tokenid&amp;nbsp;exactly. The token must also have&amp;nbsp;Sys.Audit&amp;nbsp;assigned to&amp;nbsp;/&amp;nbsp;to allow the provider to enumerate the nodes. Once you provide that permission to the token, this error will no longer occur.&lt;/p&gt;

&lt;p&gt;How can I automatically increase the size of the cloud-init disk after cloning my template to create a VM?&lt;/p&gt;

&lt;p&gt;Although you cannot increase the size of the cloud‑init ISO itself, you can increase the size of the root disk by using a&amp;nbsp;remote-exec&amp;nbsp;provisioner that runs&amp;nbsp;growpart&amp;nbsp;and&amp;nbsp;resize2fs. Make sure your cloudinit user-data file contains&amp;nbsp;growpart&amp;nbsp;under&amp;nbsp;bootcmd&amp;nbsp;or a&amp;nbsp;runcmd. It is recommended not to use&amp;nbsp;provisioner&amp;nbsp;blocks for any heavy configuration. They should be considered a last resort.&lt;/p&gt;

&lt;p&gt;Can I use one Terraform configuration to operate on multiple Proxmox nodes in a home lab?&lt;/p&gt;

&lt;p&gt;Yes! You can configure provider aliases for each node, and use a loop to iterate over a map of endpoints. Be mindful of the API's concurrency limits; keep parallelism low (for example,&amp;nbsp;-parallelism=2), so you do not overwhelm your host with too many requests at once. While looping over nodes using&amp;nbsp;for_each&amp;nbsp;works, make sure you validate the token on each node before executing the configuration.&lt;/p&gt;

</description>
      <category>automation</category>
      <category>devops</category>
      <category>infrastructure</category>
      <category>terraform</category>
    </item>
  </channel>
</rss>
