> ## Documentation Index
> Fetch the complete documentation index at: https://docs.idun-group.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Deploy to Cloud Run

> Single-container deploy on Google Cloud Run with managed Postgres.

Cloud Run runs a single container per request, scales to zero by default, and forwards HTTPS. The standalone is designed to fit.

## 1. Set up Cloud SQL (Postgres)

The standalone uses SQLite by default; on Cloud Run that disappears between revisions. Use Cloud SQL Postgres:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
gcloud sql instances create idun-postgres \
    --database-version=POSTGRES_16 --region=europe-west1 --tier=db-f1-micro
gcloud sql databases create idun --instance=idun-postgres
gcloud sql users create idun --instance=idun-postgres --password='changeme'
```

URL form (Cloud SQL Auth Proxy / unix socket):

```text theme={"theme":{"light":"github-light","dark":"github-dark"}}
postgresql+asyncpg://idun:changeme@/idun?host=/cloudsql/PROJECT:REGION:idun-postgres
```

## 2. Store secrets in Secret Manager

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
echo -n "$(idun hash-password)" | gcloud secrets create idun-admin-hash --data-file=-
openssl rand -hex 32 | gcloud secrets create idun-session-secret --data-file=-
echo -n "postgresql+asyncpg://..." | gcloud secrets create idun-db-url --data-file=-
```

## 3. Build & push

Use `Dockerfile.example` as a starting point:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
docker build -f Dockerfile.example -t gcr.io/PROJECT/my-agent:0.1.0 .
docker push gcr.io/PROJECT/my-agent:0.1.0
```

## 4. Deploy

Copy the template into your deploy directory, then edit it:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
cp /path/to/idun-agent-platform/libs/idun_agent_standalone/docker/cloud-run.example.yaml cloud-run.yaml
# Replace PROJECT, REGION, and the image tag in cloud-run.yaml.
gcloud run services replace cloud-run.yaml --region=europe-west1
```

The template ships two annotations you must keep:

* `metadata.annotations."run.googleapis.com/cloudsql-instances"` — attaches the Cloud SQL instance to the service. Required for the unix-socket form `host=/cloudsql/PROJECT:REGION:idun-postgres` in `DATABASE_URL`.
* `spec.template.metadata.annotations."run.googleapis.com/cloudsql-instances"` — same value at the revision level. Cloud Run requires both for new revisions to inherit the connection.

Recommended runtime settings (already set in the template):

* `minScale: "1"` — eliminates cold starts and keeps the trace retention scheduler running.
* `cpu-throttling: "false"` — keeps the trace writer flushing between requests.
* 1 GiB memory, 1 vCPU is plenty for a small agent.

## Caveats

* **MCP servers using `command: docker run …`** won't work on Cloud Run. Switch to `transport: stdio` with a binary command (e.g. `npx`, `uvx`, a precompiled binary) or use HTTP transport pointing at another Cloud Run service.
* **Trace retention purge** runs hourly via APScheduler — when Cloud Run scales to zero the scheduler stops too. With `minScale: "1"` it runs continuously.
* Cookies need `Secure` — Cloud Run's load balancer sets `X-Forwarded-Proto: https`. The standalone honors that automatically.

## Next steps

<Card title="Production hardening" icon="shield-halved" horizontal href="/deployment/hardening">
  Lock down admin auth, TLS, secrets, and trace retention before exposing the service.
</Card>

<Card title="GCP Trace" icon="route" horizontal href="/observability/gcp-trace">
  Send distributed traces to the same Google Cloud project.
</Card>

<Card title="GCP Logging" icon="file-text" horizontal href="/observability/gcp-logging">
  Stream structured logs to Cloud Logging from the running service.
</Card>
