Create Your First vSphere Terraform Configuration

To get started with HashiCorp Terraform, you can download the simple executable file from HashiCorp here. To understand the basics of Infrastructure as Code and Terraform, have a read of the post available here.

Terraform configuration files are text files with a .tf file extension. To get started, create a new folder for this configuration, along with a file called The first part to creating a Terraform configuration file is to define the provider you will interact with. In this example, it will create a virtual machine using the vSphere provider. The vSphere provider has some required fields like the user, password and server name. Create the provider block referring to "vsphere" and set the required fields with valid values for your environment.

1provider "vsphere" {
2  # If you use a domain, set your login like this "Domain\\User"
3  user           = "administrator@vsphere.local"
4  password       = "VMware1!"
5  vsphere_server = "vcenter-1.homelab.local"
7  # If you have a self-signed cert
8  allow_unverified_ssl = true

Following the provider, define any "data" sources needed, which are used to retrieve existing objects. In this example of creating a vSphere virtual machine, reference the existing data center, cluster, datastore, VM network and template objects. This is defined in the code below. You can see that the "name" values are used to locate each of the objects. These will be referenced later to retrieve the ID values, as you can also see in the "vsphere_resource_pool" data source.

 1data "vsphere_datacenter" "dc" {
 2  name = "vSAN Datacenter"
 5# If you don't have any resource pools, put "/Resources" after cluster name
 6data "vsphere_resource_pool" "pool" {
 7  name          = "vSAN Cluster/Resources"
 8  datacenter_id =
11# Retrieve datastore information on vsphere
12data "vsphere_datastore" "datastore" {
13  name          = "vsanDatastore"
14  datacenter_id =
17# Retrieve network information on vsphere
18data "vsphere_network" "network" {
19  name          = "VM_Network-DPortGroup"
20  datacenter_id =
23# Retrieve template information on vsphere
24data "vsphere_virtual_machine" "template" {
25  name          = "centos-8"
26  datacenter_id =

Once you have all of the required data sources, define the "resource" that is to be created. In this case, it will be the "vsphere_virtual_machine" type, where the configuration of the virtual machine is defined. Start by defining the VM name, along with how many CPUs and the amount of memory to be assigned (in MB). There are a few required fields such as the datastore_ID and resource_pool_ID, which are referred to using the "data" sources created earlier. Then set the guest_ID and scsi_type to reference the guest_id and scsi_type of the template VM by referencing the "data" source.

The network_id in the network_interface block is set to match the "data" source of the vSphere network.

The disk block is then defined where the VMDK label is defined, along with the size of the disk to be deployed (in GB).

The clone block is next, where the template VM is defined, referring to the "data" source of the template. The customization options are then set where the host_name, domain and IP configuration is set.

The final block in the "resource" is the remote-exec provisioner. A remote-exec provisioner is used to run a command or script on the provisioned resource. The script to be called is specified along with how to connect to the VM. In this case, a connection is made using the root credentials to the default IP address of the provisioned VM. The contents of the example script are also shown below.

 1# Set vm parameters
 2resource "vsphere_virtual_machine" "demo" {
 3  name             = "vm-one"
 4  num_cpus         = 2
 5  memory           = 4096
 6  datastore_id     =
 7  resource_pool_id =
 8  guest_id         = data.vsphere_virtual_machine.template.guest_id
 9  scsi_type        = data.vsphere_virtual_machine.template.scsi_type
11  # Set network parameters
12  network_interface {
13    network_id =
14  }
16  # Use a predefined vmware template as main disk
17  disk {
18    label = "vm-one.vmdk"
19    size = "30"
20  }
22  clone {
23    template_uuid =
25    customize {
26      linux_options {
27        host_name = "vm-one"
28        domain    = "vm-one.homelab.local"
29      }
31      network_interface {
32        ipv4_address    = ""
33        ipv4_netmask    = 24
34        dns_server_list = ["", ""]
35      }
37      ipv4_gateway = ""
38    }
39  }
41  # Execute script on remote vm after this creation
42  provisioner "remote-exec" {
43    script = "scripts/"
44    connection {
45      type     = "ssh"
46      user     = "root"
47      password = "VMware1!"
48      host     = vsphere_virtual_machine.demo.default_ip_address 
49    }
50  }

The final file will look like this. It will contain the provider, data and resource elements.

Note: Do not store your configuration in a version control system such as GitHub or GitLab as this example stores your credentials in the file. Instead, these would typically be stored in variables, where the variables are excluded from your git commits.

Once your file is complete, run the "terraform init" command in the folder which contains your file. This will automatically download any providers that are referenced in your Terraform configuration file. Next, run the "terraform plan" command which will show you exactly what resources are to be created. In this example, it will be one vsphere_virtual_machine. If the plan looks correct, run the command "terraform apply --auto-approve" to provision your virtual machine. Congratulations! You should now have your new VM deployed in your vSphere environment.

comments powered by Disqus