Skip to main content

GCP Setup Guide

CODITECT Infrastructure on Google Cloud Platform

Last Updated: November 23, 2025


Table of Contents

  1. Prerequisites
  2. GCP Project Setup
  3. Enable APIs
  4. Service Accounts
  5. Networking
  6. GKE Cluster
  7. Cloud SQL
  8. Secrets Management
  9. Billing & Cost Management

Prerequisites

Required Tools

# Install gcloud CLI
curl https://sdk.cloud.google.com | bash
exec -l $SHELL

# Initialize gcloud
gcloud init

# Install kubectl
gcloud components install kubectl

# Install Terraform
brew install terraform # macOS
# OR
wget https://releases.hashicorp.com/opentofu/1.6.0/terraform_1.6.0_linux_amd64.zip

GCP Account Requirements

  • Organization Account: (recommended for production)
  • Billing Account: Active billing account required
  • IAM Roles: Project Owner or Editor
  • Quota: Sufficient quota for GKE, Cloud SQL

GCP Project Setup

Create Projects

# Set organization ID (if applicable)
export ORG_ID=$(gcloud organizations list --format="value(name)")

# Create development project
gcloud projects create coditect-dev \
--organization=$ORG_ID \
--name="CODITECT Development" \
--set-as-default

# Create staging project
gcloud projects create coditect-staging \
--organization=$ORG_ID \
--name="CODITECT Staging"

# Create production project
gcloud projects create coditect-production \
--organization=$ORG_ID \
--name="CODITECT Production"
# List billing accounts
gcloud billing accounts list

# Set billing account ID
export BILLING_ACCOUNT_ID=XXXXXX-XXXXXX-XXXXXX

# Link projects to billing
gcloud billing projects link coditect-dev \
--billing-account=$BILLING_ACCOUNT_ID

gcloud billing projects link coditect-staging \
--billing-account=$BILLING_ACCOUNT_ID

gcloud billing projects link coditect-production \
--billing-account=$BILLING_ACCOUNT_ID

Enable APIs

Required APIs

# Set project
gcloud config set project coditect-dev

# Enable all required APIs
gcloud services enable \
compute.googleapis.com \
container.googleapis.com \
sqladmin.googleapis.com \
storage.googleapis.com \
secretmanager.googleapis.com \
cloudresourcemanager.googleapis.com \
iam.googleapis.com \
iamcredentials.googleapis.com \
cloudbuild.googleapis.com \
artifactregistry.googleapis.com \
monitoring.googleapis.com \
logging.googleapis.com \
cloudtrace.googleapis.com

# Verify APIs enabled
gcloud services list --enabled

Service Accounts

Create Service Accounts

# Terraform service account
gcloud iam service-accounts create terraform-sa \
--description="Terraform infrastructure provisioning" \
--display-name="Terraform SA"

# GKE service account
gcloud iam service-accounts create gke-sa \
--description="GKE node service account" \
--display-name="GKE SA"

# Cloud SQL service account
gcloud iam service-accounts create cloudsql-sa \
--description="Cloud SQL client connections" \
--display-name="Cloud SQL SA"

# Django application service account
gcloud iam service-accounts create django-app-sa \
--description="Django application runtime" \
--display-name="Django App SA"

Assign IAM Roles

export PROJECT_ID=coditect-dev

# Terraform SA - broad permissions for infrastructure
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:terraform-sa@${PROJECT_ID}.iam.gserviceaccount.com" \
--role="roles/editor"

gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:terraform-sa@${PROJECT_ID}.iam.gserviceaccount.com" \
--role="roles/iam.securityAdmin"

# GKE SA - minimal permissions
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:gke-sa@${PROJECT_ID}.iam.gserviceaccount.com" \
--role="roles/logging.logWriter"

gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:gke-sa@${PROJECT_ID}.iam.gserviceaccount.com" \
--role="roles/monitoring.metricWriter"

# Cloud SQL SA
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:cloudsql-sa@${PROJECT_ID}.iam.gserviceaccount.com" \
--role="roles/cloudsql.client"

# Django App SA
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:django-app-sa@${PROJECT_ID}.iam.gserviceaccount.com" \
--role="roles/secretmanager.secretAccessor"

gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:django-app-sa@${PROJECT_ID}.iam.gserviceaccount.com" \
--role="roles/storage.objectViewer"

Download Service Account Keys

# Terraform SA key (for local development)
gcloud iam service-accounts keys create terraform-key.json \
--iam-account=terraform-sa@${PROJECT_ID}.iam.gserviceaccount.com

# IMPORTANT: Store securely and never commit to git
mv terraform-key.json ~/.config/gcloud/terraform-key.json
chmod 600 ~/.config/gcloud/terraform-key.json

# Set environment variable
export GOOGLE_APPLICATION_CREDENTIALS=~/.config/gcloud/terraform-key.json

Networking

Create VPC Network

# Create VPC
gcloud compute networks create coditect-vpc \
--subnet-mode=custom \
--bgp-routing-mode=regional

# Create GKE subnet
gcloud compute networks subnets create gke-subnet \
--network=coditect-vpc \
--region=us-central1 \
--range=10.0.0.0/20 \
--enable-private-ip-google-access \
--secondary-range pods=10.1.0.0/16 \
--secondary-range services=10.2.0.0/16

# Create database subnet
gcloud compute networks subnets create db-subnet \
--network=coditect-vpc \
--region=us-central1 \
--range=10.0.16.0/24 \
--enable-private-ip-google-access

# Create Redis subnet
gcloud compute networks subnets create redis-subnet \
--network=coditect-vpc \
--region=us-central1 \
--range=10.0.17.0/24 \
--enable-private-ip-google-access

Configure Firewall Rules

# Allow internal communication
gcloud compute firewall-rules create allow-internal \
--network=coditect-vpc \
--allow=tcp,udp,icmp \
--source-ranges=10.0.0.0/16

# Allow HTTPS from internet
gcloud compute firewall-rules create allow-https \
--network=coditect-vpc \
--allow=tcp:443 \
--source-ranges=0.0.0.0/0 \
--target-tags=https-server

# Allow SSH from Cloud Identity-Aware Proxy
gcloud compute firewall-rules create allow-ssh-iap \
--network=coditect-vpc \
--allow=tcp:22 \
--source-ranges=35.235.240.0/20

Create NAT Gateway

# Create Cloud Router
gcloud compute routers create nat-router \
--network=coditect-vpc \
--region=us-central1

# Create NAT configuration
gcloud compute routers nats create nat-config \
--router=nat-router \
--region=us-central1 \
--auto-allocate-nat-external-ips \
--nat-all-subnet-ip-ranges

GKE Cluster

Create GKE Autopilot Cluster

# Create cluster
gcloud container clusters create-auto coditect-gke \
--region=us-central1 \
--network=coditect-vpc \
--subnetwork=gke-subnet \
--cluster-secondary-range-name=pods \
--services-secondary-range-name=services \
--enable-private-nodes \
--enable-private-endpoint \
--master-ipv4-cidr=172.16.0.0/28 \
--no-enable-master-authorized-networks \
--enable-ip-alias \
--enable-autorepair \
--enable-autoupgrade \
--service-account=gke-sa@${PROJECT_ID}.iam.gserviceaccount.com \
--workload-pool=${PROJECT_ID}.svc.id.goog \
--release-channel=regular

# Get credentials
gcloud container clusters get-credentials coditect-gke \
--region=us-central1

# Verify cluster
kubectl get nodes

Configure Workload Identity

# Create Kubernetes service account
kubectl create serviceaccount django-ksa -n default

# Bind to GCP service account
gcloud iam service-accounts add-iam-policy-binding \
django-app-sa@${PROJECT_ID}.iam.gserviceaccount.com \
--member="serviceAccount:${PROJECT_ID}.svc.id.goog[default/django-ksa]" \
--role="roles/iam.workloadIdentityUser"

# Annotate Kubernetes service account
kubectl annotate serviceaccount django-ksa \
iam.gke.io/gcp-service-account=django-app-sa@${PROJECT_ID}.iam.gserviceaccount.com

Cloud SQL

Create PostgreSQL Instance

