Configuration Model
The final machine configuration for each node is assembled from a series of configuration documents (patches) which are merged together. This is similar to how talosctl applies --config-patch flags — each patch is a partial Talos machine configuration that gets strategically merged into the result.
Merge Order
Patches are applied in the following order:
all/— applied to all nodes<role>/— applied to nodes matching the role (control-planeorworker)node/<host>/— applied only to that specific node
Tip
The per-host directory is node/ (singular), not nodes/ as each <host>/ subfolder targets a single node at a time.
Within each folder, patches are applied in lexicographical order. Later patches take precedence over earlier ones when the same field is set. This layering is useful for per-node overrides — for example, pinning a different installer image on a single host.
A typical cluster folder looks like this:
.
├── all
│ └── 01-installation.yaml
├── control-plane
│ ├── 01-vip.yaml
│ ├── 02-disable-discovery.yaml
│ └── 03-allow-cp-scheduling.yaml
├── worker
│ └── 01-worker-taints.yaml
├── node
│ └── node1
│ └── 01-some-nodespecific-patch.yaml
└── topf.yaml
Tip
Prefix patch filenames with a number (e.g. 01-, 02-) to make the merge order explicit and predictable.
Patch Formats
Patches can be provided in several formats:
| Extension | Format |
|---|---|
.yaml / .yml |
Strategic merge patch |
.yaml.tpl / .yml.tpl |
Go-templated strategic merge patch |
Warning
JSON patches (RFC 6902) are not supported. They have been deprecated in Talos starting from v1.12.
Empty patches (comments only, whitespace, {}, [], null) are automatically skipped.
Secret Resolution
TOPF reads all non-template files (including topf.yaml itself) through a two-stage pipeline:
- SOPS decryption — if a file is SOPS-encrypted, it is decrypted automatically. If SOPS is not installed, unencrypted files are read as-is.
- vals evaluation — after decryption, any vals references (e.g.
ref+vault://,ref+file://) are resolved. If no vals references are present, this step is skipped. Thevalsbinary must be onPATHwhen vals references are used.
Template files (ending with .tpl) skip this pipeline entirely and are rendered through Go templates instead.
This is useful for keeping sensitive values (e.g. private keys, credentials, tokens) out of version control — either by encrypting the entire file with SOPS, or by referencing secrets from an external store via vals.
Templating
Patches ending with .yaml.tpl support Go templating. The following context fields are available:
| Field | Description |
|---|---|
.ClusterName |
Cluster name from topf.yaml |
.ClusterEndpoint |
Cluster endpoint URL |
.KubernetesVersion |
Kubernetes version |
.TalosVersion |
Talos version (if set in topf.yaml) |
.SchematicID |
Schematic ID (if set in topf.yaml) |
.Data.<key> |
Arbitrary global data from topf.yaml (see configuration) |
.Node.Host |
Node hostname |
.Node.Role |
Node role (control-plane or worker) |
.Node.IP |
Node IP address (if set) |
.Node.Data.<key> |
Per-node data (if set) |
Template Functions
In addition to the built-in Go template functions, the full sprig function library is available. This provides env, default, b64enc/b64dec, toYaml, indent/nindent, regexReplaceAll, trunc, trimAll, and many more.
A few commonly used functions:
| Function | Description |
|---|---|
env "VAR" |
Returns the value of the environment variable VAR, or an empty string if unset |
default "x" .Val |
Returns .Val, falling back to "x" if .Val is empty |
b64enc / b64dec |
Base64 encode / decode |
Examples
Use per-node data in a patch:
Use the env function in a multi-document template to conditionally configure a registry mirror: