Skip to content
Docs menu / sealed-secrets

@konfig.ts/sealed-secrets

@konfig.ts/sealed-secrets is the secret backend for Sealed Secrets. It lets you commit encrypted secrets to git that only the controller running in your cluster can decrypt. At render time konfig resolves the plaintext from the source you configured, keeps it in memory only as redacted values, builds a plain Kubernetes Secret from it, pipes that Secret to the kubeseal CLI over stdin, and emits the SealedSecret custom resource that kubeseal returns. Only the in-cluster controller can decrypt that resource, so the rendered manifest is safe to commit.

Install

Terminal window
bun add @konfig.ts/sealed-secrets

Two things must be present on the machine that runs konfig build: the kubeseal CLI, and the controller’s public certificate. The certificate path comes from the certPath option, or from the KUBESEAL_CERT environment variable when certPath is not set.

Usage

Bind a contract from @konfig.ts/env to the backend and give it a source for the plaintext. This backend declares requiresSource: true, so leaving out source is a compile-time error.

infra/modules/db.ts
import { SecretSource } from "@konfig.ts/env"
import { Secret } from "@konfig.ts/k8s"
import { SealedSecrets } from "@konfig.ts/sealed-secrets"
const dbCreds = Secret.define({
name: "db-creds",
namespace: "prod",
env: { url: "DATABASE_URL", password: "DATABASE_PASSWORD" }
})
const bound = Secret.bind({
secret: dbCreds,
backend: SealedSecrets.backend({ scope: "strict" }),
source: SecretSource.fromConfig({
keys: ["url", "password"],
envName: (k) => `DB_${k.toUpperCase()}`
})
})
// bound.manifest is the Manifest that renders to the SealedSecret CR

To bind a whole environment bundle instead of a single secret, pass the same backend and source to Environment.bind({ env, namespace, secrets: { db: { backend, source } } }).

Surface

ExportPurpose
SealedSecrets.backend(opts?): a SecretBackend<N, K, true, SealedSecret>
SealedSecretsBackendOptionsscope?: "strict" | "namespace-wide" | "cluster-wide" (default strict), certPath? (default $KUBESEAL_CERT)
runKubeseal({ plainSecretYaml, certPath, scope }), resolveCertPath({ certPath? })Low-level helpers: run kubeseal on a serialized Secret, resolve the certificate path (RunKubesealInput)
SealedSecret, SealedSecretSpec, SealedSecretTemplate, SealedSecretScopeCR types

Errors

ErrorWhen it is raised
KubesealCertMissingNeither certPath nor KUBESEAL_CERT is set
KubesealInvocationErrorkubeseal exited non-zero or was not found
KubesealParseErrorkubeseal output was not valid YAML

Output that parses as YAML but does not match the SealedSecret schema is a different failure: it shows up as BoundaryDecodeError from @konfig.ts/core.

Requirements

  • effect@^4.0.0-rc.111 as a peer dependency (Effect 4, release-candidate line).
  • Depends on @konfig.ts/core, @konfig.ts/k8s, and yaml.
  • Runtime: Bun recommended; Node >= 23.6 works; Node 22.6 to 23.5 with --experimental-strip-types; tsx works.

Source and README: packages/sealed-secrets.