Virtual Event
Join us for the next HashiConf Digital October 12-15, 2020 Register for Free

Get Started - Google Cloud

Build Infrastructure

With Terraform installed, let's dive right into it and start creating some infrastructure.

We'll build infrastructure on GCP for this getting started guide, but Terraform can manage many other things using providers. Some examples of this are in the use cases section.

As you follow this guide, you'll use Terraform to provision, update, and destroy a simple set of infrastructure using the sample configuration provided.

The sample configuration provisions a resource group, networking resources and rules, storage, and a basic Linux virtual machine. You'll also learn about remote backends, outputs, and provisioners. These are the building blocks for more complex configurations.


  • A Google Cloud Platform account. If you don't have a GCP account, create one now. This tutorial can be completed using only the services included in the GCP free tier. However, if you provision infrastructure beyond the free tier, you may be charged.

  • A system with Terraform installed. This guide includes instructions for installing Terraform on the platform of your choice.

»Google Cloud Shell

This guide is also available as an interactive tutorial within Google Cloud Shell. If you prefer, you can follow that version instead, the material covered is the same.

Follow this guide in Google Cloud Shell

»Setting up GCP

In addition to a GCP account, you'll need two things to use Terraform to provision your infrastructure:

  • A GCP Project: GCP organizes resources into projects. Create one now in the GCP console. You'll need the Project ID later. You can see a list of your projects in the cloud resource manager.

  • Google Compute Engine: You'll need to enable Google Compute Engine for your project. Do so now in the console. Make sure the project you're using to follow this guide is selected and click the "Enable" button.

  • A GCP service account key: Terraform will access your GCP account by using a service account key. Create one now in the console. When creating the key, use the following settings:

    • Select the project you created in the previous step.
    • Under "Service account", select "New service account".
    • Give it any name you like.
    • For the Role, choose "Project -> Editor".
    • Leave the "Key Type" as JSON.
    • Click "Create" to create the key and save the key file to your system.

You can read more about service account keys in Google's documentation.


The set of files used to describe infrastructure in Terraform is known as a Terraform configuration. We're going to write our first configuration now to launch a single GCP instance.

The format of the configuration files is documented here. Configuration files can also be JSON, but we recommend only using JSON when the configuration is generated by a machine.

The entire configuration is shown below. We'll go over each part soon.

When run, Terraform loads all configuration files from the current directory. So it's a good idea to organize your configurations into separate directories based on your needs (e.g. departments, production vs development, etc).

Create a directory for the examples in this guide, and inside of it save the example configuration below to a file named Terraform recognizes files ending in .tf or .tf.json as configuration files and will load them when it runs.

provider "google" {
  version = "3.5.0"

  credentials = file("<NAME>.json")

  project = "<PROJECT_ID>"
  region  = "us-central1"
  zone    = "us-central1-c"

resource "google_compute_network" "vpc_network" {
  name = "terraform-network"

You'll also need to copy the service account key file that you downloaded earlier into this directory and reference it in the "credentials" line.

There are other ways to supply your account credentials, see the provider reference for more details.

The provider block is used to configure the named provider, in our case google. A provider is responsible for creating and managing resources. Multiple provider blocks can exist if a Terraform configuration manages resources from different providers.

The resource block defines a resource that exists within the infrastructure. A resource might be a physical component such as a server, or it can be a logical resource such as a Heroku application. In this example, we're creating a network for the resources we'll created later in this tutorial.

The resource block has two strings before opening the block: the resource type and the resource name. In our example, the resource type is "google_compute_network" and the name is "vpc_network." The prefix of the type maps to the provider. In our case "google_compute_network" automatically tells Terraform that it is managed by the "google" provider. The resource type and name together form the resource ID, in this case "google_compute_network.vpc_network". The resource can be referenced by this ID in other parts of your configuration.

Within the resource block itself is configuration for that resource. This is dependent on each resource provider and is fully documented within our providers reference.

The GCP provider documents supported resources, including google_compute_network.

There are a number of optional arguments, but for our network, we just specify the name, which will be how the network is identified in GCP.


The first command to run for a new configuration -- or after checking out an existing configuration from version control -- is terraform init, which initializes various local settings and data that will be used by subsequent commands.

Initialize your new Terraform configuration by running the terraform init command in the same directory as your file.

$ terraform init

Initializing the backend...

Initializing provider plugins...
- Checking for available provider plugins...
- Downloading plugin for provider "google" (hashicorp/google) 3.5.0...

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

The Google Cloud Platform provider plugin has been downloaded and installed in a subdirectory of the current working directory.

»Creating Resources

Apply you configuration now by running the command terraform apply.

$ terraform apply

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # google_compute_network.vpc_network will be created
  + resource "google_compute_network" "vpc_network" {
      + auto_create_subnetworks         = true
      + delete_default_routes_on_create = false
      + gateway_ipv4                    = (known after apply)
      + id                              = (known after apply)
      + name                            = "terraform-network"
      + project                         = (known after apply)
      + routing_mode                    = (known after apply)
      + self_link                       = (known after apply)

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

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value:

This output shows the execution plan, describing which actions Terraform will take in order to create infrastructure to match the configuration. The output format is similar to the diff format generated by tools such as Git. The output has a + next to resource "google_compute_network" "vpc_network", meaning that Terraform will create this resource. Beneath that, it shows the attributes that will be set. When the value displayed is (known after apply), it means that the value won't be known until the resource is created.

If the plan was created successfully, Terraform will now pause and wait for approval before proceeding. If anything in the plan seems incorrect or dangerous, it is safe to abort here with no changes made to your infrastructure.

In this case the plan looks acceptable, so type yes at the confirmation prompt to proceed.

If terraform apply failed with an error, read the error message and fix the error that occurred.

Executing the plan will take a few minutes since Terraform waits for the network to be created successfully:

# ...
  Enter a value: yes

google_compute_network.vpc_network: Creating...
google_compute_network.vpc_network: Still creating... [10s elapsed]
google_compute_network.vpc_network: Still creating... [20s elapsed]
google_compute_network.vpc_network: Still creating... [30s elapsed]
google_compute_network.vpc_network: Still creating... [40s elapsed]
google_compute_network.vpc_network: Still creating... [50s elapsed]
google_compute_network.vpc_network: Creation complete after 58s [id=terraform-network]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

After this, Terraform is all done! You can go to the GCP console to see the network you have provisioned. Make sure you're looking at the same region and project that you configured in the provider configuration.

If you look in your current working directory, you'll see that Terraform also wrote some data into the terraform.tfstate file. This state file is extremely important; it keeps track of Terraform's understanding of the resources it created. We recommended that you use source control for the configuration files, but the state file should not be stored in source control. You can also setup Terraform Cloud to store and share the state with your teams.

You can inspect the current state by running terraform show.

$ terraform show
# google_compute_network.vpc_network:
resource "google_compute_network" "vpc_network" {
    auto_create_subnetworks         = true
    delete_default_routes_on_create = false
    id                              = "terraform-network"
    name                            = "terraform-network"
    project                         = "hc-training-test"
    routing_mode                    = "REGIONAL"
    self_link                       = ""

You can see that by creating our resource, we've also gathered a lot of information about it. These values can be referenced to configure other resources or outputs, which will be covered later in this guide.