Google Compute Engine
Set up the dedicated service account, sandbox VPC, firewall rules, and Cloud Run preview proxy that back the GCE sandbox provider.
The google-compute-engine integration wraps the ~150 low-level gce_* REST actions plus the high-level gce_sandbox_* orchestration tools that the GCE-backed SandboxProvider uses. None of those tools work until the GCP-side scaffolding below is in place: an IAM-scoped service account, an isolated VPC, an IAP-only firewall rule, and (for preview URLs) a Cloud Run reverse proxy.
This guide assumes the project nova-admin and zone us-central1-a. Swap names if you're working in a different project.
Prerequisites
gcloudCLI authenticated as a principal with Owner or Project IAM Admin onnova-admin.compute.googleapis.comandiap.googleapis.comenabled (commands below enable them if not).- One free-tier
e2-standard-2quota slot inus-central1(matches the existing crabbox quota; nothing new to request).
gcloud config set project nova-admin
gcloud services enable compute.googleapis.com iap.googleapis.com run.googleapis.com1. Service account
The sandbox provider acts as nova-admin-gce-sandbox@nova-admin.iam.gserviceaccount.com. Its key is the only credential that ends up in nova-admin; it never touches user identity.
gcloud iam service-accounts create nova-admin-gce-sandbox \
--display-name="Nova Admin GCE sandbox provider" \
--description="Non-human SA used by nova-admin's GCE SandboxProvider"2. IAM roles
Two roles, both scoped narrowly. compute.admin is wide but required for VM lifecycle + image baking; the trade-off is documented in the GCE sandbox provider design.
SA="nova-admin-gce-sandbox@nova-admin.iam.gserviceaccount.com"
gcloud projects add-iam-policy-binding nova-admin \
--member="serviceAccount:${SA}" \
--role="roles/compute.admin"
gcloud projects add-iam-policy-binding nova-admin \
--member="serviceAccount:${SA}" \
--role="roles/iap.tunnelResourceAccessor"3. Sandbox VPC
Sandbox VMs live in their own VPC with no public IPs. All ingress is funneled through Identity-Aware Proxy (IAP) — the proxy and Cloud Functions reach VMs only via IAP tunnels.
gcloud compute networks create sandbox-vpc \
--subnet-mode=custom \
--description="Isolated VPC for nova-admin sandbox VMs"
gcloud compute networks subnets create sandbox-us-central1 \
--network=sandbox-vpc \
--region=us-central1 \
--range=10.20.0.0/164. Firewall rule (IAP → 22 + 3000 + 8443)
IAP's TCP-forwarding source range is the well-known 35.235.240.0/20. The rule below allows that range to reach the SSH port plus the two app ports the sandbox provider expects (3000 for bun run dev, 8443 for the WSS terminal). Everything else is denied by VPC default.
gcloud compute firewall-rules create sandbox-allow-iap \
--network=sandbox-vpc \
--direction=INGRESS \
--action=ALLOW \
--rules=tcp:22,tcp:3000,tcp:8443 \
--source-ranges=35.235.240.0/20 \
--target-tags=sandbox-vm \
--description="IAP-only ingress to sandbox VMs (SSH + dev server + terminal)"Every sandbox VM the provider creates is tagged sandbox-vm automatically — the tag is what binds VMs to this rule.
5. Service-account key for nova-admin
Generate the JSON key the integration dialog will consume. Keep this file off git and out of .env.local-tracked paths.
gcloud iam service-accounts keys create ~/nova-admin-gce-sandbox.json \
--iam-account="nova-admin-gce-sandbox@nova-admin.iam.gserviceaccount.com"In Nova Admin, go to /agents/integrations, find Google Compute Engine, and paste:
projectId:nova-adminclientEmail:nova-admin-gce-sandbox@nova-admin.iam.gserviceaccount.comprivateKey: theprivate_keystring from the JSON file (preserve\nline breaks)
Save. The dialog will run a credential-validation ping against the live GCE API before persisting.
6. Cloud Run preview proxy (optional — for share-link previews)
The gce-sandbox-proxy Cloud Run service is what makes gce_sandbox_share_create URLs actually loadable in a browser. It opens an IAP tunnel to the target VM on demand and proxies HTTP/WSS through to it.
Without this service deployed, the gce_sandbox_* action surface still works — agents can claim, exec, bake, etc. — but the share URLs return 502. Skip this step if you're not yet shipping shared previews.
# Deploy the proxy. Code lands in PR 8 of the GCE roadmap.
gcloud run deploy gce-sandbox-proxy \
--source=apps/admin/services/gce-sandbox-proxy \
--service-account="nova-admin-gce-sandbox@nova-admin.iam.gserviceaccount.com" \
--region=us-central1 \
--vpc-connector=sandbox-vpc-connector \
--no-allow-unauthenticatedAfter it deploys, copy the *.run.app URL into GCE_SANDBOX_PROXY_BASE_URL in Firebase Secret Manager. The provider reads this env var when minting share links.
7. Smoke test
From a thread, ask any agent that has gce_* in its allowedTools:
"ping the GCE sandbox tools"
The agent should invoke gce_sandbox_ping. A response of "pong" confirms the credentials parse and the action registry sees the integration. Then try:
"list GCE pools"
This invokes gce_sandbox_pool_list and returns the seeded pooriaarab/Nova pool. If the pool is missing, run bun packages/cli/src/index.ts seed run sandbox-pools.
What lives where
| Where | What |
|---|---|
gcloud (this guide) | Service account + IAM roles + VPC + firewall rule + Cloud Run deploy |
/agents/integrations | Service-account credentials (projectId, clientEmail, privateKey) |
/agents/skills | Per-repo GCE config (machine type, bake script, ingress ports, cost cap) — see the sandbox provider design |
/agents/sandboxes | Pools + claimed VMs + bake jobs (live state) |
| Firebase Secret Manager | GCE_SANDBOX_PROXY_BASE_URL, any future provider-wide secrets |
Cost notes
- Idle: ~$0/day. The shared warm box (one
e2-standard-2) is the only thing that runs 24/7 if you leave it on.bin/crabbox-warm-shared.sh --stopbrings it to zero overnight. - Per claim: one
e2-standard-2× claim duration. A typical PR-verification flow costs <$0.10 round-trip. - Cloud Run: scales to zero. Per-share-URL traffic adds ~$5–20/mo at moderate demo volume.
Troubleshooting
PERMISSION_DENIEDoncompute.instances.insert: SA is missingcompute.adminon the project — re-run step 2.- IAP tunnel hangs at "establishing tunnel": firewall rule's
source-rangesdoesn't match35.235.240.0/20, or the target VM isn't taggedsandbox-vm. invalid_grant: Invalid JWT signaturefrom nova-admin: theprivateKeyin the integration dialog had its\nline breaks stripped on paste. Re-paste from the original JSON.- Share URL returns 502: the Cloud Run proxy isn't deployed or
GCE_SANDBOX_PROXY_BASE_URLis wrong.