Skip to content

External Secrets

External secrets are centralized credentials for third-party providers (OpenAI, Stripe, GitHub, SendGrid, …) that PaaS Runtime stores encrypted and auto-injects into your apps as environment variables. You manage them once and every deploy picks them up — no copy-pasting API keys into each app's config.

Why

  • Encrypted at rest — values are sealed with AES-256-GCM; the API never returns a stored value (list/read endpoints are metadata-only).
  • One source of truth — set a provider key once at the tenant level and all your apps inherit it.
  • Per-app overrides — an individual app can override the tenant default for a given provider key when it needs a different credential.

Scopes

Scope Set where Applies to
Tenant default Settings → External Secrets (/settings/secrets) every app in the tenant
App override an app's External Secrets tab (/apps/{id}/external-secrets) that app only (wins over the tenant default for the same provider + key)

The app view shows a merged list: each row is badged App-specific (🔵, an override you can edit/delete here) or Inherited (⚫, the tenant default — read-only here, managed in Settings).

Providers & keys

A catalog of 50 providers is available. Each provider declares the keys it needs (e.g. OPENAI_API_KEY) and, where supported, a Test action that makes a real call to verify the credential. Stored secrets can also be rotated in place.

Lifecycle (how it was built)

The feature shipped across phases: tenant-scoped CRUD + encryption + test + rotate, per-app overrides, the dashboard UIs, and a server-side merged endpoint. Each privileged action emits a distinct audit event (external_secret.created, .rotated, .deleted, .injected, .accessed, .test_passed, .test_failed, .app_scoped, .merged_fetched, plus external_secret.provider_lookup) so the full credential lifecycle is traceable.

Injection

See External Secrets Injection for how a secret reaches a running pod's environment at deploy time.