Cloud SQL Terraform: Infrastructure as Code Guide for Private PostgreSQL Deployment
Cloud SQL Terraform enables fully automated, private PostgreSQL deployments using Private Service Connect, IAM authentication, and declarative HCL configuration.
Google Cloud SQL provides a fully-managed relational database service that you can provision entirely through Terraform infrastructure as code. By describing your desired database state in HashiCorp Configuration Language (HCL), you obtain reproducible, version-controlled infrastructure deployable across environments without manual console work.
Core Architecture Components
The Google Skills repository demonstrates a production-grade Cloud SQL Terraform module built around five key components.
Cloud SQL Instance Resource
The google_sql_database_instance resource defines the database engine and connectivity model. According to assets/main.tf in the N-Tier Serverless Web App skill, production deployments should enable Private Service Connect (psc_enabled = true) and explicitly disable public IP access (ipv4_enabled = false).
Key settings include:
database_version– e.g.,"POSTGRES_18"for PostgreSQL 18 Enterpriseavailability_type–"REGIONAL"for high availability across zonestier– machine type such as"db-custom-2-7680"
PSC Forwarding Rule
Private Service Connect requires a google_compute_forwarding_rule that maps a reserved internal IP to the Cloud SQL service attachment. This keeps all database traffic inside your VPC without traversing the public internet.
IAM-Authenticated Database Users
The google_sql_user resource with type = "CLOUD_IAM_USER" eliminates password management. Users authenticate through Google's IAM system and connect via the Cloud SQL Auth Proxy.
Service Account Permissions
Applications receive database access through google_project_iam_member bindings granting roles/cloudsql.client. This follows least-privilege principles documented in references/iam-security.md.
Optional Monitoring Configuration
The insights_config block within google_sql_database_instance enables Query Insights for performance analysis without additional agents.
Complete Terraform Configuration Example
This production-ready snippet from assets/main.tf provisions a private PostgreSQL instance with IAM authentication and Query Insights:
terraform {
required_providers {
google = {
source = "hashicorp/google"
version = "~> 5.0"
}
}
}
provider "google" {
project = var.project_id
region = var.region
}
# -------------------------------------------------------------------------
# Cloud SQL instance (Private Service Connect, no public IP)
# -------------------------------------------------------------------------
resource "google_sql_database_instance" "postgres" {
name = var.instance_name
database_version = "POSTGRES_18"
region = var.region
tier = var.instance_tier
deletion_protection = true
settings {
tier = var.instance_tier
activation_policy = "ALWAYS"
availability_type = "REGIONAL"
ip_configuration {
ipv4_enabled = false
psc_config {
psc_enabled = true
}
}
insights_config {
query_insights_enabled = true
}
}
}
# -------------------------------------------------------------------------
# PSC forwarding rule (private IP in consumer VPC)
# -------------------------------------------------------------------------
resource "google_compute_forwarding_rule" "psc_sql" {
name = "${var.instance_name}-psc"
region = var.region
load_balancing_scheme = "INTERNAL"
network = var.vpc_network
ip_address = var.psc_ip
target = google_sql_database_instance.postgres.service_attachment_self_link
ports = ["5432"]
}
# -------------------------------------------------------------------------
# IAM binding for application service account
# -------------------------------------------------------------------------
resource "google_project_iam_member" "sql_client" {
project = var.project_id
role = "roles/cloudsql.client"
member = "serviceAccount:${var.backend_service_account}"
}
# -------------------------------------------------------------------------
# Database and IAM-authenticated user
# -------------------------------------------------------------------------
resource "google_sql_database" "app_db" {
name = var.database_name
instance = google_sql_database_instance.postgres.name
}
resource "google_sql_user" "app_user" {
name = var.db_user
instance = google_sql_database_instance.postgres.name
type = "CLOUD_IAM_USER"
}
Deployment Workflow
Execute these steps to deploy your Cloud SQL Terraform configuration:
- Initialize Terraform – Download providers and modules:
terraform init
- Validate configuration – Catch syntax errors before any infrastructure changes:
terraform validate
- Plan changes – Review the execution plan with a dry-run:
terraform plan -out=tfplan
- Apply configuration – Provision resources after plan review:
terraform apply tfplan
Application Connectivity: Cloud SQL Auth Proxy
Cloud SQL Terraform pairs with the Cloud SQL Auth Proxy for secure, passwordless connections. In your Cloud Run service configuration, mount the proxy's Unix socket:
containers:
- name: app
image: gcr.io/${PROJECT_ID}/my-app:latest
volumeMounts:
- name: cloudsql-instance
mountPath: /cloudsql
volumes:
- name: cloudsql-instance
cloudSqlInstance:
instances: ["${PROJECT_ID}:${REGION}:${INSTANCE_NAME}"]
Your application connects through the socket path /cloudsql/${PROJECT_ID}:${REGION}:${INSTANCE_NAME} using IAM authentication—no passwords stored or transmitted.
Security Best Practices from the Source Code
The google/skills repository enforces several hardening patterns for Cloud SQL Terraform deployments:
| Practice | Implementation |
|---|---|
| No public IP exposure | ipv4_enabled = false in ip_configuration block |
| Private connectivity only | psc_enabled = true with PSC forwarding rule |
| Least-privilege networking | Firewall rules allowing only TCP 5432 to PSC endpoint and TCP 443 for Auth Proxy token exchange |
| IAM-based authentication | type = "CLOUD_IAM_USER" instead of built-in database passwords |
| Deletion protection | deletion_protection = true to prevent accidental instance destruction |
These patterns appear in SKILL.md and assets/main.tf within the N-Tier Serverless Web App skill directory.
Key Reference Files
| File | Location | Purpose |
|---|---|---|
SKILL.md |
skills/cloud/google-cloud-solution-n-tier-serverless-web-app/SKILL.md |
Architecture overview and Cloud SQL IaC patterns |
assets/main.tf |
skills/cloud/google-cloud-solution-n-tier-serverless-web-app/assets/main.tf |
Complete Terraform module implementation |
references/terraform-usage.md |
skills/cloud/spanner-basics/references/terraform-usage.md |
General Terraform style guide for extending modules |
references/iam-security.md |
skills/cloud/workload-manager-basics/references/iam-security.md |
IAM authentication best practices |
references/general-best-practices.md |
skills/cloud/workload-manager-basics/references/general-best-practices.md |
Cloud-native security principles |
Summary
- Cloud SQL Terraform enables fully declarative database provisioning through HCL configuration files tracked in version control
- Private Service Connect with disabled public IP provides secure, VPC-native connectivity without internet exposure
- IAM database authentication eliminates password management and integrates with Google Cloud's identity system
- Query Insights offers built-in performance monitoring through the
insights_configblock - The
google/skillsrepository provides production-tested modules atassets/main.tfwith security hardening patterns documented inSKILL.md
Frequently Asked Questions
What is the difference between Private Service Connect and private IP for Cloud SQL?
Private Service Connect establishes a private, consumer-side endpoint that routes traffic through Google's network backbone without exposing IPs publicly. Traditional private IP requires VPC peering and allocates IP addresses from your VPC range. PSC offers simpler routing, better security boundaries, and is the recommended approach in the google/skills Cloud SQL Terraform modules.
How does IAM database authentication work with Terraform-managed Cloud SQL?
Set type = "CLOUD_IAM_USER" in the google_sql_user resource. Users authenticate with OAuth 2.0 tokens instead of passwords, and the Cloud SQL Auth Proxy validates these tokens automatically. Your Terraform configuration grants roles/cloudsql.client to service accounts, enabling applications to connect without credential files.
Can I enable high availability through Cloud SQL Terraform?
Yes. Set availability_type = "REGIONAL" in the settings block of google_sql_database_instance. This creates a synchronous standby in a different zone within the same region, providing automatic failover without data loss. The configuration in assets/main.tf demonstrates this pattern combined with deletion protection for production safety.
Should I use terraform.tfvars or environment variables for sensitive values?
Use environment variables prefixed with TF_VAR_ for sensitive values like project IDs and service account emails, or integrate with Google Secret Manager via the google_secret_manager_secret_version data source. Never commit credentials to terraform.tfvars in version control. The references/terraform-usage.md file shows variable passing patterns compatible with Cloud Shell and CI/CD pipelines.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →