# Self-hosted keyless connections

> Offer keyless Vertex AI and Anthropic connections from your own installation: its issuer address, uploaded key sets, and the installation's own identity.

Product: AI Cost Optimizer Gateway (ACOG). Web version: https://tessarac.com/docs/acog/self-hosted/install-identity. Last updated: 2026-10-16.

A self-hosted installation offers the same [keyless connections](https://tessarac.com/docs/acog/providers/keyless-connections.md) as the hosted service, and one more mode, **install identity**.

| Mode | Console label | Identity presented to Google or Anthropic |
|---|---|---|
| `workload_identity` | Keyless (workload identity) | A per-organization issuer that your installation runs |
| `ambient` | This install's identity | The identity the installation itself runs as |

## Per-organization keyless connections

Your installation becomes an OpenID Connect issuer with one issuer per organization, exactly as on the hosted service. Set its public address on the control plane:

```yaml
services:
  controlplane:
    extraEnv:
      ACOG_WORKLOAD_IDENTITY_ISSUER_BASE: "https://acog.example.com/api/v1/identity"
```

Each organization's issuer is then `https://acog.example.com/api/v1/identity/<issuer id>`. Google and Anthropic fetch its public keys from `<issuer>/.well-known/openid-configuration` and `<issuer>/jwks.json`, so the address must be reachable from the internet over HTTPS on port 443.

Without `ACOG_WORKLOAD_IDENTITY_ISSUER_BASE`, keyless connections are not offered and saving one is refused with that reason.

Signing keys are generated by the control plane and stored sealed with `ACOG_CREDS_KEY` (or held in AWS KMS with `ACOG_WORKLOAD_IDENTITY_KEY_SOURCE=kms`). They rotate every 90 days, and each new key is published 24 hours before it starts signing.

### When Google or Anthropic cannot reach your installation

If the issuer address is not reachable from the internet, upload the key set instead of letting the provider fetch it. **Admin → Providers → Connect provider → Keyless** shows the key set under **Can't reach the internet? Upload these keys**:

- Google: create the workload identity provider with `--jwk-json-path` pointing at the saved key set.
- Anthropic: create the federation issuer with an inline JWKS.

Then the issuer URL only has to match as text. **You must upload the new key set every time a key rotates**, before it starts signing: the Providers page warns when a new key is pending and shows when it takes effect. Increase `ACOG_WORKLOAD_IDENTITY_KEY_ACTIVATION_DELAY` (default `24h`) to give yourself time.

## Install identity

With install identity, a connection uses the identity the installation already runs as, and stores nothing. Any organization on the installation can create such a connection, so **grant the installation's identity only what every organization on it may use.**

### Google (Vertex AI)

The data plane and control plane use, in order:

1. `GOOGLE_APPLICATION_CREDENTIALS`, naming a service account key file or an `external_account` (workload identity federation) file whose credential source is a file or URL;
2. otherwise the metadata server: GKE Workload Identity, or the Compute Engine service account.

On GKE, bind the chart's Kubernetes service account to a Google service account:

```yaml
serviceAccount:
  annotations:
    iam.gke.io/gcp-service-account: acog@my-project.iam.gserviceaccount.com
```

Grant that service account `roles/aiplatform.user` on the projects your organizations will use. A connection can still name a service account to impersonate.

### Anthropic

The chart can mount a projected Kubernetes service-account token for Anthropic to trust:

```yaml
installIdentity:
  anthropic:
    enabled: true
```

This mounts a token with audience `https://api.anthropic.com` at `/var/run/secrets/anthropic.com/token`, rotated by Kubernetes. In the Claude Console, register your cluster's service-account issuer as a federation issuer (see Anthropic's [Kubernetes guide](https://platform.claude.com/docs/en/manage-claude/wif-providers/kubernetes)) and create a rule matching the chart's service account. The connection takes the same four identifiers as a keyless connection.

ACOG refuses to send any token whose audience is not `https://api.anthropic.com`, so a misconfigured token file never sends the cluster's own credentials.

**More than one install-identity Anthropic connection:** each presents the same token, and Anthropic's single-use check (`check_jti`) refuses a token seen before. Turn `check_jti` off on that issuer in the Claude Console.