# Create instance
gcloud sql instances create coditect-postgres \
--database-version=POSTGRES_15 \
--tier=db-custom-4-16384 \
--region=us-central1 \
--network=projects/${PROJECT_ID}/global/networks/coditect-vpc \
--no-assign-ip \
--enable-bin-log \
--backup-start-time=03:00 \
--maintenance-window-day=SUN \
--maintenance-window-hour=04 \
--storage-type=SSD \
--storage-size=100GB \
--storage-auto-increase \
--availability-type=REGIONAL

# Create database
gcloud sql databases create coditect_dev \
--instance=coditect-postgres

# Create user
gcloud sql users create django \
--instance=coditect-postgres \
--password=<SECURE_PASSWORD>

Setup Cloud SQL Proxy

# Install Cloud SQL Proxy
curl -o cloud_sql_proxy https://dl.google.com/cloudsql/cloud_sql_proxy.darwin.amd64
chmod +x cloud_sql_proxy

# Get instance connection name
gcloud sql instances describe coditect-postgres --format="value(connectionName)"

# Run proxy
./cloud_sql_proxy -instances=${PROJECT_ID}:us-central1:coditect-postgres=tcp:5432

Secrets Management

Create Secrets

# Django secret key
echo -n "$(python -c 'from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())')" | \
gcloud secrets create django-secret-key --data-file=-

# Database password
echo -n "SECURE_DATABASE_PASSWORD" | \
gcloud secrets create db-password --data-file=-

# Stripe API key
echo -n "sk_live_YOUR_STRIPE_KEY" | \
gcloud secrets create stripe-api-key --data-file=-

# Grant access to Django app SA
for secret in django-secret-key db-password stripe-api-key; do
gcloud secrets add-iam-policy-binding $secret \
--member="serviceAccount:django-app-sa@${PROJECT_ID}.iam.gserviceaccount.com" \
--role="roles/secretmanager.secretAccessor"
done

Billing & Cost Management

Set Budget Alerts

# Create budget (example: $500/month for dev)
gcloud billing budgets create \
--billing-account=$BILLING_ACCOUNT_ID \
--display-name="CODITECT Dev Monthly Budget" \
--budget-amount=500USD \
--threshold-rule=percent=50 \
--threshold-rule=percent=90 \
--threshold-rule=percent=100

Cost Optimization Tips

Development Environment:

  • Use preemptible VMs where possible
  • Scale down resources outside business hours
  • Use GKE Autopilot (pay per pod)
  • Enable auto-scaling with lower limits

Monitoring:

  • Enable cost allocation labels
  • Review cost breakdown weekly
  • Set up alerts for unexpected spikes

Verification Checklist

After completing setup, verify:

  • All projects created (dev, staging, production)
  • Billing accounts linked
  • Required APIs enabled
  • Service accounts created with proper permissions
  • VPC network and subnets configured
  • Firewall rules in place
  • GKE cluster operational
  • Cloud SQL instance running
  • Secrets created and accessible
  • Budget alerts configured
  • kubectl configured and working
  • Cloud SQL Proxy connection successful

Next Steps

  1. Run Terraform: Initialize infrastructure as code

    cd opentofu/environments/dev
    terraform init
    terraform plan
    terraform apply
  2. Deploy Application: Deploy Django to GKE

    kubectl apply -k kubernetes/base
    kubectl apply -k kubernetes/services
  3. Configure Monitoring: Setup Prometheus and Grafana

    kubectl apply -k kubernetes/monitoring

Troubleshooting

Issue: API not enabled

# List all services
gcloud services list --available

# Enable specific service
gcloud services enable SERVICE_NAME

Issue: Insufficient quota

# Check quota
gcloud compute project-info describe --project=$PROJECT_ID

# Request quota increase via GCP Console
# Compute Engine → Quotas → Select quota → Request increase

Issue: Permission denied

# Check current permissions
gcloud projects get-iam-policy $PROJECT_ID

# Add missing role
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="user:your-email@example.com" \
--role="roles/REQUIRED_ROLE"

Additional Resources


Document Owner: CODITECT Infrastructure Team Review Cycle: Quarterly Next Review: February 2026