Deploy on Cloud Run (Sandbox)
This guide deploys a single-node Scion Hub on a Cloud Run Instance. Agents run as Cloud Run Sandboxes inside the same Instance — one container image, one deploy command, no external database or storage to provision.
What you will set up:
| Component | Provided by | Purpose |
|---|---|---|
| Hub + Broker | Cloud Run Instance | Control plane, API, web UI |
| Agent runtime | Cloud Run Sandboxes | Isolated agent containers |
| Database | Embedded SQLite | State (ephemeral) |
| Auth perimeter | Identity-Aware Proxy (IAP) | Zero-trust access control |
0. Prerequisites
Section titled “0. Prerequisites”GCP project
Section titled “GCP project”You need a GCP project with billing enabled and the following APIs:
export PROJECT_ID="your-project-id"
gcloud services enable \ run.googleapis.com \ iap.googleapis.com \ iam.googleapis.com \ --project=$PROJECT_IDCLI tools
Section titled “CLI tools”| Tool | Verify |
|---|---|
gcloud 582.0.0 or later (verified; 575.0.0 does not have beta run instances) |
gcloud version and gcloud beta run instances deploy --help |
git |
git --version |
Authentication
Section titled “Authentication”The deploy requires two credentials. gcloud auth and Application Default
Credentials (ADC) are separate credential stores — both must be configured:
gcloud auth logingcloud auth application-default login| Credential | Verify | Used by |
|---|---|---|
gcloud auth login |
gcloud auth list |
gcloud commands (instance create, IAM bindings) |
gcloud auth application-default login |
gcloud auth application-default print-access-token |
REST API call that enables IAP (step 3b) |
Deployer permissions
Section titled “Deployer permissions”The identity running the deploy needs these IAM roles on the target project:
| Role | Why |
|---|---|
roles/run.admin |
Create and update Cloud Run Instances |
roles/iam.serviceAccountUser |
Attach a service account to the Instance (if using --service-account) |
roles/iap.admin |
Enable IAP and bind access policies |
Container image
Section titled “Container image”The deploy requires a pre-built omni image — a single image containing the Hub and all supported harnesses. There is no public image; you must build your own.
Build your own image with Cloud Build:
The repository includes a Cloud Build config that builds the full omni image chain. Before building, create an Artifact Registry repository to push to:
gcloud artifacts repositories create scion \ --repository-format=docker \ --location=us-central1 \ --project=$PROJECT_IDThen submit the build:
git clone https://github.com/GoogleCloudPlatform/scion.gitcd scion
gcloud builds submit \ --project=$PROJECT_ID \ --config=image-build/cloudbuild-omni.yaml \ --substitutions="_TAG=$(git rev-parse --short HEAD),_SHORT_SHA=$(git rev-parse --short HEAD),_COMMIT_SHA=$(git rev-parse HEAD),_REGISTRY=us-central1-docker.pkg.dev/$PROJECT_ID/scion" \ --ignore-file=image-build/gcloudignore-omni \ .The build runs eight images in a chain (thick-prep → scion-base → claude → codex →
opencode → antigravity → grok-build → omni). Each step builds in the Cloud Build
worker and feeds the next. Only the final scion-omni image is pushed to your
registry. Workers start fresh each run — there is no warm cache between builds.
Monitor progress in the
Cloud Build console or with
gcloud builds list --project=$PROJECT_ID.
When it completes, your image is:
us-central1-docker.pkg.dev/$PROJECT_ID/scion/scion-omni:$(git rev-parse --short HEAD)The deploy derives the agent image registry from --image automatically; if
derivation fails, the error names --image-registry as the explicit override.
When this value is wrong, agent creation fails — not the deploy itself.
Stay in the clone directory for the rest of this guide — the deploy script and teardown script are repository-relative paths.
1. Deploy
Section titled “1. Deploy”A single command creates the Instance, enables IAP, and verifies the perimeter:
./scripts/single-node/deploy.sh \ --name my-scion-hub \ --project $PROJECT_ID \ --region us-east4 \ --image us-central1-docker.pkg.dev/YOUR_PROJECT/scion/scion-omni:YOUR_TAGWhat the command does, step by step:
- Resolves your gcloud identity and the project number.
- Creates the Cloud Run Instance with
--sandbox-launcherenabled (this is what allows agents to run as sandboxes inside the Instance). - Enables IAP via a REST API PATCH (
iapEnabled: true,invokerIamDisabled: true). - Waits for IAP enforcement to activate (~30–75 seconds).
- Binds your identity as an IAP-authorized user.
- Asserts the perimeter — fetches the Instance URL with no credentials and fails the deploy if the app answers. This is the safety gate.
- Prints the Instance URL.
Optional flags
Section titled “Optional flags”| Flag | Default | Description |
|---|---|---|
--region |
us-east4 |
GCP region |
--cpu |
4 |
CPU allocation |
--memory |
8Gi |
Memory allocation |
--admin-email |
deployer’s gcloud account | Override the Hub admin email |
--service-account |
(default compute SA) | GCP service account for the Instance |
--image-registry |
derived from --image |
Override the image registry the broker uses to pull agent images |
2. First login
Section titled “2. First login”Open the Instance URL printed by the deploy command in your browser:
https://my-scion-hub-PROJECT_NUMBER.us-east4.run.app- IAP challenge — Google sign-in. Use the email that was bound as the IAP user
during deploy (your gcloud account, or the
--admin-emailvalue). - Hub access — After sign-in you land directly in the Hub. There is no second login. The deployer is automatically seeded as the first admin.
3. Create a project and start an agent
Section titled “3. Create a project and start an agent”Create a project
Section titled “Create a project”From the Hub web UI, click New Project. Provide a name and a git remote URL (e.g. a GitHub repository the agent will work in).
Start an agent
Section titled “Start an agent”Create an agent via the web UI or the API. The web UI is the simplest path — click a project, then New Agent, pick a harness (e.g. Claude), and start it.
Attach to the agent’s terminal
Section titled “Attach to the agent’s terminal”Once the agent reaches a running state, click Attach in the web UI to open a live tmux session in your browser. You can watch the agent work, send it messages, and inspect its output in real time.
4. Sizing
Section titled “4. Sizing”Measured ceilings
Section titled “Measured ceilings”| Instance size | Idle agents | Working agents |
|---|---|---|
| 4 CPU / 8 GiB (default) | 20 | 6 |
| 8 CPU / 32 GiB (maximum) | 51 | 14 |
8 CPU / 32 GiB is the largest size Cloud Run allows. Larger deploys are refused.
Each number is a single observation — one stress-test run per size. Repeatability is unmeasured. These are the points past which the Instance was observed to fail, not thresholds to design against.
Do not extrapolate a per-CPU or per-GiB rule. Four times the memory and twice the CPU bought about three times the idle capacity and about twice the working capacity. Two points cannot establish a curve, and the relationship is not linear in either resource.
The numbers are context. The operating signal is create latency. Agent creates under two seconds mean headroom. Creates at ten seconds or more mean the Instance is near its ceiling — stop adding agents. That rule was measured at both sizes and, unlike a headcount, adapts to what the agents are actually doing. See the overload warning below for details.
Sizing to the measured ceiling is not the safe choice. Running fewer agents than you could costs only capacity. Running more destroys every workspace on the Instance with no warning and no recovery. The two errors are not the same size.
There are no per-agent resource limits. All agents share the Instance’s CPU and memory budget. A single compute-heavy agent can starve its neighbours.
To change the Instance size:
./scripts/single-node/deploy.sh \ --name my-scion-hub \ --project $PROJECT_ID \ --cpu 8 --memory 32Gi \ --image us-central1-docker.pkg.dev/YOUR_PROJECT/scion/scion-omni:YOUR_TAG5. Durability
Section titled “5. Durability”This tier is Tier 0: pure ephemeral.
- Workspaces live on the Instance’s ephemeral filesystem.
- The SQLite database (projects, agent metadata) lives on the same ephemeral filesystem.
- The admin seed (your email) is set by an environment variable in the deploy command, so it is re-established automatically.
All state on the Instance is destroyed when the container restarts — whether by a planned redeploy, an overload that crashes the container, or any other restart. A redeploy you can plan for; a crash you cannot. The only durable copy of any agent’s work is what it has pushed to a git remote.
This is a deliberate design trade for fast, cheap, disposable deployments — not an oversight. Treat the Instance as a workspace, not as infrastructure. If you need durable workspaces, use the VM (GCE) path or the HA tier.
6. Teardown
Section titled “6. Teardown”Delete the Instance:
./scripts/single-node/teardown.sh \ --name my-scion-hub \ --project $PROJECT_IDOr directly:
gcloud beta run instances delete my-scion-hub \ --region=us-east4 \ --project=$PROJECT_ID \ --quietCost of leaving an Instance running
Section titled “Cost of leaving an Instance running”A Cloud Run Instance is billed for CPU and memory for the entire time it exists, regardless of whether it is handling requests. There is no scale-to-zero. Delete the Instance when you are not using it.
Cleaning up IAP bindings
Section titled “Cleaning up IAP bindings”IAP access bindings are region-scoped, not per-instance. If this was the only instance in the region, review and clean up bindings:
gcloud iap web get-iam-policy \ --project=$PROJECT_ID \ --region=us-east4 \ --resource-type=cloud-run7. Troubleshooting
Section titled “7. Troubleshooting”Image pull failures on first deploy
Section titled “Image pull failures on first deploy”If the Instance fails to start with a confusing image-pull error that names a cache mirror rather than your image, this is a known platform behavior (ptone/scion#1291). Verify:
- The image coordinate is correct (check for typos in the digest or tag).
- The image is accessible to the Instance’s service account.
- Re-run the deploy — transient pull failures sometimes resolve on retry.
IAP not enforcing after deploy
Section titled “IAP not enforcing after deploy”The deploy command includes a perimeter assertion that fails the deploy if IAP is not enforcing. If you see the Instance URL responding without an IAP challenge:
# Check IAP statuscurl -s -o /dev/null -w "%{http_code}" "https://INSTANCE_URL"# Expected: 302 (redirect to Google sign-in)# Bad: 200 (app is answering directly — IAP is not enforcing)Re-run the deploy command — it is idempotent and will re-enable IAP.
Agent create returns 502: harness-config "antigravity" not found
Section titled “Agent create returns 502: harness-config "antigravity" not found”If creating an agent without harnessConfig returns a 502 with failed to find harness-config "antigravity", the fix is to specify harnessConfig explicitly
(e.g. "harnessConfig": "claude"). See the note in
Section 3.