From f86dc5f4cd44366d0a216e4e627ac780b9be704b Mon Sep 17 00:00:00 2001 From: Aleksei Sviridkin Date: Wed, 24 Jun 2026 15:48:00 +0300 Subject: [PATCH 1/3] [docs] talm: document encrypted user values and dry-run secret redaction Add a talm.md section covering the encrypted-user-values workflow (values-secret.yaml -> talm.key encryption -> templateOptions.valueFiles -> in-template use) and how secrets are redacted across talm template, talm template -i, and talm apply --dry-run. Documents --show-secrets / --show-secrets-in-drift, the apply value-source flags, and the value-based-matching sharp edge. Signed-off-by: Aleksei Sviridkin --- .../en/docs/next/install/kubernetes/talm.md | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/content/en/docs/next/install/kubernetes/talm.md b/content/en/docs/next/install/kubernetes/talm.md index 29ee4a81..11de2430 100644 --- a/content/en/docs/next/install/kubernetes/talm.md +++ b/content/en/docs/next/install/kubernetes/talm.md @@ -258,6 +258,43 @@ To configure Keycloak as an OIDC provider, apply the following changes to the te ``` +### 2.4 Encrypted user values and secret redaction (Talm v0.32+) + +Beyond `secrets.yaml` (the Talos bootstrap secrets), templates often inject operator-supplied secrets into the config — a registry password, an OIDC client secret, a static-pod env value. Talm lets you keep those encrypted in git the same way as `secrets.yaml`, decrypt them in memory at render time, and keep them out of committed node files, terminal output, and CI logs. + +**Step 1 — put the secret values in `values-secret.yaml`:** + +```yaml +registryPassword: "s3cr3t-high-entropy-value" +``` + +**Step 2 — encrypt it** with the project's `talm.key`. `talm init --encrypt` produces `values-secret.encrypted.yaml`. Commit the encrypted file; the plaintext `values-secret.yaml` is git-ignored. + +**Step 3 — reference the encrypted file** from `Chart.yaml` by adding it to `templateOptions.valueFiles`, so both `talm template` and `talm apply` read it: + +```yaml +templateOptions: { valueFiles: ["values-secret.encrypted.yaml"] } +``` + +Referencing it only via the CLI `--values` flag is a foot-gun: the modeline in a node file does not persist value files, so a later `talm apply` would re-render WITHOUT the secret and silently drop the field. Talm surfaces a warning when an encrypted file is passed via `--values` but is not in `templateOptions.valueFiles`. + +**Step 4 — use the values in templates** like any other: `{{ .Values.registryPassword | quote }}`. + +How secrets are handled across commands: + +| Command | Behaviour | +| --- | --- | +| `talm template` (stdout) | secret values render as `***`; `--show-secrets` prints them verbatim. | +| `talm template -i` (node file) | secret values are omitted entirely from the committed node file — the real value is re-rendered in memory only at apply, so no plaintext (or ciphertext) ever lands in `nodes/*.yaml`. | +| `talm apply --dry-run` | both diffs redact secrets: talm's structured drift preview AND the server-returned `Config diff:` block. `--show-secrets-in-drift` reveals them. | + +The `--show-secrets-in-drift` flag governs every secret-bearing surface of the apply dry-run, covering both these user values and the Talos bootstrap material (`cluster.ca.key`, `machine.token`, encryption secrets, Wireguard keys, etc.). By default a dry-run never prints a CA private key or a user secret in cleartext. + +`talm apply` honours the full set of value sources, matching `talm template`: `--values`, `--set`, `--set-string`, `--set-file`, `--set-json`, `--set-literal`, merged on top of the `templateOptions.*` defaults from `Chart.yaml`. This keeps `template` and `apply` rendering identically. + +**Sharp edge — value-based matching.** Redaction matches by exact value across the whole rendered config, so a secret whose plaintext coincides with an ordinary structural string (a password literally set to `controlplane`, or a bare port like `6443`) will also redact that unrelated field. Prefer high-entropy values; do not encrypt low-entropy strings that collide with non-secret config. + + ## 3. Generate Node Configuration Files Next step is to make node configuration files from templates. From 9884e5e072d36f483158d61b505b42927e2fba07 Mon Sep 17 00:00:00 2001 From: Aleksei Sviridkin Date: Wed, 24 Jun 2026 16:26:31 +0300 Subject: [PATCH 2/3] [docs] talm: address review feedback on encrypted-values section - block-style YAML for the templateOptions.valueFiles example - American English spelling (Behavior, honors) - comma after "By default" for readability Signed-off-by: Aleksei Sviridkin --- content/en/docs/next/install/kubernetes/talm.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/content/en/docs/next/install/kubernetes/talm.md b/content/en/docs/next/install/kubernetes/talm.md index 11de2430..28aa02bb 100644 --- a/content/en/docs/next/install/kubernetes/talm.md +++ b/content/en/docs/next/install/kubernetes/talm.md @@ -273,7 +273,9 @@ registryPassword: "s3cr3t-high-entropy-value" **Step 3 — reference the encrypted file** from `Chart.yaml` by adding it to `templateOptions.valueFiles`, so both `talm template` and `talm apply` read it: ```yaml -templateOptions: { valueFiles: ["values-secret.encrypted.yaml"] } +templateOptions: + valueFiles: + - values-secret.encrypted.yaml ``` Referencing it only via the CLI `--values` flag is a foot-gun: the modeline in a node file does not persist value files, so a later `talm apply` would re-render WITHOUT the secret and silently drop the field. Talm surfaces a warning when an encrypted file is passed via `--values` but is not in `templateOptions.valueFiles`. @@ -282,15 +284,15 @@ Referencing it only via the CLI `--values` flag is a foot-gun: the modeline in a How secrets are handled across commands: -| Command | Behaviour | +| Command | Behavior | | --- | --- | | `talm template` (stdout) | secret values render as `***`; `--show-secrets` prints them verbatim. | | `talm template -i` (node file) | secret values are omitted entirely from the committed node file — the real value is re-rendered in memory only at apply, so no plaintext (or ciphertext) ever lands in `nodes/*.yaml`. | | `talm apply --dry-run` | both diffs redact secrets: talm's structured drift preview AND the server-returned `Config diff:` block. `--show-secrets-in-drift` reveals them. | -The `--show-secrets-in-drift` flag governs every secret-bearing surface of the apply dry-run, covering both these user values and the Talos bootstrap material (`cluster.ca.key`, `machine.token`, encryption secrets, Wireguard keys, etc.). By default a dry-run never prints a CA private key or a user secret in cleartext. +The `--show-secrets-in-drift` flag governs every secret-bearing surface of the apply dry-run, covering both these user values and the Talos bootstrap material (`cluster.ca.key`, `machine.token`, encryption secrets, Wireguard keys, etc.). By default, a dry-run never prints a CA private key or a user secret in cleartext. -`talm apply` honours the full set of value sources, matching `talm template`: `--values`, `--set`, `--set-string`, `--set-file`, `--set-json`, `--set-literal`, merged on top of the `templateOptions.*` defaults from `Chart.yaml`. This keeps `template` and `apply` rendering identically. +`talm apply` honors the full set of value sources, matching `talm template`: `--values`, `--set`, `--set-string`, `--set-file`, `--set-json`, `--set-literal`, merged on top of the `templateOptions.*` defaults from `Chart.yaml`. This keeps `template` and `apply` rendering identically. **Sharp edge — value-based matching.** Redaction matches by exact value across the whole rendered config, so a secret whose plaintext coincides with an ordinary structural string (a password literally set to `controlplane`, or a bare port like `6443`) will also redact that unrelated field. Prefer high-entropy values; do not encrypt low-entropy strings that collide with non-secret config. From 1ac030179a7c13a3dddd28cdd0df5a1e744361c8 Mon Sep 17 00:00:00 2001 From: Aleksei Sviridkin Date: Fri, 3 Jul 2026 11:04:57 +0300 Subject: [PATCH 3/3] docs(talm): use -I for in-place node-file secret redaction row The secret-handling table referenced `talm template -i` for the in-place node-file case, but `-i` is `--insecure` (render via the maintenance service). In-place rendering into nodes/*.yaml uses `-I` / `--in-place`. Assisted-By: Claude Signed-off-by: Aleksei Sviridkin --- content/en/docs/next/install/kubernetes/talm.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/en/docs/next/install/kubernetes/talm.md b/content/en/docs/next/install/kubernetes/talm.md index 28aa02bb..263f0ad7 100644 --- a/content/en/docs/next/install/kubernetes/talm.md +++ b/content/en/docs/next/install/kubernetes/talm.md @@ -287,7 +287,7 @@ How secrets are handled across commands: | Command | Behavior | | --- | --- | | `talm template` (stdout) | secret values render as `***`; `--show-secrets` prints them verbatim. | -| `talm template -i` (node file) | secret values are omitted entirely from the committed node file — the real value is re-rendered in memory only at apply, so no plaintext (or ciphertext) ever lands in `nodes/*.yaml`. | +| `talm template -I` (node file) | secret values are omitted entirely from the committed node file — the real value is re-rendered in memory only at apply, so no plaintext (or ciphertext) ever lands in `nodes/*.yaml`. | | `talm apply --dry-run` | both diffs redact secrets: talm's structured drift preview AND the server-returned `Config diff:` block. `--show-secrets-in-drift` reveals them. | The `--show-secrets-in-drift` flag governs every secret-bearing surface of the apply dry-run, covering both these user values and the Talos bootstrap material (`cluster.ca.key`, `machine.token`, encryption secrets, Wireguard keys, etc.). By default, a dry-run never prints a CA private key or a user secret in cleartext.