Google Cloud
Connect a Google Cloud project with a service account key, prepare the GCS state bucket, and see what OrkStage creates on Cloud Run, Cloud SQL and Memorystore.
Preview
The Google Cloud adapter is covered by unit tests and its OpenTofu modules pass tofu validate.
It has not been verified against a live project yet.
OrkStage creates Google Cloud resources with the OpenTofu modules in
orkstage-modules/modules/gcp, one isolated state per resource, kept in a GCS bucket you own.
Health, logs, secrets and redeploys go through the Google Cloud REST APIs.
What OrkStage creates
| Template resource | Capability | What gets created |
|---|---|---|
network | vpc (default) | Custom mode VPC, one regional subnet with private Google access, a private services access range for Cloud SQL and Memorystore, Cloud NAT when natGateway is set |
compute.container-service | cloud-run (default) | Cloud Run v2 service with its own service account. Direct VPC egress into the subnet when a network is in the slot (all traffic through NAT when the network has one). replicas or the autoscaling range sets the instance bounds. Public services accept unauthenticated calls; the others accept internal traffic only. |
database.postgresql | cloud-sql-postgres (default) | Cloud SQL Enterprise edition, private IP only when a network is in the slot. Regional availability for zone-redundant HA, backups with point in time recovery, deletion protection in production, TLS required. |
cache.redis | memorystore-redis (default) | Memorystore for Redis: Basic tier without replicas, Standard tier with one replica, read replicas from two. AUTH on. |
object-storage | gcs (default) | Bucket with uniform access, public access prevention unless publicAccess, versioning, class change after 30 days for infrequent (Nearline) and archive, expiry from retentionDays |
ingress | cloud-run-ingress (default) | Nothing: each routed service uses the HTTPS URL Cloud Run gives it and becomes public |
Cloud Run services mount database and cache credentials from Secret Manager as
<ID>_CREDENTIALS, and get read and write access to the buckets they depend on.
The PostgreSQL app password lives in OpenTofu state and in a Secret Manager secret
(secret_ref). The Redis AUTH string is stored in Secret Manager too. readSecret returns
username, password, host, port, database and url for PostgreSQL, and password,
host, port and url for Redis, so a resource on another provider can connect.
Target configuration
config field | Required | Example | Meaning |
|---|---|---|---|
projectId | yes | acme-prod-123 | Project id, not the project number |
stateBucket | yes | acme-orkstage-state | Existing GCS bucket for OpenTofu state. OrkStage never creates it. |
Credential secret
The secret behind credentialRef is the service account key JSON file exactly as Google issues
it. The adapter needs client_email and private_key, and also reads private_key_id and
project_id when present.
{
"type": "service_account",
"project_id": "acme-prod-123",
"private_key_id": "<key id>",
"private_key": "<PEM private key>",
"client_email": "orkstage-deployer@acme-prod-123.iam.gserviceaccount.com"
}The key signs a short JWT that is exchanged for an OAuth access token, cached in memory. It
reaches OpenTofu only as the GOOGLE_CREDENTIALS environment variable of one runner command.
Workload identity federation, with no long lived key, is planned.
gcloud iam service-accounts create orkstage-deployer --project acme-prod-123 --display-name "OrkStage deployer"
gcloud iam service-accounts keys create key.json --iam-account orkstage-deployer@acme-prod-123.iam.gserviceaccount.com
# Store the content of key.json in the secret store, then delete the local file.Prepare state storage
Create the bucket once, in the region you deploy to most:
gcloud storage buckets create gs://acme-orkstage-state --project acme-prod-123 --location us-central1 \
--uniform-bucket-level-access --public-access-prevention
gcloud storage buckets update gs://acme-orkstage-state --versioningThe state of a resource is the object orkstage/<name>.tfstate/default.tfstate. The
configuration applied is kept beside it as orkstage/<name>.tfstate.config.json, so destroy never
depends on a newer template.
APIs and permissions
Enable the APIs the modules use. Validation reports any that are off.
gcloud services enable compute.googleapis.com servicenetworking.googleapis.com run.googleapis.com \
iam.googleapis.com secretmanager.googleapis.com sqladmin.googleapis.com redis.googleapis.com \
storage.googleapis.com logging.googleapis.com --project acme-prod-123Grant these roles to the deployer service account on the project:
| Role | Why |
|---|---|
roles/browser | Validation reads the project |
roles/serviceusage.serviceUsageViewer | Validation checks enabled APIs |
roles/compute.networkAdmin | VPC, subnet, private services range, Cloud Router and NAT |
roles/servicenetworking.networksAdmin | Private services access peering |
roles/run.admin | Cloud Run services and redeploys |
roles/iam.serviceAccountAdmin, roles/iam.serviceAccountUser | One runtime service account per Cloud Run service |
roles/cloudsql.admin | Cloud SQL instances, databases and users |
roles/redis.admin | Memorystore instances |
roles/storage.admin | Buckets, bucket IAM and the state bucket |
roles/secretmanager.admin | Credential secrets, their IAM bindings and readSecret |
roles/logging.viewer | Service logs in the console |
Regions
Regions are Google Cloud regions such as us-central1, southamerica-east1 or europe-west1.
Subnets span every zone of a region, so availabilityZones does not change the network layout.
Actions for triggers
| Capability | Action | Parameters | Effect |
|---|---|---|---|
cloud-run | redeploy | none | Starts a new Cloud Run revision with the current image and settings, replacing every running instance |
Known limits
- Cloud Run CPU is rounded up to 1, 2, 4, 6 or 8 vCPU, and memory is raised to the minimum for that CPU. Fractional CPU would force one request per instance.
- Cloud Run scales on request concurrency.
targetCpuPercentis not used. - There is no shared HTTPS load balancer with path routing yet. Each service keeps its own
run.appURL. - Same zone HA is not offered for Cloud SQL; regional availability is the HA option.
- A PostgreSQL instance without a network gets a public IP with no authorized networks, reachable only through Cloud SQL connectors.
- Memorystore needs a network in the same slot and runs without in transit encryption; traffic stays inside the VPC. Two or more replicas need at least 5 GB, so small sizes are raised.
- The private services peering is abandoned on destroy and removed with the network.
- Credentials of dependencies outside Google Cloud are not mounted into Cloud Run.
Microsoft Azure
Connect an Azure subscription with a service principal, prepare the Blob state container, and see what OrkStage creates on Container Apps and Flexible Server.
Oracle Cloud Infrastructure
Connect an OCI compartment with an API signing key, prepare the state bucket and vault, and see what OrkStage creates on Container Instances and OCI PostgreSQL.