Qubittron Bastion
Best practices

API key management

How to issue, store, scope, and rotate Bastion API keys without leaking them.

API keys (qbt_...) are the only credential the Bastion API accepts. Treat them like passwords — leakage is a billing and data-access risk.

Issue one key per environment and per service

Use a distinct key for each combination of (environment, service). Keys are cheap to create and they give you a clean audit and revocation surface.

EnvironmentServiceExample key label
devlocal laptopdev-laptop-<initials>
stagingapi workerstaging-api-worker
prodapi workerprod-api-worker
prodbatch jobprod-batch-nightly

Mixing environments (one key powering both staging and prod) defeats audit logs and means revoking a leak takes down everything.

Store keys in a secrets manager — never in client code

A key in client-side JavaScript, a mobile app binary, or a public Git history is compromised the moment it ships. Acceptable homes:

  • AWS Secrets Manager / SSM Parameter Store
  • HashiCorp Vault
  • GCP Secret Manager
  • GitHub Actions / GitLab CI encrypted secrets
  • 1Password / Doppler (for developer machines)

Inject the secret as an environment variable at runtime — code should only ever read it via process.env.QUBITTRON_API_KEY (or your platform's equivalent).

Rotate on a schedule and on suspected exposure

The dashboard supports rolling rotation: create a new key, deploy services to use it, then revoke the old one. Old and new keys coexist until you revoke, so there's no downtime.

Trigger an immediate rotation when:

  • A key appears in a log, an error report, a stack trace, or a screenshot.
  • A laptop with developer keys is lost or sold.
  • An employee with key access leaves the company.
  • A git log -p shows a key was ever committed (even if reverted — assume Git history is forever).

Test that a key works

A small smoke test is useful right after issuing or rotating a key. It costs nothing and confirms the key is live before you depend on it in code:

curl https://api.qubittron.ai/v1/models \
  -H "Authorization: Bearer $QUBITTRON_API_KEY" \
  -o /dev/null -w "%{http_code}\n"

A 200 means the key is live. A 401 means it's missing, malformed, or revoked.

Never log or echo the raw key

Redact secrets at the logging boundary. Most logging libraries support a redactor or a structured-logging pattern that drops known-secret fields:

const safeHeaders = {
  ...headers,
  authorization: headers.authorization ? "Bearer qbt_***" : undefined,
};
logger.info({ url, headers: safeHeaders }, "outbound request");

Treat error reporters (Sentry, Datadog, etc.) the same way — accidentally shipping headers in an error payload is a common leak path.

On this page