Reference Terraform

Terraform Integration

LocalCloud works with the standard hashicorp/google Terraform provider. Your existing .tf files run against LocalCloud without modification — just set environment variables to redirect the provider to localhost.

Quick Start

# 1. Start LocalCloud
docker run -d \
  -p 8080:8080 -p 4443:4443 \
  -p 8085-8087:8085-8087 \
  -p 9010:9010 -p 9020:9020 \
  -p 9050:9050 -p 9060:9060 \
  -p 6379:6379 \
  -m 4g --name localcloud \
  jaysen2apache/localcloud

# 2. Point Terraform at LocalCloud
eval $(curl -s 'http://localhost:8080/_localcloud/env?format=terraform')

# 3. Run Terraform normally
terraform init
terraform plan
terraform apply

The /_localcloud/env?format=terraform endpoint exports GOOGLE_*_CUSTOM_ENDPOINT variables for all enabled services, plus GOOGLE_APPLICATION_CREDENTIALS=/dev/null to bypass authentication.

Provider Configuration

No changes to your provider block. The standard configuration works:

terraform {
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = ">= 5.0"
    }
  }
}

provider "google" {
  project = "local-project"
  region  = "us-central1"
}

Environment Variables

When you run eval $(curl -s 'http://localhost:8080/_localcloud/env?format=terraform'), the following variables are set:

VariableValueService
GOOGLE_STORAGE_CUSTOM_ENDPOINThttp://localhost:4443Cloud Storage
GOOGLE_PUBSUB_CUSTOM_ENDPOINThttp://localhost:8085Pub/Sub
GOOGLE_BIGQUERY_CUSTOM_ENDPOINThttp://localhost:9050BigQuery
GOOGLE_SPANNER_CUSTOM_ENDPOINThttp://localhost:9020Spanner (REST)
GOOGLE_FIRESTORE_CUSTOM_ENDPOINThttp://localhost:8086Firestore
GOOGLE_BIGTABLE_CUSTOM_ENDPOINThttp://localhost:8087Bigtable
GOOGLE_SECRET_MANAGER_CUSTOM_ENDPOINThttp://localhost:8080Secret Manager
GOOGLE_CLOUD_TASKS_CUSTOM_ENDPOINThttp://localhost:8080Cloud Tasks
GOOGLE_COMPUTE_CUSTOM_ENDPOINThttp://localhost:8080Compute Engine
GOOGLE_CLOUD_RUN_CUSTOM_ENDPOINThttp://localhost:8080Cloud Run
GOOGLE_CONTAINER_CUSTOM_ENDPOINThttp://localhost:8080GKE
GOOGLE_LOGGING_CUSTOM_ENDPOINThttp://localhost:8080Cloud Logging
GOOGLE_MONITORING_CUSTOM_ENDPOINThttp://localhost:8080Cloud Monitoring
GOOGLE_APPLICATION_CREDENTIALS/dev/nullAuth bypass
GOOGLE_PROJECTlocal-projectAll services

Example Configuration

# Cloud Storage
resource "google_storage_bucket" "data" {
  name          = "my-data-bucket"
  location      = "us-central1"
  force_destroy = true
}

# Pub/Sub
resource "google_pubsub_topic" "events" {
  name = "user-events"
}

resource "google_pubsub_subscription" "processor" {
  name  = "event-processor"
  topic = google_pubsub_topic.events.id
  ack_deadline_seconds = 20
}

# BigQuery
resource "google_bigquery_dataset" "analytics" {
  dataset_id = "analytics"
  location   = "us-central1"
}

resource "google_bigquery_table" "events" {
  dataset_id = google_bigquery_dataset.analytics.dataset_id
  table_id   = "events"

  schema = jsonencode([
    { name = "event_id", type = "STRING", mode = "REQUIRED" },
    { name = "event_type", type = "STRING", mode = "NULLABLE" },
    { name = "created_at", type = "TIMESTAMP", mode = "NULLABLE" },
  ])
}

