Machine identities

Updated

A machine identity is a non-human credential: a client id (kmi_…) and a client secret. It is how a CI job, a deploy script or an internal tool reads secrets without a person being involved.

Machine identities do not consume developer seats. A CI job, pipeline run, or secret retrieval is not itself a machine identity and does not count toward any allowance.

Machine identities

Creating one

Dashboard -> Machine identities -> New identity. Unlock the vault first: the browser generates the key pair and can seal the organization key. There is no project-scoping control in the dashboard. Pending machine grants, if any, are approved on Approvals (the identity cannot decrypt bundles until that grant exists).

The client secret is displayed exactly once, at creation. The server keeps only a hashed, derived form and cannot recover it - copy it into your CI secret store before closing the dialog. If you lose it, rotate the identity.

Client secrets created from now on start with a ksm2_ prefix. Older secrets keep working unchanged; rotating an identity moves it to the new format.

Using it

Kryptic is a blind store: the Pipelines BFF returns ciphertext, never plaintext. kryptic ci export runs the decryption chain on the runner (client secret unwraps the machine private key, which opens the org key, which opens each envelope) and prints dotenv, shell, or JSON.

export KRYPTIC_CLIENT_ID=kmi_...
export KRYPTIC_CLIENT_SECRET=...
# optional, self-hosted:
# export KRYPTIC_PIPELINES_API=https://pipelines.kryptic.example.com

kryptic ci export --project proj_x --env production --format dotenv > .env

--format accepts:

ValueOutput
dotenv (default)KEY=value lines, quoted where needed
shellexport KEY='value' lines, correctly escaped
jsonA flat JSON object

The Kubernetes operator uses the same identity. The recommended production path is a credentials Secret in each application namespace. For non-production clusters you can set KRYPTIC_CLIENT_ID and KRYPTIC_CLIENT_SECRET on the operator once and omit spec.auth on each KrypticSecret.

If you are implementing your own client instead of the CLI, exchange credentials at POST https://pipelines.kryptic.dev/api/token, fetch GET /api/keys/me and GET /api/secrets/bundle?projectPublicId=proj_x&environment=production, then decrypt with the Go encryption engine. The REST API v1 is the same shape on https://secrets.kryptic.dev.

GitHub Actions

- name: Load secrets from Kryptic
  env:
    KRYPTIC_CLIENT_ID: ${{ secrets.KRYPTIC_CLIENT_ID }}
    KRYPTIC_CLIENT_SECRET: ${{ secrets.KRYPTIC_CLIENT_SECRET }}
  run: |
    ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')
    curl -fsSL "https://kryptic.dev/dl/kryptic-linux-${ARCH}" -o /tmp/kryptic
    chmod +x /tmp/kryptic
    eval "$(/tmp/kryptic ci export --project proj_x --env production --format shell)"

The dashboard Client generator (and the same tab on each project) emits a snippet pre-filled with the project id for GitHub Actions, GitLab CI, Azure DevOps, Docker, Compose, dotenv, and the other runners listed in CI/CD. Prefer kryptic ci export over calling the bundle endpoint yourself: it is the path that actually decrypts. Do not use install.sh on a runner; that script configures a desktop daemon.

Lifecycle

ActionEffect
RotateIssues a new secret and invalidates the old one immediately. The vault must be unlocked
DeactivateToken exchange starts returning 401

Every read is audit-logged with the machine identity as the actor, so a CI pipeline's access is as reviewable as a person's.

Licensing

Seats are people. Machine identities do not consume developer seats.

On Free, Team, and Business, machine identities are unlimited. On Enterprise, included usage is ten active machine identities per active developer seat, calculated across the organization (not ten assigned to each person). Only active identities count. Disabled or revoked identities do not. CI/CD executions, pipeline runs, jobs, and secret retrieval operations do not count toward the allowance.

Usage above that threshold is Exceptional Scale Usage. It does not automatically create a fixed overage charge. Kryptic may review the deployment and require additional licensing or an Enterprise capacity agreement where appropriate, including for unusually machine-heavy organizations and large automated infrastructures.

For Kubernetes, prefer the operator over calling the API from an init container. It handles refresh, drift and failure modes for you. For Coolify, follow the Coolify guide: there is no native connector, so the container runs kryptic ci export at start.