Recently I got asked to provision a number of identical VMs. Now usually I resort to PowerCLI for this task, but this time I thought it would be nice to get out of my comfort zone and try something new for a change. Since I was experimenting with Packer in the beginning of this year I thought it might be a good idea to give Hashicorp Terraform a try.


Like Packer Terraform can be used to provision infrastructure resources using a declarative configuration file. This means that a Terraform configuration describes a desired state. Then it makes sure that all the necessary steps are executed to create, modify or remove objects as needed. In contrast a tool like Powershell works in an imperative style. Using an imperative syntax means that you specify exactly which commands need to be executed to achieve a certain goal. There are both cons and cons to each of these approaches. And there are many resources on the web that go into that in more detail so I don’t have to. ?


Now to get started with Terraform you first need to install it. You can download the appropriate files from the Terraform download page. Like Packer there are versions available for macOS, FreeBSD, Linux, OpenBSD, Solaris and Windows. The beauty is you can simply download an archive file, extract it and you’re ready to go.

Create a project

Once you installed Terraform you can start creating your first project. In this case I’ll be using the vSphere provider to provision a number of VMs. To make this happen you need to first create a configuration file. When you create a directory for your project Terraform will process all files that have a .tf file extension. Since this project contains credentials to connect to a vCenter server I use a file called terraform.tfvars which is processed by default if it exists in the project directory. More information on using variables can be found on the getting started page. To make things easy on myself I used the “Cloning and customization example”from the vSphere provider documentation as a baseline.

I did however change a couple of things that I want to highlight.

  • Changed the code so a datastore cluster is used instead of a single datastore
  • Added a count property in the vsphere_virtual_machine resource so multiple resouces are created instead of just one
  • Added a number of variables to control a suffix for the VM and guest OS hostname and to assign each VM with a static IPv4 address

The code contains comments that describe how the configuration is supposed to work. So you can reuse the code in your projects easily. So without any further ado, here is my sample configuration file.

Initializing plugins

Now before you can use the vSphere provider you must first initialize it. This is achieved by using the following command in your project directory. Below the command you can see it’s output.

Testing and applying the configuration

When you initialized the plugin you can first do a dry-run before deploying the resources for real. Use the following command for a dry-run.

Finally when you are confident that the configuration will create the resources correctly you can apply the configuration using the following command.

And when you are done with the project you can remove it just as easily.

That’s all there is to it.

Now I am aware that simply provisioning a couple VMs is only part of a solution. You probably also want to install some applications, maybe configure some network resources such as a firewall et cetera. Fortunately there are plenty of providers within the Terraform framework that you can use. But for the purposes of this blog post I limit myself to the vSphere provider.

So I hope this blog post makes sense and maybe get you excited about using Terraform for your projects as well.


  1. Hello

    Thanks for this instruction.
    But what if I want to add another VM. In my test environment every time I wanna apply again, the other VM that already exists is gonna be deleted and created again.
    What’s the solution of this? Create every time a new file and then a new VM?


Leave a Reply

Your email address will not be published. Required fields are marked *