# Spanner
resource "google_spanner_instance" "main" {
  name         = "local-instance"
  config       = "emulator-config"
  display_name = "Local Instance"
  num_nodes    = 1
}

resource "google_spanner_database" "db" {
  instance = google_spanner_instance.main.name
  name     = "my-database"
}

# Secret Manager
resource "google_secret_manager_secret" "api_key" {
  secret_id = "api-key"

  replication {
    auto {}
  }
}

Resource Compatibility

Fully Supported

ResourceBackend
google_storage_bucketGCS (fake-gcs-server)
google_storage_bucket_objectUpload/download objects
google_pubsub_topicPub/Sub emulator
google_pubsub_subscriptionWith ack_deadline, message_retention
google_bigquery_datasetDuckDB-based emulator
google_bigquery_tableSchema definition, create, delete
google_spanner_instanceSpanner emulator
google_spanner_databaseDDL, create, delete

Partially Supported

ResourceNotes
google_secret_manager_secretgRPC works; REST transcoding in progress
google_secret_manager_secret_versionSame
google_cloud_tasks_queueSame

Not Supported

ResourceReason
google_projectProjects managed via /_localcloud/projects API
google_project_iam_*IAM is permissive by default
google_service_accountNot emulated
google_dns_*DNS not emulated
google_sql_*Cloud SQL not emulated
google_vpc_* / google_compute_networkNetworking not emulated

Authentication

LocalCloud runs in permissive IAM mode by default — no credentials required. Setting GOOGLE_APPLICATION_CREDENTIALS=/dev/null tells the Google provider to skip real GCP authentication. All requests are accepted without token validation.

CI/CD Integration

GitHub Actions

name: Terraform Integration Test

on:
  pull_request:
    paths: ['*.tf', 'terraform/**']

jobs:
  terraform-test:
    runs-on: ubuntu-latest
    services:
      localcloud:
        image: jaysen2apache/localcloud
        ports:
          - 8080:8080
          - 4443:4443
          - 8085-8087:8085-8087
          - 9010:9010
          - 9020:9020
          - 9050:9050
          - 9060:9060
          - 6379:6379
        options: >-
          --memory 4g
          --health-cmd "curl -f http://localhost:8080/_localcloud/health"
          --health-interval 10s
          --health-timeout 5s
          --health-retries 10

    steps:
      - uses: actions/checkout@v4
      - uses: hashicorp/setup-terraform@v3
        with:
          terraform_version: "1.9"

      - name: Wait for LocalCloud
        run: |
          for i in $(seq 1 30); do
            if curl -sf http://localhost:8080/_localcloud/health > /dev/null; then
              echo "LocalCloud is ready"
              break
            fi
            sleep 2
          done

      - name: Configure Terraform for LocalCloud
        run: eval $(curl -s http://localhost:8080/_localcloud/env?format=terraform) >> $GITHUB_ENV

      - name: Terraform Init & Apply
        run: |
          terraform init
          terraform plan -out=tfplan
          terraform apply -auto-approve tfplan

      - name: Terraform Destroy
        if: always()
        run: terraform destroy -auto-approve

Moving to Production

To switch from LocalCloud to real GCP, unset the environment variables:

unset GOOGLE_STORAGE_CUSTOM_ENDPOINT
unset GOOGLE_PUBSUB_CUSTOM_ENDPOINT
unset GOOGLE_BIGQUERY_CUSTOM_ENDPOINT
unset GOOGLE_SPANNER_CUSTOM_ENDPOINT
# ... unset all GOOGLE_*_CUSTOM_ENDPOINT vars

# Set real credentials
export GOOGLE_APPLICATION_CREDENTIALS=path/to/service-account.json
export GOOGLE_PROJECT=my-real-project

terraform plan   # now targets real GCP

Your .tf files require zero changes.