Automated, idempotent scaffolding and Terraform management plane for Google Cloud Platform (GCP). Designed for personal accounts and standalone setups without requiring a GCP Organization or Folder hierarchy.
- Prerequisites
- Tool Installation
- GCP Authentication
- Quick Start Guide
- Repository Structure
- Troubleshooting & FAQ
Before getting started, make sure you have:
- Google Cloud Account:
- A personal Google Account (e.g.,
@gmail.comor custom Google Workspace). - Access to the Google Cloud Console.
- A personal Google Account (e.g.,
- Active GCP Billing Account:
- An active billing account is required to create and link projects.
- How to find your Billing Account ID:
- Open GCP Console Billing.
- Select your billing account.
- Look for Billing account ID (format:
01XXXX-XXXXXX-XXXXXX).
- Billing IAM Permissions:
- Your account must have the Billing Account User (
roles/billing.user) or Billing Account Administrator (roles/billing.admin) role on that billing account.
- Your account must have the Billing Account User (
Install the two required command-line tools: the Google Cloud SDK (gcloud) and Terraform.
brew install --cask google-cloud-sdksudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates gnupg curl
curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo gpg --dearmor -o /usr/share/keyrings/cloud.google.gpg
echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main" | sudo tee -a /etc/apt/sources.list.d/google-cloud-sdk.list
sudo apt-get update && sudo apt-get install -y google-cloud-cliFor other operating systems or standalone tarballs, see the official Google Cloud SDK install guide.
Verify the installation:
gcloud versionRequires Terraform >= 1.5.0.
brew tap hashicorp/tap
brew install hashicorp/tap/terraformwget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update && sudo apt install terraformVerify the installation:
terraform versionBecause this repository uses both gcloud CLI scripts and Terraform, authenticate both:
# 1. Log in to gcloud CLI (used by bootstrap scripts)
gcloud auth login
# 2. Log in to Application Default Credentials / ADC (used by Terraform)
gcloud auth application-default login
# 3. Confirm your active logged-in account
gcloud config get-value accountCopy the example configuration to .env in the repository root:
cp .env.example .envOpen .env in your editor and update the required values:
# Project & domain prefix (will create <DOMAIN_NAME>-mgmt project)
DOMAIN_NAME="my-project"
# Your GCP Billing Account ID (from GCP Console -> Billing)
BILLING_ACCOUNT_ID="01XXXX-XXXXXX-XXXXXX"
# Optional: Leave empty if you do not have/want custom Cloud DNS subzones
PARENT_DOMAIN=""
# Optional: Target GCP Region for remote state storage (Default: Singapore)
REGION="asia-southeast1"
# Optional: Collaborator emails to grant Editor / Viewer roles
PROJECT_ADMINS=""
PROJECT_MEMBERS=""Run the pre-flight verification script to ensure your .env settings, CLI authentication, and billing account permissions are valid:
# Live validation against GCP:
./scripts/check_env.sh
# Or offline static syntax validation only:
./scripts/check_env.sh --skip-gcpThe bootstrap script scaffolds the management directory, provisions the management GCP project, links your billing account, enables essential APIs, and provisions a secure GCS remote state bucket.
# 1. Preview changes (Dry-Run / Plan Mode):
./scripts/bootstrap_domain.sh --plan
# 2. Provision and apply:
./scripts/bootstrap_domain.shWhat happens behind the scenes:
- Scaffolds
<domain>-mgmt/from the template. - Creates the GCP management project:
<domain>-mgmt. - Links the project to your
BILLING_ACCOUNT_ID. - Enables foundational APIs (
serviceusage,cloudresourcemanager,secretmanager,iam, etc.). - Creates a versioned Google Cloud Storage bucket (
gs://<domain>-mgmt-tfstate) for Terraform remote state. - Automatically populates
<domain>-mgmt/terraform/terraform.tfvars.
Navigate into the generated management directory and apply the Terraform configuration:
cd <domain>-mgmt/terraform
# 1. Initialize remote GCS backend
terraform init
# 2. Preview infrastructure changes
terraform plan
# 3. Apply baseline configuration
terraform applyThis deploys:
- Project Deletion Protection Lien (prevents accidental deletion of the management project).
- Project IAM Bindings (for any configured
project_adminsandproject_members). - Secret Manager Baseline (secure vault with billing ID metadata).
- Authoritative Cloud DNS Zone (only if
DOMAIN_NAMEandPARENT_DOMAINare set; skipped if empty).
You can launch workloads in two ways depending on your needs:
For simple setups, deploy VMs, containers, or databases directly inside <domain>-mgmt.
For zero blast radius and isolation, instantiate dedicated workload projects using the included example:
cd <domain>-mgmt/terraform
# Copy the workload project template
cp prj-workload.tf.example prj-workload.tf
# Review prj-workload.tf and apply
terraform plan
terraform applyThis creates a dedicated child project (<domain>-workload) linked to your billing account, with its own APIs and service accounts, managed cleanly by Terraform.
.
βββ .env.example # Environment configuration template
βββ README.md # Quick start and runbook (this file)
βββ scripts/
β βββ check_env.sh # Environment and pre-flight validation
β βββ scaffold_domain.sh # Scaffolding tool (template -> <domain>-mgmt)
β βββ bootstrap_domain.sh # Idempotent GCP project & storage bootstrapper
βββ template-mgmt/ # Baseline template for management plane
βββ terraform/
βββ main.tf # GCS backend & deletion protection lien
βββ dns.tf # Cloud DNS managed subzone (conditional)
βββ iam.tf # Project IAM roles (Editor, Viewer)
βββ secrets.tf # Secret Manager vault
βββ variables.tf # Terraform input variables
βββ outputs.tf # Outputs (DNS, nameservers, etc.)
βββ prj-workload.tf.example# Starter template for child projects
βββ terraform.tfvars.example
1. Error: "The caller does not have permission" or Billing link failure
Ensure your authenticated account has roles/billing.user or roles/billing.admin on the billing account:
gcloud billing accounts get-iam-policy YOUR_BILLING_ACCOUNT_IDAlso verify you logged into the correct account:
gcloud config get-value account2. Error: "google: could not find default credentials" when running Terraform
Terraform uses Application Default Credentials (ADC), which is separate from gcloud auth login. Run:
gcloud auth application-default login3. Do I need a domain name or DNS delegation?
No. If you leave PARENT_DOMAIN="" in .env, Cloud DNS is automatically skipped in Terraform, and you can use the GCP project without any custom domain.
4. How to tear down or clean up resources?
To destroy resources managed by Terraform:
cd <domain>-mgmt/terraform
terraform destroy(Note: If deletion protection liens were enabled, remove or comment out the lien in main.tf first before destroying the project).