Write, plan, and create infrastructure as code

What is Terraform?

Terraform provisions and manages cloud resources across providers

Think Ansible, but for cloud resources rather than just servers

Terraform can...

Provision AWS EC2 instances · Configure AWS Auto Scaling Groups Create and manage AWS AMIs · Provision VMware vSphere VMs Configure Datadog monitors · Manage GitHub repos and teams · Create ZIP archives Brew your coffee

And a whooole lot more...

Terraform currently supports ~300 different resources for AWS alone

Shut up and show us the code!

Configurations are written in HCL, a human friendly configuration language that transpiles to JSON


Creating an EC2 instance running Ubuntu 14.04

Let's start by configuring a provider:

    provider "aws" {
      region = "us-east-1"

Terraform will automatically read our AWS credentials from the environment so there's no need to specify anything else

Let's grab the latest Ubuntu 14.04 AMI from Canonical:

    data "aws_ami" "ubuntu" {
      most_recent = true

      owners = [
        "099720109477", # Canonical; look ma, comments!

      filter {
        name = "name"

        values = [

Now, spin up a t2.micro instance:

    resource "aws_instance" "hello_world" {
      ami           = "${data.aws_ami.ubuntu.id}"
      instance_type = "t2.micro"

      tags {
        Name = "HelloWorld"

Finally, let's go ahead and bootstrap the instance:

    resource "aws_instance" "hello-world" {

      provisioner "file" {
        source      = "bootstrap.sh"
        destination = "/tmp/bootstrap.sh"

      provisioner "remote-exec" {
        inline = [
          "chmod +x /tmp/bootstrap.sh",
          "/tmp/bootstrap.sh --id ${aws_instance.hello_world.id}",

With the configuration in place, we can spin up the infrastructure

The first step is to create an execution plan by running terraform plan:

    + aws_instance.hello_world
        ami:                         "ami-49c9295f"
        instance_type:               "t2.micro"
        source_dest_check:           "true"
        tags.%:                      "1"
        tags.Name:                   "HelloWorld"
        associate_public_ip_address: "<computed>"

    Plan: 1 to add, 0 to change, 0 to destroy.

The plan will tell exactly what Terraform intends to do

When happy with the execution plan, apply it using terraform apply

Once applied, Terraform will keep track of the current infrastructure state in a .tfstate file

This file can be checked into version control to allow collaborating on the state

When you want to change your infrastructure, just rinse and repeat the plan and apply steps

Why use Terraform?

It's collaborative

Infrastructure configuration can be version controlled and code reviewed

It's predicatable

Plan your changes, review the execution plan, and finally apply it

It's reproducible

All configuration is encapsulated in code and can easily be applied to a clean environment

It's reusable

Shared configuration can be separated into modules and re-used across projects

No provider lock-in

Terraform is provider agnostic and integrates with as many or as few providers as needed