This chapter follows Infrastructure as Code with Terraform. You need a GCP project with billing enabled, the Google Cloud SDK (gcloud), and Terraform 1.x installed.
Prepare the workstation
Install Terraform from developer.hashicorp.com/terraform/downloads or your package manager. Confirm the binary:
terraform versionLog in for Application Default Credentials and set your project:
gcloud auth application-default logingcloud config set project YOUR_PROJECT_IDEnable APIs Terraform will call (one-time per project):
gcloud services enable storage.googleapis.com compute.googleapis.comCreate a working directory for this tutorial, for example ~/terraform-gcp-intro.
Configure providers and backend (local state)
Create versions.tf to pin Terraform and the Google provider:
terraform { required_version = ">= 1.5.0"
required_providers { google = { source = "hashicorp/google" version = "~> 5.0" } }}
provider "google" { project = var.project_id region = var.region}For learning, state stays local in terraform.tfstate. Before team use, move state to a GCS backend as described in State data in Terraform.
Add variables.tf:
variable "project_id" { type = string description = "GCP project ID"}
variable "region" { type = string default = "europe-west1" description = "Default region for regional resources"}
variable "bucket_name" { type = string description = "Globally unique GCS bucket name"}Create terraform.tfvars (do not commit secrets here; project id and bucket name are fine):
project_id = "YOUR_PROJECT_ID"bucket_name = "YOUR_UNIQUE_BUCKET_NAME"Create a Cloud Storage bucket
Add main.tf with a single bucket:
resource "google_storage_bucket" "tutorial" { name = var.bucket_name location = var.region
uniform_bucket_level_access = true
force_destroy = true}Add outputs.tf:
output "bucket_url" { value = google_storage_bucket.tutorial.url description = "Base URL of the tutorial bucket"}Initialize and apply:
cd ~/terraform-gcp-introterraform initterraform fmt -recursiveterraform validateterraform planterraform applyOpen the bucket URL from terraform output bucket_url or verify in the Cloud Console. State now records the bucket resource id.
Add a VPC and a small VM
Extend main.tf with networking and a minimal instance:
resource "google_storage_bucket" "tutorial" { name = var.bucket_name location = var.region
uniform_bucket_level_access = true force_destroy = true}
resource "google_compute_network" "vpc" { name = "terraform-tutorial-vpc" auto_create_subnetworks = false}
resource "google_compute_subnetwork" "subnet" { name = "terraform-tutorial-subnet" ip_cidr_range = "10.0.1.0/24" region = var.region network = google_compute_network.vpc.id}
resource "google_compute_instance" "vm" { name = "terraform-tutorial-vm" machine_type = "e2-micro" zone = "${var.region}-b"
boot_disk { initialize_params { image = "debian-cloud/debian-12" } }
network_interface { network = google_compute_network.vpc.id subnetwork = google_compute_subnetwork.subnet.id }
tags = ["terraform-tutorial"]}Run plan again. Terraform should propose the network, subnet, and VM without recreating the bucket unless you changed it:
terraform planterraform applyInspect resources in the console or with gcloud compute instances list.
Clean up
When you are finished experimenting, destroy managed resources:
terraform destroyConfirm when prompted. force_destroy = true on the bucket allows deletion even if objects exist—appropriate for a sandbox, not for production data stores.
Next: HCL structure in Terraform explains blocks, expressions, and meta-arguments in depth.