@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
bun add @konfig.ts/sealed-secretsTwo 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.
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 CRTo 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
| Export | Purpose |
|---|---|
SealedSecrets.backend | (opts?): a SecretBackend<N, K, true, SealedSecret> |
SealedSecretsBackendOptions | scope?: "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, SealedSecretScope | CR types |
Errors
| Error | When it is raised |
|---|---|
KubesealCertMissing | Neither certPath nor KUBESEAL_CERT is set |
KubesealInvocationError | kubeseal exited non-zero or was not found |
KubesealParseError | kubeseal 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.111as a peer dependency (Effect 4, release-candidate line).- Depends on
@konfig.ts/core,@konfig.ts/k8s, andyaml. - Runtime: Bun recommended; Node >= 23.6 works; Node 22.6 to 23.5 with
--experimental-strip-types;tsxworks.
Source and README: packages/sealed-secrets.