DevOps
Provision VMs on VMware ESXi and vCenter with Terraform: vsphere provider, templates, cloud-init, networking, and resource pools.
LLuca Berton2 min read
On this page
- Quick Pattern (TL;DR)
- Discover Existing Datacenter Objects
- Clone a VM from Template with cloud-init
- Distributed Port Group for Production Networks
- Resource Pools and Folders
- Best Practices
- Frequently asked questions
- How do I connect Terraform to vCenter?
- Can Terraform provision VMs directly on a standalone ESXi host without vCenter?
- How do I clone a VM from a template with Terraform?
- How do I pass cloud-init to a vSphere Linux VM?
- Related
VMware vSphere / ESXi remains the dominant on-prem hypervisor in 2026. The official hashicorp/vsphere Terraform provider lets you create datacenters, clusters, resource pools, port groups, and virtual machines from templates with cloud-init customization — the same workflow you use for cloud VMs.
Quick Pattern (TL;DR)
terraform {
required_providers {
vsphere = {
source = "hashicorp/vsphere"
version = "~> 2.10"
}
}
}
provider "vsphere" {
user = var.vsphere_user
password = var.vsphere_password
vsphere_server = var.vcenter_server
allow_unverified_ssl = false
}Discover Existing Datacenter Objects
data "vsphere_datacenter" "dc" {
name = "DC01"
}
data "vsphere_compute_cluster" "cluster" {
name = "Cluster01"
datacenter_id = data.vsphere_datacenter.dc.id
}
data "vsphere_datastore" "ds" {
name = "vsanDatastore"
datacenter_id = data.vsphere_datacenter.dc.id
}
data "vsphere_network" "vmnet" {
name = "VM Network"
datacenter_id = data.vsphere_datacenter.dc.id
}
data "vsphere_virtual_machine" "ubuntu_template" {
name = "templates/ubuntu-24.04"
datacenter_id = data.vsphere_datacenter.dc.id
}Clone a VM from Template with cloud-init
resource "vsphere_virtual_machine" "web" {
name = "web-01"
resource_pool_id = data.vsphere_compute_cluster.cluster.resource_pool_id
datastore_id = data.vsphere_datastore.ds.id
num_cpus = 4
memory = 8192
guest_id = data.vsphere_virtual_machine.ubuntu_template.guest_id
network_interface {
network_id = data.vsphere_network.vmnet.id
adapter_type = data.vsphere_virtual_machine.ubuntu_template.network_interface_types[0]
}
disk {
label = "disk0"
size = 80
eagerly_scrub = false
thin_provisioned = true
}
clone {
template_uuid = data.vsphere_virtual_machine.ubuntu_template.id
customize {
linux_options {
host_name = "web-01"
domain = "lab.example.com"
}
network_interface {
ipv4_address = "10.0.10.21"
ipv4_netmask = 24
}
ipv4_gateway = "10.0.10.1"
dns_server_list = ["10.0.10.1"]
}
}
extra_config = {
"guestinfo.userdata" = base64encode(file("${path.module}/cloud-init.yaml"))
"guestinfo.userdata.encoding" = "base64"
}
}Distributed Port Group for Production Networks
resource "vsphere_distributed_port_group" "prod" {
name = "pg-prod-100"
distributed_virtual_switch_uuid = data.vsphere_distributed_virtual_switch.dvs.id
vlan_id = 100
active_uplinks = ["uplink1", "uplink2"]
}Resource Pools and Folders
resource "vsphere_resource_pool" "team" {
for_each = toset(var.teams)
name = each.key
parent_resource_pool_id = data.vsphere_compute_cluster.cluster.resource_pool_id
}
resource "vsphere_folder" "team" {
for_each = toset(var.teams)
path = "teams/${each.key}"
type = "vm"
datacenter_id = data.vsphere_datacenter.dc.id
}Best Practices
- Bake templates with Packer, then clone with Terraform — don't try to install OSes from Terraform.
- Use cloud-init via guestinfo for Linux; use
customize { windows_options {} }for Windows Sysprep. - Pin provider version — vSphere provider has had breaking changes around v2.0/v2.5.
- Tag VMs via
vsphere_tagso you can drive backup, snapshot, and patching policies. - Hide vCenter creds in Vault or HCP Vault Secrets — never commit them.
Frequently asked questions
How do I connect Terraform to vCenter?
Configure the hashicorp/vsphere provider with user, password, and vsphere_server (your vCenter FQDN). Keep allow_unverified_ssl = false in production and pass credentials via environment variables (VSPHERE_USER, VSPHERE_PASSWORD) or a secrets manager rather than hardcoding them.
Can Terraform provision VMs directly on a standalone ESXi host without vCenter?
The vsphere provider is built around vCenter — most resources (resource pools, distributed port groups, content libraries) require it. A standalone ESXi host works for only a limited subset, so for real automation point Terraform at vCenter, not the ESXi host directly.
How do I clone a VM from a template with Terraform?
Look up the template with a vsphere_virtual_machine data source, then reference its id in the clone { template_uuid = ... } block of your vsphere_virtual_machine resource. Use the nested customize block to set hostname, IP, and DNS at first boot.
How do I pass cloud-init to a vSphere Linux VM?
Set the guestinfo.userdata (base64-encoded) and guestinfo.userdata.encoding keys in extra_config. The cloud-init datasource for VMware reads these on first boot. For Windows, use customize { windows_options { ... } } for Sysprep instead.
#Terraform#VMware#vSphere#ESXi#vCenter
DevOps
Terraform for Hyper-V Virtualization
Automate Microsoft Hyper-V with Terraform: taliesins/hyperv provider, VM provisioning, virtual switches, and Windows Server-based hypervisor management.
1 min read
DevOps
Terraform for Nutanix AHV: HCI VM Automation
Automate Nutanix AHV with Terraform: nutanix/nutanix provider, VM provisioning, categories, and Prism Central infrastructure as code.
2 min read
DevOps
Terraform for Proxmox VE: Provision Virtual Machines
Provision VMs on Proxmox VE with Terraform using the bpg/proxmox provider: API token auth, cloud-init, LXC containers, and storage pools.
3 min read
DevOps
Terraform for Xen and XCP-ng Virtualization
Automate Xen and XCP-ng pools with Terraform: xenorchestra provider, VM provisioning, SR storage, and Citrix Hypervisor lab automation.
1 min read

Comments
Nothing yet. Say the first thing.
Sign in to join the conversation.