Terraform and VMWare vSphere: A quick intro

This one is still very much a work in progress - the VMWare vSphere plugin is still very new and under development (it went from 0.3 to 0.4.1 over a weekend, leaving me a little confused when things suddenly changed).

First of all, you need a license for vSphere or ESXi which grants you API and datastore access.  This comes in the 60 day trial license, but the free ESXi license does not include it.

Here's a simple vSphere orientated build.tf:

# Configure the VMware vSphere Provider
provider "vsphere" {
    vsphere_server = "${var.vsphere_vcenter}"
    user = "${var.vsphere_user}"
    password = "${var.vsphere_password}"
    allow_unverified_ssl = true

data "vsphere_datacenter" "my-dc" {}

resource "vsphere_folder" "standalone" {
    path = "standalone"
    datacenter_id = "${data.vsphere_datacenter.my-dc.id}"
    type = "vm"

resource "vsphere_virtual_machine" "plex-server" {
    name   = "plex-server"
    hostname = "plex-server"
    folder = "${vsphere_folder.standalone.path}"
    vcpu   = 4
    memory = 8192
    #domain = "${var.vsphere_domain}"
    datacenter = "${var.vsphere_datacenter}"
    cluster = "${var.vsphere_cluster}"

    # Define the Networking settings for the VM
    network_interface {
        label = "VM Network"
        ipv4_gateway = ""
        ipv4_address = ""
        ipv4_prefix_length = "24"

    dns_servers = ["", ""]

    # Define the Disks and resources. The first disk should include the template.
    disk {
        template = "${var.template_name}"
        datastore = "datastore1"
        type ="thin"

    disk {
        datastore = "datastore1"
        type ="thin"
        name = "plex-store"
        keep_on_remove = "true"
        size = "50"

    # Define Time Zone
    time_zone = "Pacific/Auckland"

Very simply, this does the following:

Sets up the vSphere Terraform plugin (more on this later)

Defines a data center to use - this should reflect whatever data center you are using in your vSphere setup.  If you don't have a data center, you dont have to use this.

Creates a folder called standalone (to put standalone virtual machines in, rather than Docker or Kubernetes clusters etc)

Creates a virtual machine

The virtual machine has 4 virtual CPUs, 8GB RAM, a static IPv4 address, DNS servers and default gateway, a hostname and two virtual disks each on datastore1.

The first disk sets the OS template to use - there is a caveat here in that you are lead to believe that this is a vSphere template, and that you need vCenter to create such a template, but you don't.

The template is actually any existing virtual machine - just use its name here and Terraform will clone that machines virtual disk.  Its got nothing to do with vSphere or vCenter templates...

The two additional Terraform files you need to make this work are variables.tf, which sets the variables available in your build.tf:

variable "vsphere_vcenter" {}
variable "vsphere_user" {}
variable "vsphere_password" {}
variable "vsphere_datacenter" {}
variable "vsphere_cluster" {}
variable "vsphere_domain" {}
variable "template_name" {}

and terraform.tfvars, which populates those variables:

vsphere_vcenter = "my-vsphere-server-address"
vsphere_user = "myapiuser"
vsphere_password = "ohlookapassword!"
vsphere_datacenter = "my-dc"
vsphere_domain = "my-vsphere-domain"
vsphere_cluster = "smy-vsphere-cluster"
template_name = "ubuntu-1604"

You typically do NOT want to check any terraform.tfvars file into source control, as it usually contains passwords, API keys and other such dirty underwear.

Once you have these files configured in a folder, you need to initialise terraform:

$ terraform init

This downloads any plugins needed, based on whats in your build.tf file.

Then make a plan:

$ terraform plan

This will go off and talk to your vSphere server, find the differences between the infrastructure on the server and the infrastructure you have defined in your build.tf and give you a plan of what its going to do - create, update and destroy.

The plan is quite strict in that it doesn't trash your entire existing vSphere setup - in the above scenario it will look for a datacenter called my-dc, create it if it doesnt exist, then it will look for a folder called standalone and create it if it doesn't, then look for a VM called plex and create it if it doesn't.  If the VM exists, then it will update it with the settings you have defined.

Then let it rip:

$ terraform apply

And off down the rabbit hole you go...