---
title: "Configuration Patches"
description: "In this guide, we'll patch the generated machine configuration."
---

Talos generates machine configuration for two types of machines: controlplane and worker machines.
Many configuration options can be adjusted using `talosctl gen config` but not all of them.
Configuration patching allows modifying machine configuration to fit it for the cluster or a specific machine.

## Configuration Patch Formats

Talos supports two configuration patch formats:

- strategic merge patches
- RFC6902 (JSON patches)

Strategic merge patches are the easiest to use, but JSON patches allow more precise configuration adjustments.

### Strategic Merge patches

Strategic merge patches look like incomplete machine configuration files:

```yaml
machine:
  network:
    hostname: worker1
```

When applied to the machine configuration, the patch gets merged with the respective section of the machine configuration:

```yaml
machine:
  network:
    interfaces:
      - interface: eth0
        addresses:
          - 10.0.0.2/24
    hostname: worker1
```

In general, machine configuration contents are merged with the contents of the strategic merge patch, with strategic merge patch
values overriding machine configuration values.
There are some special rules:

- If the field value is a list, the patch value is appended to the list, with the following exceptions:
  - values of the fields `cluster.network.podSubnets` and `cluster.network.serviceSubnets` are overwritten on merge
  - `network.interfaces` section is merged with the value in the machine config if there is a match on `interface:` or `deviceSelector:` keys

### RFC6902 (JSON Patches)

[JSON patches](https://jsonpatch.com/) can be written either in JSON or YAML format.
A proper JSON patch requires an `op` field that depends on the machine configuration contents: whether the path already exists or not.

For example, the strategic merge patch from the previous section can be written either as:

```yaml
- op: replace
  path: /machine/network/hostname
  value: worker1
```

or:

```yaml
- op: add
  path: /machine/network/hostname
  value: worker1
```

The correct `op` depends on whether the `/machine/network/hostname` section exists already in the machine config or not.

## Examples

### Machine Network

Base machine configuration:

```yaml
# ...
machine:
  network:
    interfaces:
      - inteface: eth0
        dhcp: false
        addresses:
          - 192.168.10.3/24
```

The goal is to add a virtual IP `192.168.10.50` to the `eth0` interface and add another interface `eth1` with DHCP enabled.

<!-- markdownlint-disable MD007 -->
<!-- markdownlint-disable MD032 -->
<!-- markdownlint-disable MD025 -->

{{< tabpane lang="yaml" >}}
{{< tab header="Strategic merge patch" >}}
machine:
  network:
    interfaces:
      - interface: eth0
        vip:
          ip: 192.168.10.50
      - interface: eth1
        dhcp: true
{{< /tab >}}
{{< tab header="JSON patch" >}}
- op: add
  path: /machine/network/interfaces/0/vip
  value:
    ip: 192.168.10.50
- op: add
  path: /machine/network/interfaces/-
  value:
    interface: eth1
    dhcp: true
{{< /tab >}}
{{< /tabpane >}}

Patched machine configuration:

```yaml
machine:
  network:
    interfaces:
      - inteface: eth0
        dhcp: false
        addresses:
          - 192.168.10.3/24
        vip:
          ip: 192.168.10.50
      - interface: eth1
        dhcp: true
```

### Cluster Network

Base machine configuration:

```yaml
cluster:
  network:
    dnsDomain: cluster.local
    podSubnets:
      - 10.244.0.0/16
    serviceSubnets:
      - 10.96.0.0/12
```

The goal is to update pod and service subnets and disable default CNI (Flannel).

{{< tabpane lang="yaml" >}}
{{< tab header="Strategic merge patch" >}}
cluster:
  network:
    podSubnets:
      - 192.168.0.0/16
    serviceSubnets:
      - 192.0.0.0/12
    cni:
      name: none
{{< /tab >}}
{{< tab header="JSON patch" >}}
- op: replace
  path: /cluster/network/podSubnets
  value:
    - 192.168.0.0/16
- op: replace
  path: /cluster/network/serviceSubnets
  value:
    - 192.0.0.0/12
- op: add
  path: /cluster/network/cni
  value:
    name: none
{{< /tab >}}
{{< /tabpane >}}

Patched machine configuration:

```yaml
cluster:
  network:
    dnsDomain: cluster.local
    podSubnets:
      - 192.168.0.0/16
    serviceSubnets:
      - 192.0.0.0/12
    cni:
      name: none
```

### Kubelet

Base machine configuration:

```yaml
# ...
machine:
  kubelet: {}
```

The goal is to set the `kubelet` node IP to come from the subnet `192.168.10.0/24`.

{{< tabpane lang="yaml" >}}
{{< tab header="Strategic merge patch" >}}
machine:
  kubelet:
    nodeIP:
      validSubnets:
        - 192.168.10.0/24
{{< /tab >}}
{{< tab header="JSON patch" >}}
- op: add
  path: /machine/kubelet/nodeIP
  value:
    validSubnets:
      - 192.168.10.0/24
{{< /tab >}}
{{< /tabpane >}}

Patched machine configuration:

```yaml
machine:
  kubelet:
    nodeIP:
      validSubnets:
        - 192.168.10.0/24
```

### Admission Control: Pod Security Policy

Base machine configuration:

```yaml
cluster:
  apiServer:
    admissionControl:
      - name: PodSecurity
        configuration:
          apiVersion: pod-security.admission.config.k8s.io/v1alpha1
          defaults:
            audit: restricted
            audit-version: latest
            enforce: baseline
            enforce-version: latest
            warn: restricted
            warn-version: latest
          exemptions:
            namespaces:
              - kube-system
            runtimeClasses: []
            usernames: []
          kind: PodSecurityConfiguration
```

The goal is to add an exemption for the namespace `rook-ceph`.

{{< tabpane lang="yaml" >}}
{{< tab header="Strategic merge patch" >}}
cluster:
  apiServer:
    admissionControl:
      - name: PodSecurity
        configuration:
          exemptions:
            namespaces:
              - rook-ceph
{{< /tab >}}
{{< tab header="JSON patch" >}}
- op: add
  path: /cluster/apiServer/admissionControl/0/configuration/exemptions/namespaces/-
  value: rook-ceph
{{< /tab >}}
{{< /tabpane >}}

Patched machine configuration:

```yaml
cluster:
  apiServer:
    admissionControl:
      - name: PodSecurity
        configuration:
          apiVersion: pod-security.admission.config.k8s.io/v1alpha1
          defaults:
            audit: restricted
            audit-version: latest
            enforce: baseline
            enforce-version: latest
            warn: restricted
            warn-version: latest
          exemptions:
            namespaces:
              - kube-system
              - rook-ceph
            runtimeClasses: []
            usernames: []
          kind: PodSecurityConfiguration
```

## Configuration Patching with `talosctl` CLI

Several `talosctl` commands accept config patches as command-line flags.
Config patches might be passed either as an inline value or as a reference to a file with `@file.patch` syntax:

```shell
talosctl ... --patch '[{"op": "add", "path": "/machine/network/hostname", "value": "worker1"}]' --patch @file.patch
```

If multiple config patches are specified, they are applied in the order of appearance.
The format of the patch (JSON patch or strategic merge patch) is detected automatically.

Generated machine configuration can be patched with `talosctl gen config`:

```shell
talosctl gen config test-cluster https://172.20.0.1:6443 --config-patch @all.yaml --config-patch-control-plane @cp.yaml --config-patch-worker @worker.yaml
```

Machine configuration on the running Talos node can be patched with `talosctl patch`:

```shell
talosctl patch mc --nodes 172.20.0.2 --patch @patch.yaml
```
