---
title: "Google Secret Manager"
description: "Use Google Secret Manager for MainSDK secrets - service account setup, main.yaml, secret references, rotation, local testing and swapping."
section: "integrations"
canonical: "https://mainsdk.dev/docs/integrations/google-secret-manager"
updated: "2026-10-28"
---

# Google Secret Manager

> Use Google Secret Manager for MainSDK secrets - service account setup, main.yaml, secret references, rotation, local testing and swapping.

Canonical: https://mainsdk.dev/docs/integrations/google-secret-manager · Updated: 2026-10-28

Google Secret Manager is one of the cloud drivers behind [`secrets`](https://mainsdk.dev/docs/interfaces/secrets). Your app reads provider keys from Secret Manager on the server, and `main.yaml` refers to them as `secret:NAME`. Pick it when your app runs on Google Cloud and you want secrets under the same IAM and audit logs as the rest of your project.

## Interfaces it serves

### Secrets (`secrets`)

- Status: Building for 0.2 · ships as a stable API
- Driver: `gcp-secret-manager` (Google Secret Manager)
- Docs: https://mainsdk.dev/docs/interfaces/secrets.md

```yaml
secrets:
  driver: gcp-secret-manager
```

Swap to another provider: `vault`, `aws-secrets-manager`, `azure-key-vault`, `doppler`, `infisical`, `env`, `local`.

## Before you start

1. **Enable the Secret Manager API** in the Google Cloud project that will hold your secrets.
2. **Create a secret for each key**, such as `RESEND_API_KEY`, and add its value as a version. Choose replication locations that fit your data rules. How a `secret:` name maps to a Secret Manager resource name is not defined yet [TBD].
3. **Give your app an identity.** Prefer workload identity: the service account your Cloud Run service, GKE workload or other compute already runs as, or Workload Identity Federation when the app runs outside Google Cloud. Avoid downloaded service account key files.
4. **Grant read access only**, such as the Secret Manager secret accessor role, on just the secrets the app needs.

## Configure

```yaml title="main.yaml"
secrets:
  driver: gcp-secret-manager   # [TBD] project and other driver settings are not specified yet
email:
  key: secret:RESEND_API_KEY   # suggested name; read from Secret Manager at startup
```

Keep `local` in a development overlay and `gcp-secret-manager` in `main.env.prod.yaml`. A literal value in a field marked secret fails `mainsdk check` with `MAIN-CONFIG-0004`.

## Use it

```ts title="app/lib/partner.ts"
import { secrets } from "mainsdk";   // server only: a client import fails the build

export async function partnerHeaders() {
  const token = await secrets.get("PARTNER_API_TOKEN");
  return { authorization: `Bearer ${token}` };
}
```

## Local development and testing

- **No Google Cloud project:** use the `local` driver (`.mainsdk/secrets.json`, git-ignored) or the `env` driver.
- **Against real Secret Manager:** use a development project and your own application default credentials on your machine.
- **Tests:** `createTestApp()` from `@mainsdk/testing` runs `secrets` on its in-memory fake, and `chaos.on("secrets", { outage: true })` simulates Secret Manager being unreachable.

```ts title="app/lib/partner.test.ts"
import { it } from "node:test";
import assert from "node:assert/strict";
import { createTestApp, chaos } from "@mainsdk/testing";
import { secrets } from "mainsdk";

it("serves the last good value when Secret Manager is down", async () => {
  createTestApp({ main: "./main.yaml" });
  const first = await secrets.get("PARTNER_API_TOKEN");
  chaos.on("secrets", { outage: true });
  assert.equal(await secrets.get("PARTNER_API_TOKEN"), first);
});
```

## What MainSDK adds on top

- `secrets` is importable only in server code; values are redacted from logs, errors and telemetry.
- The last good value is served from memory when Secret Manager is unreachable, with `MAIN-SECRET-0007`; never written to disk.
- A key in code, a committed env file or the browser bundle fails `mainsdk check`.

See [Secrets](https://mainsdk.dev/docs/interfaces/secrets) for the full contract.

## Limits and notes

- The driver comes with the config-secrets spec (phase 1).
- When you add a new secret version, the next `secrets.get()` after the driver's cache TTL returns it, with no restart. The TTL length, and which version the driver reads, are [TBD].
- `secrets.raw()` returns the provider's client; each use is logged and listed by `mainsdk check`.

## Swap to or from it

```yaml title="main.yaml"
secrets:
  driver: gcp-secret-manager   # was env
```

> **Warning:** Secrets are read in place, and MainSDK copies nothing between managers. Create the same names in the new manager before you swap.

## FAQ

**Do I need a service account key file?** No. Use the service account your compute runs as, or Workload Identity Federation outside Google Cloud.

**Can secrets live in one region only?** Secret Manager lets you choose replication locations per secret. Pick ones that match where your app's data must stay.

## Next

- [Secrets](https://mainsdk.dev/docs/interfaces/secrets) and [Encryption keys](https://mainsdk.dev/docs/interfaces/keys)
- [Google Cloud KMS](https://mainsdk.dev/docs/integrations/google-cloud-kms), [AWS Secrets Manager](https://mainsdk.dev/docs/integrations/aws-secrets-manager) and [HashiCorp Vault](https://mainsdk.dev/docs/integrations/hashicorp-vault)
- [Swap a driver](https://mainsdk.dev/docs/guides/swap-a-driver)
