Skip to content

Instantly share code, notes, and snippets.

@kpratikshak
Created February 22, 2026 09:32
Show Gist options
  • Select an option

  • Save kpratikshak/0f225791841764d6c4d112a8240be8a5 to your computer and use it in GitHub Desktop.

Select an option

Save kpratikshak/0f225791841764d6c4d112a8240be8a5 to your computer and use it in GitHub Desktop.
gcp VPC, network subnet creation automation
resource "google_sql_database_instance" "default" {
name = "example-sql"
database_version = "POSTGRES_15"
region = "us-central1"
settings {
tier = "db-f1-micro"
}
}
resource "google_sql_user" "users" {
name = "example-user"
instance = google_sql_database_instance.default.name
password = var.db_password
}
resource "google_sql_database" "database" {
name = "example-db"
instance = google_sql_database_instance.default.name
}
terraform {
required_version = ">= 1.0"
required_providers {
google = {
source = "hashicorp/google"
version = "~> 5.0"
}
google-beta = {
source = "hashicorp/google-beta"
version = "~> 5.0"
}
}
}
provider "google" {
project = var.project_id
region = var.region
}
provider "google-beta" {
project = var.project_id
region = var.region
}
2. Input Variables (variables.tf)
variable "project_id" {
type = string
description = "Google Cloud Project ID"
validation {
condition = length(var.project_id) > 6
error_message = "Project ID must be more than 6 characters."
}
}
variable "region" {
type = string
description = "GCP region for resources"
default = "us-central1"
validation {
condition = contains([
"us-central1", "us-east1", "us-west1", "us-west2",
"europe-west1", "europe-west2", "asia-east1"
], var.region)
error_message = "Region must be a valid GCP region."
}
}
variable "environment" {
type = string
description = "Environment name (dev, staging, prod)"
default = "dev"
validation {
condition = contains(["dev", "staging", "prod"], var.environment)
error_message = "Environment must be dev, staging, or prod."
}
}
variable "vpc_name" {
type = string
description = "Name for the VPC network"
default = "main-vpc"
}
variable "subnet_name" {
type = string
description = "Name for the subnet"
default = "main-subnet"
}
variable "subnet_cidr" {
type = string
description = "CIDR range for the subnet"
default = "10.0.1.0/24"
validation {
condition = can(cidrhost(var.subnet_cidr, 0))
error_message = "Subnet CIDR must be a valid IPv4 CIDR block."
}
}
3. Networking Resources (networking.tf)
# VPC Network
resource "google_compute_network" "main_vpc" {
name = "${var.environment}-${var.vpc_name}"
project = var.project_id
auto_create_subnetworks = false
routing_mode = "REGIONAL"
mtu = 1460
description = "Main VPC network for ${var.environment} environment"
# Enable deletion protection in production
delete_default_routes_on_create = false
}
# Subnet
resource "google_compute_subnetwork" "main_subnet" {
name = "${var.environment}-${var.subnet_name}"
project = var.project_id
region = var.region
network = google_compute_network.main_vpc.name
ip_cidr_range = var.subnet_cidr
private_ip_google_access = true
description = "Primary subnet in ${var.region} for ${var.environment}"
# Enable flow logs for security monitoring
log_config {
aggregation_interval = "INTERVAL_10_MIN"
flow_sampling = 0.5
metadata = "INCLUDE_ALL_METADATA"
}
# Secondary IP ranges for future use (GKE, etc.)
secondary_ip_range {
range_name = "pods"
ip_cidr_range = "10.1.0.0/16"
}
secondary_ip_range {
range_name = "services"
ip_cidr_range = "10.2.0.0/16"
}
}
# Cloud Router for Cloud NAT (we'll use this in Part 2)
resource "google_compute_router" "main_router" {
name = "${var.environment}-cloud-router"
project = var.project_id
region = var.region
network = google_compute_network.main_vpc.id
description = "Cloud Router for NAT gateway"
}
4. Storage Resources (storage.tf)
# Storage bucket for Terraform state (remote backend)
resource "google_storage_bucket" "terraform_state" {
name = "${var.project_id}-${var.environment}-terraform-state"
project = var.project_id
location = var.region
# Force destroy for development (disable in production)
force_destroy = var.environment == "dev" ? true : false
# Enable versioning for state file safety
versioning {
enabled = true
}
# Uniform bucket-level access for better security
uniform_bucket_level_access = true
# Encryption at rest
encryption {
default_kms_key_name = null # We'll add KMS in Part 4
}
# Lifecycle management to control costs
lifecycle_rule {
condition {
age = 30
}
action {
type = "Delete"
}
}
lifecycle_rule {
condition {
age = 7
with_state = "ARCHIVED"
}
action {
type = "Delete"
}
}
# Labels for resource management
labels = {
environment = var.environment
purpose = "terraform-state"
managed-by = "terraform"
}
}
# General purpose storage bucket
resource "google_storage_bucket" "app_storage" {
name = "${var.project_id}-${var.environment}-app-storage"
project = var.project_id
location = var.region
# Storage class optimization
storage_class = "STANDARD"
uniform_bucket_level_access = true
# CORS configuration for web applications
cors {
origin = ["*"]
method = ["GET", "HEAD", "PUT", "POST", "DELETE"]
response_header = ["*"]
max_age_seconds = 3600
}
labels = {
environment = var.environment
purpose = "application-storage"
managed-by = "terraform"
}
}
# IAM binding for service account access to state bucket
resource "google_storage_bucket_iam_member" "terraform_state_access" {
bucket = google_storage_bucket.terraform_state.name
role = "roles/storage.admin"
member = "serviceAccount:terraform-automation@${var.project_id}.iam.gserviceaccount.com"
}
5. Outputs (outputs.tf)
output "vpc_name" {
value = google_compute_network.main_vpc.name
description = "Name of the created VPC"
}
output "vpc_id" {
value = google_compute_network.main_vpc.id
description = "ID of the created VPC"
}
output "vpc_self_link" {
value = google_compute_network.main_vpc.self_link
description = "Self-link of the VPC (useful for other resources)"
}
output "subnet_name" {
value = google_compute_subnetwork.main_subnet.name
description = "Name of the created subnet"
}
output "subnet_cidr" {
value = google_compute_subnetwork.main_subnet.ip_cidr_range
description = "CIDR range of the subnet"
}
output "subnet_gateway_address" {
value = google_compute_subnetwork.main_subnet.gateway_address
description = "Gateway IP address of the subnet"
}
output "terraform_state_bucket" {
value = google_storage_bucket.terraform_state.name
description = "Name of the Terraform state storage bucket"
}
output "app_storage_bucket" {
value = google_storage_bucket.app_storage.name
description = "Name of the application storage bucket"
}
output "cloud_router_name" {
value = google_compute_router.main_router.name
description = "Name of the Cloud Router (for NAT in Part 2)"
}
# Network details for use in subsequent parts
output "network_details" {
value = {
vpc_name = google_compute_network.main_vpc.name
subnet_name = google_compute_subnetwork.main_subnet.name
region = var.region
project_id = var.project_id
}
description = "Network configuration details for other Terraform configurations"
}
6. Variable Values (terraform.tfvars)
# Project Configuration
project_id = "your-gcp-project-id" # Replace with your actual project ID
environment = "dev"
# Network Configuration
region = "us-central1"
vpc_name = "main-vpc"
subnet_name = "primary-subnet"
subnet_cidr = "10.0.1.0/24"
7. Backend Configuration (backend.tf)
# Local backend for initial setup
terraform {
backend "local" {
path = "terraform.tfstate"
}
}
# After creating the storage bucket, uncomment below and migrate:
# terraform {
# backend "gcs" {
# bucket = "your-project-id-dev-terraform-state"
# prefix = "foundation/state"
# }
-beta" {
project = var.project_id
region = var.region
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment