Machine config
talosctl apply-config. Same inputs, same node, every time.From secrets to three files
CAs, keys, tokens. The only thing that must stay secret and stable: regenerate it and you have a different cluster.
Deterministic: same secrets and patches always yield the same configs.
talosctl gen secrets -o secrets.yaml # keep this in a vault / SOPS
talosctl gen config homelab https://10.0.0.5:6443 \
--with-secrets secrets.yaml \
--config-patch @patches/install.yaml \
--config-patch-control-plane @patches/cilium.yaml \
--output-dir _out
talosctl validate --config _out/controlplane.yaml --mode metal# render a node-specific file (no secrets in git if you template them)
talosctl machineconfig patch _out/controlplane.yaml \
--patch @nodes/cp-1.yaml -o cp-1.yaml
# or patch a running node in place
talosctl -n 10.0.0.10 patch machineconfig --patch @nodes/cp-1.yaml
# or open the live config in $EDITOR
talosctl -n 10.0.0.10 edit machineconfigTwo halves: machine and cluster
machine: is about this node. cluster: is about the Kubernetes cluster and is identical across nodes (workers get a trimmed copy without the CA keys).- type
- controlplane or worker. Decides whether etcd and the control-plane static pods run.
- token / ca
- The machine token and Talos API CA: how nodes join (via trustd) and how apid trusts clients.
- certSANs
- Extra names/IPs in the Talos API certificate.
- kubelet
- Image (= Kubernetes version), extraArgs, extraMounts, nodeIP selection.
- network
- Hostname, interfaces (static addresses, bonds, VLANs, VIP), routes, nameservers.
- install
- Target disk (or diskSelector) and installer image. Used at install and upgrade.
- features
- KubePrism, hostDNS, RBAC for the Talos API, Talos API access from pods…
- sysctls, kernel, files, registries
- Node-level tuning, kernel modules, registry mirrors and auth.
- controlPlane.endpoint
- The URL every kubelet and client uses for the API server: a VIP, load balancer or DNS name, never one node.
- clusterName
- Name baked into kubeconfig and certs.
- network
- cni (flannel / none / custom URLs), podSubnets, serviceSubnets, dnsDomain.
- proxy
- kube-proxy settings, or disabled: true when a CNI replaces it.
- apiServer / controllerManager / scheduler
- Images, extraArgs, certSANs, admission config for the static pods.
- etcd
- CA, extraArgs, advertisedSubnets for multi-homed nodes.
- discovery
- Discovery registries used for node membership (and KubeSpan).
- secrets
- ca, aggregatorCA, serviceAccount key, secretboxEncryptionSecret, bootstrap token: the cluster's identity.
Patches: small, composable, reviewable
$patch: delete removes a key. Toggle patches and watch the merged config; each highlighted line is colored by the patch that introduced it.Strategic-merge playground
cluster:
network:
cni:
name: none
proxy:
disabled: trueTalos deploys Flannel and kube-proxy by default. Setting cni.name: none and proxy.disabled leaves the slot free for Cilium with kube-proxy replacement. Nodes stay NotReady until you install it.
talosctl gen config homelab https://10.0.0.5:6443 \ --with-secrets secrets.yaml \ --config-patch @patches/cp1-network.yaml \ --config-patch @patches/cilium.yaml
version: v1alpha1debug: falsepersist: truemachine:type: controlplanetoken: 7k2x9f.q8wzr4h1m0c6ab3tca:crt: LS0tLS1CRUdJTi…key: LS0tLS1CRUdJTi…certSANs: []kubelet:image: ghcr.io/siderolabs/kubelet:v1.34.1defaultRuntimeSeccompProfileEnabled: truedisableManifestsDirectory: truenetwork:hostname: cp-1nameservers:- 10.0.0.1interfaces:- deviceSelector:physical: trueaddresses:- 10.0.0.10/24routes:- network: 0.0.0.0/0gateway: 10.0.0.1vip:ip: 10.0.0.5install:disk: /dev/sdaimage: ghcr.io/siderolabs/installer:v1.11.3wipe: falsefeatures:rbac: truestableHostname: trueapidCheckExtKeyUsage: truediskQuotaSupport: truekubePrism:enabled: trueport: 7445hostDNS:enabled: trueforwardKubeDNSToHost: truecluster:id: Qm9vdHN0cmFwIElE…secret: c2VjcmV0…controlPlane:endpoint: https://10.0.0.5:6443clusterName: homelabnetwork:dnsDomain: cluster.localpodSubnets:- 10.244.0.0/16serviceSubnets:- 10.96.0.0/12cni:name: nonetoken: abc123.0123456789abcdefsecretboxEncryptionSecret: z8x…ca:crt: LS0tLS1CRUdJTi…key: LS0tLS1CRUdJTi…apiServer:image: registry.k8s.io/kube-apiserver:v1.34.1certSANs:- 10.0.0.5controllerManager:image: registry.k8s.io/kube-controller-manager:v1.34.1proxy:image: registry.k8s.io/kube-proxy:v1.34.1disabled: truescheduler:image: registry.k8s.io/kube-scheduler:v1.34.1discovery:enabled: trueregistries:kubernetes:disabled: trueservice: {}etcd:ca:crt: LS0tLS1CRUdJTi…key: LS0tLS1CRUdJTi…
---: the classic v1alpha1 document plus typed documents such as ExtensionServiceConfig, and in newer releases VolumeConfig / UserVolumeConfig for disk layout. Recent releases keep moving settings (e.g. parts of networking) into their own documents. Patches can target either kind.cluster:
network:
cni:
name: none # Talos won't deploy flannel
proxy:
disabled: true # Cilium replaces kube-proxy
machine:
features:
kubePrism:
enabled: true # default in generated configs
port: 7445 # Cilium's k8sServiceHost=localhost, k8sServicePort=7445machine:
nodeLabels:
node.kubernetes.io/storage: longhorn
---
apiVersion: v1alpha1
kind: UserVolumeConfig
name: longhorn
provisioning:
diskSelector:
match: disk.transport == "nvme"
minSize: 100GiB
---
apiVersion: v1alpha1
kind: ExtensionServiceConfig
name: nut-client
environment:
- UPS_HOST=10.0.0.2Applying a change: does it need a reboot?
cluster: section) is reconciled live by machined's controllers. A few fields only take effect at boot. The mode decides what happens when you mix them.Apply modes
Default. Apply live if every change supports it, otherwise apply and reboot.
Change categories follow the Talos docs on which fields support live apply; when in doubt, --dry-run prints the diff and whether a reboot would be needed. Modes shown are those of Talos ≤1.13; Talos 1.14 removed --mode=reboot, and the default now applies without rebooting (reboot-only changes wait for your next reboot). Try-mode timer runs at 10× speed here.
# maintenance mode (fresh ISO boot): no certs yet, so --insecure
talosctl apply-config --insecure -n 10.0.0.10 -f cp-1.yaml
# afterwards: authenticated, and preview first
talosctl -n 10.0.0.10 apply-config -f cp-1.yaml --dry-run
talosctl -n 10.0.0.10 apply-config -f cp-1.yaml --mode try --timeout 2m- why it matterssecrets.yaml is the cluster's identity; everything else is derived. Back it up, and you can regenerate every node config at will.
- why it mattersPatches keep intent small and reviewable: "use Cilium", "static IP for cp-1". The generated base can change between Talos versions without merge conflicts in your repo.
- why it mattersMost changes apply live because machined reconciles them; use --dry-run to see the diff and --mode try for changes that could cut you off.