Search the docs

Search guides, API endpoints and MCP tools.

Pull secrets in a deploy

Load a deployment's secrets from the vault when the process starts, with a vault key in production.

This example loads the storefront's secrets when its server starts. In production it pulls with a vault key that can read only the storefront's production secrets; in staging it pulls with an ordinary API key. Each pull is one GET request that returns a JSON map of name to value.

Before you begin

  • The storefront is deployed to production and staging, and its secrets are set. See Secrets vault and CLI.
  • You are an admin or owner of the workspace, to create the vault key.

1. Create a vault key

A vault key (ctvk_…) names the products and production environments it may pull. Create one for the storefront in production, on the website under Secrets vault › Vault Keys, or with the CLI:

bash
clanker vault key create --name "Storefront runtime" --product storefront --env production
json
{
  "id": "Vk8MtR3pLx6N",
  "name": "Storefront runtime",
  "productIds": ["Pr4GtY9sLm3B"],
  "environmentIds": ["En1MwX6cTb7F"],
  "secret": "ctvk_7HqP2mXv9LsR4tWc8NbK3dFj6YgZ1aQe"
}

Copy secret now; it is never shown again. Store it in your hosting platform's secret store as CLANKER_VAULT_KEY, next to the deployment that uses it.

2. Pull when the process starts

Pull an environment's secrets with the key as a bearer token:

bash
curl --fail-with-body \
  https://api.clankertest.com/v1/workspaces/acme/products/storefront/environments/production/secrets/pull \
  -H "Authorization: Bearer $CLANKER_VAULT_KEY"
json
{
  "DATABASE_URL": "postgres://storefront@db.acme.dev:5432/storefront",
  "SESSION_SECRET": "9c1f…"
}

Unset names are left out, and a deployment with nothing set returns {}.

In a Node server, load the values into process.env before anything reads them:

typescript
// load-secrets.ts: import this first in the server's entry point.
// DEPLOY_ENV is your own setting: production or staging.
const environment = process.env.DEPLOY_ENV ?? "staging";
const key =
  environment === "production" ? process.env.CLANKER_VAULT_KEY : process.env.CLANKER_API_KEY;

const response = await fetch(
  `https://api.clankertest.com/v1/workspaces/acme/products/storefront/environments/${environment}/secrets/pull`,
  { headers: { Authorization: `Bearer ${key}` } },
);
if (!response.ok) {
  const error = await response.json();
  throw new Error(`Could not pull secrets (${response.status} ${error._tag}): ${error.message}`);
}
Object.assign(process.env, (await response.json()) as Record<string, string>);

From a shell entry point, export each value with jq, which quotes it for the shell:

bash
eval "$(curl --fail-with-body -sS \
  https://api.clankertest.com/v1/workspaces/acme/products/storefront/environments/production/secrets/pull \
  -H "Authorization: Bearer $CLANKER_VAULT_KEY" \
  | jq -r 'to_entries[] | "export \(.key)=\(.value | @sh)"')"
exec node server.js

Pull once when the process starts, not on every request.

Staging and other non-production environments

Vault keys cannot pull non-production values. Pull staging with a user API key, an account API key or a CLI login instead:

bash
curl --fail-with-body \
  https://api.clankertest.com/v1/workspaces/acme/products/storefront/environments/staging/secrets/pull \
  -H "Authorization: Bearer $CLANKER_API_KEY"

On a developer's computer, the CLI does the same with the saved login:

bash
clanker vault pull --product storefront --env staging

When a pull fails

The pull answers with an error and no values. Fail the start instead of running without secrets.

Status_tagWhy
401UnauthorizedThe key is missing, wrong or revoked
403ForbiddenAn ordinary key pulled production, or a vault key pulled non-production, or the vault key does not name this product and environment
404NotFoundNo such product or environment, or the product is not deployed there
409ConflictThe product or the environment is archived

Every production pull, including a refused one, is recorded in the vault's audit log with the key that made it, never the values.

Rotate the key

Create a new key with the same scope, deploy it, then revoke the old one:

bash
clanker vault key list
clanker vault key revoke Vk8MtR3pLx6N

The next pull with a revoked key fails with 401.