From bae427651d957f272bb345cff52051a8e0995789 Mon Sep 17 00:00:00 2001 From: Thanatat Tamtan Date: Wed, 17 Jun 2026 10:32:21 +0700 Subject: [PATCH 1/2] registry: document Google Cloud service-account auth Add a subsection on authenticating to registry.deploys.app with a Google Cloud service account: log in with `oauth2accesstoken` + a short-lived access token, which must carry the userinfo.email scope (the registry resolves the caller's identity from the token's email), and grant the SA email a role with registry.push/registry.pull on the project. Includes a GitHub Actions snippet. Co-Authored-By: Claude Opus 4.8 (1M context) --- content/registry/overview.md | 43 ++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/content/registry/overview.md b/content/registry/overview.md index 9e4615b..e75adf0 100644 --- a/content/registry/overview.md +++ b/content/registry/overview.md @@ -35,6 +35,49 @@ The username for service accounts is the account email; the password is the key. Generate one from [Service accounts → Keys](/access/service-accounts/) in the console. +### Using a Google Cloud service account + +You can also authenticate with a **Google Cloud service account** instead of a +deploys.app key — handy when you already run in Google Cloud or in GitHub Actions +with a Google credential. The username is the literal `oauth2accesstoken` and the +password is a short-lived **access token** for the service account: + +```bash +docker login registry.deploys.app \ + -u oauth2accesstoken \ + -p "$(gcloud auth print-access-token \ + --scopes=https://www.googleapis.com/auth/userinfo.email)" +``` + +Two things are required: + +- **The access token must carry the `https://www.googleapis.com/auth/userinfo.email` + scope.** The registry identifies the caller by the token's email, so a token + without that scope (for example the default `cloud-platform`-only token) is + rejected with `unauthorized: authentication required`. +- **The service account's email must be granted registry access on the project.** + Add `@.iam.gserviceaccount.com` as a member of a role that holds + `registry.push` (to push) and/or `registry.pull` (to pull) under + [Roles](/access/roles/), exactly as you would any other member. + +In **GitHub Actions** with `google-github-actions/auth`, request the email scope +alongside any others you need, then log in with the access token: + +```yaml +- uses: google-github-actions/auth@v3 + id: auth + with: + credentials_json: ${{ secrets.GOOGLE_CREDENTIALS }} + token_format: access_token + # keep cloud-platform too if the same token also pushes to Artifact Registry + access_token_scopes: https://www.googleapis.com/auth/userinfo.email +- uses: docker/login-action@v4 + with: + registry: registry.deploys.app + username: oauth2accesstoken + password: ${{ steps.auth.outputs.access_token }} +``` + ## Pushing an image The repository name is `/` — the project is your project ID, From 6ddf73e7ced776b07e0546f53b7e7c9a60a652c1 Mon Sep 17 00:00:00 2001 From: Thanatat Tamtan Date: Wed, 17 Jun 2026 12:32:37 +0700 Subject: [PATCH 2/2] api: document Google Cloud service-account auth The API accepts a Google Cloud SA access token as the bearer token (not just the registry). Document it in the API overview's Authentication section: the token needs the userinfo.email scope and the SA email must be granted the required permissions; cross-link the registry section. Co-Authored-By: Claude Opus 4.8 (1M context) --- content/api/overview.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/content/api/overview.md b/content/api/overview.md index 50187fb..254f615 100644 --- a/content/api/overview.md +++ b/content/api/overview.md @@ -33,6 +33,24 @@ right choice for CI and back-end services): Authorization: Basic base64(:) ``` +**Google Cloud service account** — pass a Google Cloud SA **access token** as the +bearer token, instead of issuing a deploys.app key: + +```http +Authorization: Bearer +``` + +The token must include the `https://www.googleapis.com/auth/userinfo.email` scope +(deploys.app identifies the caller by the token's email), and the service +account's email (`@.iam.gserviceaccount.com`) must be granted the +permissions you need via [Roles](/access/roles/). Mint one with `gcloud auth +print-access-token --scopes=https://www.googleapis.com/auth/userinfo.email`, or in +GitHub Actions with `google-github-actions/auth` (`token_format: access_token`). +It's the same identity the [container +registry](/registry/overview/#using-a-google-cloud-service-account) accepts — +useful when you already run in Google Cloud and don't want to manage a separate +deploys.app key. Note these tokens are short-lived (about an hour). + Unauthenticated calls and calls with a bad token return **401 Unauthorized**. Calls authenticated but missing a [permission](/access/roles/) return a **200 OK** response with `{ "ok": false, "error": { "message": "api: forbidden" } }` —