| 1 | --- |
| 2 | title: Setup |
| 3 | description: Connect alchemy to Google Cloud — project, service-account key, the APIs to enable, and Docker. |
| 4 | --- |
| 5 | |
| 6 | ## What you need |
| 7 | |
| 8 | - **A GCP project** and its id. |
| 9 | - **A service-account key** with enough IAM to create what you deploy. |
| 10 | A working starting point is Cloud Run Admin, Storage Admin, Pub/Sub |
| 11 | Admin, Service Account Admin (Alchemy mints a per-host `alch-*` |
| 12 | runtime account), and Project IAM Admin (it grants roles to that |
| 13 | account). Add the admin role for anything else you declare — |
| 14 | Firestore, BigQuery, Secret Manager. |
| 15 | - **Docker running locally.** `GCP.Function`, `GCP.Run.Service`, |
| 16 | `GCP.Run.Job`, and `GCP.Run.WorkerPool` bundle your code and build a |
| 17 | container image before pushing it to Artifact Registry. |
| 18 | - **The APIs enabled** on the project for whatever you use: |
| 19 | `run.googleapis.com`, `artifactregistry.googleapis.com`, |
| 20 | `iam.googleapis.com`, `cloudresourcemanager.googleapis.com`, plus the |
| 21 | service-specific ones (`firestore.googleapis.com`, |
| 22 | `secretmanager.googleapis.com`, `pubsub.googleapis.com`, |
| 23 | `bigquery.googleapis.com`, `redis.googleapis.com`). |
| 24 | |
| 25 | ```sh |
| 26 | gcloud services enable run.googleapis.com artifactregistry.googleapis.com \ |
| 27 | iam.googleapis.com cloudresourcemanager.googleapis.com |
| 28 | ``` |
| 29 | |
| 30 | ## Credentials |
| 31 | |
| 32 | Run `alchemy profile edit --add GCP`, choose **Service account JSON**, |
| 33 | and point at the key file. Alchemy stores it under |
| 34 | `~/.alchemy/credentials/<profile>/`. |
| 35 | |
| 36 | In CI (`CI=true`), Alchemy skips profiles and reads the environment: |
| 37 | |
| 38 | - `GOOGLE_PROJECT_ID` — project id (`GOOGLE_CLOUD_PROJECT` is accepted |
| 39 | as an alias). |
| 40 | - `GOOGLE_APPLICATION_CREDENTIALS` — path to the key file. |
| 41 | |
| 42 | Or `GOOGLE_ACCESS_TOKEN` plus `GOOGLE_PROJECT_ID` for a short-lived |
| 43 | token. On GKE with Workload Identity, neither is needed — the metadata |
| 44 | server is the last link in the chain. |
| 45 | |
| 46 | See [Profiles](/environments/profiles) for how credentials are stored |
| 47 | and switched. |
| 48 | |
| 49 | ## Register the provider |
| 50 | |
| 51 | ```typescript |
| 52 | // alchemy.run.ts |
| 53 | import * as Alchemy from "alchemy"; |
| 54 | import * as GCP from "alchemy/GCP"; |
| 55 | import * as Effect from "effect/Effect"; |
| 56 | |
| 57 | export default Alchemy.Stack( |
| 58 | "App", |
| 59 | { providers: GCP.providers(), state: Alchemy.localState() }, |
| 60 | Effect.gen(function* () { |
| 61 | return {}; |
| 62 | }), |
| 63 | ); |
| 64 | ``` |
| 65 | |
| 66 | `GCP.providers()` merges next to any other cloud's providers, so a |
| 67 | single stack can span GCP and Cloudflare or AWS. |
| 68 | |
| 69 | ## Choose a region |
| 70 | |
| 71 | Regional resources created without a `location` / `region` prop land in |
| 72 | the default region. It comes with the credential (the profile's |
| 73 | `region`, which `alchemy profile` asks for), else `us-central1`. To pin |
| 74 | a stack to a region regardless of the credential, provide |
| 75 | `GCP.Region(...)`: |
| 76 | |
| 77 | ```typescript |
| 78 | export default Alchemy.Stack( |
| 79 | "App", |
| 80 | { |
| 81 | providers: GCP.providers().pipe( |
| 82 | Layer.provideMerge(GCP.Region("europe-west1")), |
| 83 | ), |
| 84 | state: Alchemy.localState(), |
| 85 | }, |
| 86 | program, |
| 87 | ); |
| 88 | ``` |
| 89 | |
| 90 | A resource that should live elsewhere takes an explicit `location`. |
| 91 | Changing the stack region never moves a deployed resource: its recorded |
| 92 | location wins. |
| 93 | |
| 94 | Requests for regional resources that Google only serves from a regional |
| 95 | endpoint (Secret Manager, Parameter Manager) go to |
| 96 | `{service}.{region}.rep.googleapis.com` automatically. For data |
| 97 | residency, send every regional request to its regional endpoint: |
| 98 | |
| 99 | ```typescript |
| 100 | GCP.providers().pipe( |
| 101 | Layer.provideMerge(GCP.RegionalEndpoints("prefer")), |
| 102 | ); |
| 103 | ``` |
| 104 | |
| 105 | ## Cleaning up |
| 106 | |
| 107 | `alchemy destroy` removes what a stack created, including the per-host |
| 108 | service accounts and their role grants. For a test project that has |
| 109 | drifted, `pnpm nuke:gcp` deletes Alchemy-managed resources across the |
| 110 | whole project — including every service account stamped |
| 111 | `alchemy-host`. Do not point it at a project you care about. |
| 112 | |
| 113 | ## Next steps |
| 114 | |
| 115 | - [GCP overview](/gcp) — hosts, resources, and bindings. |
| 116 | - [Serve an API on Cloud Run](/gcp/guides/cloud-run-api) — the first |
| 117 | thing to build. |