Terraform Reference: GCP Basic Infrastructure

Type: Software Reference Confidence: 0.92 Sources: 7 Verified: 2026-02-28 Freshness: 2026-02-28

TL;DR

Constraints

Quick Reference

ResourceTerraform TypeKey ArgumentsNotes
VPC Networkgoogle_compute_networkname, auto_create_subnetworksSet false for custom
Subnetgoogle_compute_subnetworknetwork, ip_cidr_range, regionOne per region
Firewall Rulegoogle_compute_firewallnetwork, allow, source_rangesNetwork-level
Compute Instancegoogle_compute_instancemachine_type, zone, boot_diskUse data source for image
Cloud Storagegoogle_storage_bucketname, location, storage_classGlobally unique name
Cloud SQLgoogle_sql_database_instancedatabase_version, settings.tierPrivate IP with VPC peering
IAM Bindinggoogle_project_iam_memberrole, memberUse member for additive
Service Accountgoogle_service_accountaccount_idOne per service
Cloud NATgoogle_compute_router_natrouter, nat_ip_allocate_optionPrivate subnet egress
API Enablementgoogle_project_serviceserviceEnable APIs declaratively
GCS Backendbackend "gcs"bucket, prefixNative locking

Decision Tree

START
├── First time with Terraform on GCP?
│   ├── YES → Enable APIs + GCS backend (Step 1-2)
│   └── NO ↓
├── Need full VPC with private/public subnets?
│   ├── YES → Custom VPC + Cloud NAT (Step 3)
│   └── NO ↓
├── Need VMs or containers?
│   ├── VMs → Compute Engine (Step 4)
│   ├── Containers → Cloud Run or GKE
│   └── NO ↓
├── Need managed database?
│   ├── YES → Cloud SQL with private IP
│   └── NO ↓
└── DEFAULT → VPC + Compute Engine + Cloud Storage

Step-by-Step Guide

1. Configure provider and GCS backend

Set up the Google provider and enable APIs. [src1]

terraform {
  required_version = ">= 1.6.0"
  required_providers {
    google = { source = "hashicorp/google", version = "~> 6.0" }
  }
  backend "gcs" {
    bucket = "my-project-tf-state"
    prefix = "prod"
  }
}

provider "google" {
  project = var.project_id
  region  = var.region
}

resource "google_project_service" "apis" {
  for_each = toset(["compute.googleapis.com", "sqladmin.googleapis.com", "storage.googleapis.com"])
  service            = each.value
  disable_on_destroy = false
}

Verify: terraform init → backend configured

2. Create VPC with subnets

Custom-mode VPC. [src5]

resource "google_compute_network" "main" {
  name                    = "${var.project_name}-vpc"
  auto_create_subnetworks = false
}

resource "google_compute_subnetwork" "public" {
  name          = "${var.project_name}-public"
  ip_cidr_range = "10.0.1.0/24"
  region        = var.region
  network       = google_compute_network.main.id
}

Verify: terraform plan → shows network resources

3. Launch Compute Engine instance

Deploy a VM. [src2]

data "google_compute_image" "debian" {
  family  = "debian-12"
  project = "debian-cloud"
}

resource "google_compute_instance" "web" {
  name         = "${var.project_name}-web"
  machine_type = "e2-micro"
  zone         = "${var.region}-a"
  boot_disk {
    initialize_params { image = data.google_compute_image.debian.self_link }
  }
  network_interface {
    subnetwork = google_compute_subnetwork.public.id
    access_config {}
  }
  tags = ["web", "ssh"]
}

Verify: terraform apply → instance running

Code Examples

HCL: VPC + Cloud SQL with private IP

# Input:  Terraform configuration
# Output: Cloud SQL PostgreSQL with private VPC peering

resource "google_compute_global_address" "private_ip" {
  name          = "private-ip-range"
  purpose       = "VPC_PEERING"
  address_type  = "INTERNAL"
  prefix_length = 16
  network       = google_compute_network.main.id
}

resource "google_sql_database_instance" "main" {
  name             = "${var.project_name}-db"
  database_version = "POSTGRES_16"
  region           = var.region
  settings {
    tier = "db-f1-micro"
    ip_configuration {
      ipv4_enabled    = false
      private_network = google_compute_network.main.id
    }
    backup_configuration { enabled = true; start_time = "03:00" }
  }
  deletion_protection = var.environment == "prod"
}

HCL: Cloud Storage static site with CDN

# Input:  Domain name
# Output: Cloud Storage + HTTP(S) Load Balancer with CDN

resource "google_storage_bucket" "website" {
  name     = var.domain_name
  location = "US"
  website {
    main_page_suffix = "index.html"
    not_found_page   = "404.html"
  }
  uniform_bucket_level_access = true
}

resource "google_compute_backend_bucket" "website" {
  name        = "${var.project_name}-backend"
  bucket_name = google_storage_bucket.website.name
  enable_cdn  = true
}

Anti-Patterns

Wrong: Using default network

# ❌ BAD — permissive firewall rules
resource "google_compute_instance" "web" {
  network_interface { network = "default" }
}

Correct: Custom VPC with explicit rules

# ✅ GOOD — isolated network
resource "google_compute_network" "main" {
  name = "my-vpc"
  auto_create_subnetworks = false
}
resource "google_compute_instance" "web" {
  network_interface { subnetwork = google_compute_subnetwork.public.id }
}

Wrong: Forgetting to enable APIs

# ❌ BAD — "API not enabled" error
resource "google_compute_instance" "web" { ... }

Correct: Declare API enablement

# ✅ GOOD — API enabled first
resource "google_project_service" "compute" {
  service = "compute.googleapis.com"
  disable_on_destroy = false
}
resource "google_compute_instance" "web" {
  depends_on = [google_project_service.compute]
}

Wrong: Owner role for Terraform SA

# ❌ BAD — excessive permissions
role = "roles/owner"

Correct: Least-privilege roles

# ✅ GOOD — specific roles
for_each = toset(["roles/compute.admin", "roles/storage.admin"])

Common Pitfalls

Diagnostic Commands

# Initialize providers
terraform init

# Preview changes
terraform plan -out=tfplan

# Apply plan
terraform apply tfplan

# List state
terraform state list

# Check enabled APIs
gcloud services list --enabled --project=PROJECT_ID

# List VMs
gcloud compute instances list --project=PROJECT_ID

Version History & Compatibility

VersionStatusBreaking ChangesMigration Notes
Terraform 1.9+CurrentNoneHCL improvements
Google Provider 6.xCurrentRemoved deprecated resourcesCheck migration guide
Google Provider 5.xSupportedDefault labels
OpenTofu 1.6+ActiveFork of TF 1.6Drop-in compatible

When to Use / When Not to Use

Use WhenDon't Use WhenUse Instead
Reproducible GCP infrastructureOne-off gcloud commandsgcloud CLI
Team collaboration with reviewsRapid prototypingGCP Console
Multi-cloud deploymentsGCP-only with DM expertiseDeployment Manager
Long-lived infra (VPCs, Cloud SQL)K8s resource managementConfig Connector, Helm

Important Caveats

Related Units