This episode covers automating VM provisioning with Terraform and OpenTofu through the bpg/proxmoxve provider, configuration automation with Ansible, and an end-to-end flow from cloud-init templates to a configured software stack.

In episode 4 you created VMs from templates manually. Episode 17 teaches you how to create hundreds of VMs with code: defining infrastructure as files that can be reviewed, verified, and repeated — this is Infrastructure as Code (IaC).
We'll use Terraform and OpenTofu with the Proxmox provider for provisioning, Ansible for in-VM configuration, and then combine both into a single automated flow. By the end of the episode, you'll be able to write a file, run one command, and the infrastructure appears by itself.
Terraform and OpenTofu are declarative tools: you describe the desired end state, and the tool works to achieve it. For Proxmox, the most mature official provider is bpg/proxmoxve — a community provider developed with broad support and complete features.
mkdir proxmox-iac && cd proxmox-iac
cat > versions.tf <<'EOF'
terraform {
required_providers {
proxmox = {
source = "bpg/proxmox"
version = "~> 0.70"
}
}
}
EOF
terraform initThe terraform init command downloads the provider according to the versions.tf definition. OpenTofu uses the exact same flow.
Define a VM as a resource in a .tf file:
resource "proxmox_virtual_environment_vm" "web" {
name = "web-01"
node_name = "pve"
vm_id = 200
clone {
vm_id = 9000
}
cpu {
cores = 2
}
memory {
dedicated = 2048
}
network_device {
bridge = "vmbr0"
}
disk {
datastore_id = "local-lvm"
interface = "scsi0"
}
initialization {
ip_config {
ipv4 {
address = "192.168.1.50/24"
gateway = "192.168.1.1"
}
}
user_account {
username = "admin"
keys = [trimspace(file("~/.ssh/id_ed25519.pub"))]
}
}
}Save it as main.tf, then apply:
terraform plan
terraform apply -auto-approveThe bpg/proxmoxve provider creates a VM from template 9000, configures the resources and cloud-init, and Proxmox powers it on. All results are recorded as state — you can modify, delete, or duplicate VMs simply by editing the file.
Ansible is an imperative, playbook-based tool for configuration. The community.general.proxmox* modules let Ansible manage the VM lifecycle — creating, stopping, or deleting — through the Proxmox API. A simple playbook example:
- name: Ensure the VM is running
hosts: localhost
connection: local
tasks:
- name: Start VM 200
community.general.proxmox_kvm:
api_host: 192.168.1.10
api_user: root@pam
api_password: "{{ proxmox_password }}"
vmid: 200
state: startedThis playbook ensures VM 200 is running, using credentials from an Ansible Vault variable for security.
For work inside VMs — installing packages, writing configuration, running services — Ansible works directly on the guests. Create an inventory containing the VMs Terraform built, then run the playbook to set up the software stack:
ansible-playbook -i inventory.yml setup-webserver.ymlThe ansible-playbook command configures the VMs according to the playbook — idempotent, safe to run repeatedly, and consistent in results.
The real power appears when both are combined. The standard flow:
Terraform: cloud-init template -> ready VM
Ansible : VM -> configured software stackYou can schedule this flow in CI/CD — every time the infrastructure code changes, the pipeline rebuilds a consistent environment. This is the pattern SRE teams use in production.
Info
Keep all IaC files in git. Infrastructure as code means infrastructure can be reviewed like code: pull requests, reviews, and a changelog for every change.
Episode 17 took you into the IaC era: provisioning VMs with Terraform and OpenTofu through the bpg/proxmoxve provider, managing the lifecycle with Ansible, and combining both in an end-to-end pipeline from cloud-init templates to a ready-to-use software stack.
The key takeaways:
bpg/proxmoxve provider is the standard for Terraform and OpenTofu.In the next episode, episode 18, we will cover monitoring, alerting, and metrics — monitoring nodes and VMs with built-in metrics, exporting metrics to Prometheus with pve-exporter, visualizing them in Grafana, and configuring alerts for early notification. Your infrastructure is automated; now it's time to make it visible and alert!