Skip to main content

Ship Astro to Cloud Run β€” keyless & cost-optimized

Astro β†’ Cloud Run, keyless & ~$0/mo. Workload Identity Federation, scale-to-zero economics, and a hardened, fully reproducible IaC stack.

astro-gcp-cloudrun-starter Hero Image
Principles: Keyless identity Β· Reproducible IaC Β· Scale-to-zero by default

What you get

A secure, cheap path from repo to public URL

Everything needed to stand up a containerized web app on Cloud Run β€” with no service-account keys, no secrets in git, and a perpetual-free-tier cost profile.

Keyless Workload Identity Federation

GitHub Actions exchanges its OIDC token for short-lived GCP credentials at deploy time. No service-account JSON keys exist anywhere β€” nothing to leak from a public repo. The WIF provider is scoped to this exact repository.

Terraform-managed infrastructure

Bootstrap, shared, and per-environment layers provision projects, Artifact Registry, Cloud Run, IAM, monitoring, logging, and budgets. State lives in GCS. Every change is reviewable and reproducible.

Scale-to-zero cost optimization

min-instances = 0, a low max-instances cap, the smallest sensible CPU/memory, and a billing budget with alerts. An idle public demo costs effectively ~$0/month within the perpetual free tier.

Zero secrets in the repo

Identity is keyless; app runtime secrets (if any) live in Google Secret Manager, injected into Cloud Run. Only placeholder .example files are committed β€” real values stay in GitHub Variables and your untracked tfvars.

Security-hardened by default

Non-root, multi-stage container (~25MB nginx image), least-privilege deploy identity that cannot alter infrastructure, repo-scoped federation, and feature-gated network/DB modules off on day one.

Astro v6 + Tailwind CSS v4

A fast, SEO-friendly static site with a blog, RSS, image optimization, and dark mode β€” built with the latest Astro and Tailwind, served by nginx on Cloud Run.

Architecture

Bootstrap β†’ Shared β†’ Environment, all in Terraform

Reproducible from the seed up

A new engineer can stand up an identical environment from the Setup Playbook and the Terraform configuration β€” with zero tribal knowledge.

Two-stage bootstrap

A one-time seed creates the GCP projects, a GCS state bucket, and an automation service account, then migrates its own state into GCS.

Shared layer

Provisions the Workload Identity pool/provider, the GitHub deploy service account, and the Artifact Registry that every environment pulls from.

Environment layers

dev / staging / prod each adopt their bootstrap-created project and stand up Cloud Run, IAM, monitoring, logging, and a billing budget β€” feature-gated extras off by default.

Built so there is nothing sensitive to expose, and nothing costly to leave running.

Keyless deploy flow

Push to main β†’ GitHub Actions authenticates via WIF β†’ builds the Astro container β†’ pushes to Artifact Registry β†’ deploys a new Cloud Run revision β†’ smoke-tests the public URL.

App-deploy-only CI

The pipeline only ships images; it cannot modify infrastructure. Terraform is run deliberately from a controlled environment, keeping the deploy identity least-privilege.

Cost guardrails baked in

A per-project billing budget with 50/80/100% alerts and a low max-instances cap mean a public URL anyone can hit cannot autoscale into a surprise bill.

Verified secret-clean

No real IDs, keys, or secrets in files, history, or CI logs β€” only the intended public demo URL and committed .example placeholders.

From template to a live, public Cloud Run URL β€” in about 30–45 minutes.

Step 1: Use this template

Click 'Use this template' on GitHub (or clone it). Copy each .example to its real, git-ignored counterpart and fill in your values β€” billing account, project prefix, region.

Step 2: Bootstrap GCP

Authenticate keylessly with gcloud, run the bootstrap module to create your projects, state bucket, and automation SA, then apply the shared and dev layers with Terraform.

Step 3: Wire CI & deploy

Set the GitHub Actions Variables from your Terraform outputs (no secrets), push to main, and watch the keyless pipeline build and deploy your site to Cloud Run.

Live!

Steps image

The stack

What's in the box

A complete, modular Terraform foundation plus a polished Astro front end.

Cloud Run

Serverless container hosting with scale-to-zero, CPU throttling, and a public unauthenticated demo.

Workload Identity Federation

Keyless GitHub→GCP auth, scoped to this repo. No service-account keys anywhere.

Artifact Registry

Private Docker registry in the shared project, with image retention policies.

Terraform modules

iam, cloud_run, artifact_registry, monitoring, logging, secret_manager, cost_governance, and more.

Cost governance

A billing budget per project with 50/80/100% alerts β€” your sleep-at-night control.

Monitoring & logging

Uptime checks, an availability SLO, alert policies, and audit log export β€” on by default.

Secret Manager

For any real runtime secret β€” injected into Cloud Run, never near the repo.

Feature-gated extras

VPC, Cloud SQL, DNS, Load Balancer, Cloud Armor, Vertex AI β€” all off on day one for cost.

Astro + nginx container

A ~25MB, non-root, multi-stage image serving the static build on port 8080.

Guides & deep dives on the blog

View all posts Β»

The blog documents how this template works β€” deploying to Cloud Run, the keyless Workload Identity Federation setup, the Terraform layers, and how the demo stays within the free tier.

FAQs

Frequently Asked Questions

The questions people ask before adopting a public GCP starter template.

How much does the demo cost to run?

Effectively ~$0/month. With min-instances = 0 the service scales to zero and is not billed while idle, and a low-traffic static demo stays within Cloud Run’s perpetual free tier. A billing budget alert is created automatically as a backstop. (An estimate, not a guarantee β€” model your traffic with the GCP pricing calculator.)

Is it safe that the repo is public?

Yes β€” that’s the core design. Identity is keyless via Workload Identity Federation, so there is no service-account key to leak. No secrets live in files, history, or CI logs; only placeholder .example files are committed.

What does β€œkeyless” actually mean?

GitHub Actions presents an OIDC token that GCP exchanges for a short-lived credential at deploy time. The WIF provider only trusts tokens from this exact repository, so no other repo β€” even under the same owner β€” can assume the deploy identity.

What do I need to deploy it myself?

A GCP billing account, the gcloud CLI, Terraform, and Docker. Follow the Setup Playbook and the Fresh User Walkthrough: bootstrap β†’ shared β†’ dev β†’ set GitHub Variables β†’ push to main. About 30–45 minutes of active work.

Can I use my own framework instead of Astro?

Yes. The root Dockerfile is the contract: build your app and serve it on port 8080. Swap the source and the build steps; the Terraform foundation and CI are framework-agnostic.

How do I add a custom domain or a backend later?

The template ships feature-gated modules for DNS, Load Balancer, Cloud Armor, VPC, and Cloud SQL β€” all disabled by default for cost. Enable them in your tfvars when you actually need them.

~$0
Monthly cost (idle)
0
SA JSON keys
~40m
Time to deploy
100%
IaC coverage

Astro + 
GCP Cloud Run

Keyless, reproducible, and ~$0/month.Branch it, configure it, and deploy your own in under an hour.