> ## Documentation Index
> Fetch the complete documentation index at: https://docs.siderolabs.com/llms.txt
> Use this file to discover all available pages before exploring further.

# User Volumes

> Configuring user volumes to allocate local storage for Kubernetes workloads.

export const VersionWarningBanner = () => {
  const latestVersion = "v1.13";
  const [latestUrl, setLatestUrl] = useState(null);
  const [currentVersion, setCurrentVersion] = useState(null);
  const [isBeta, setIsBeta] = useState(false);
  const parseVersion = v => v.replace("v", "").split(".").map(Number);
  const isGreaterVersion = (a, b) => {
    const [aMajor, aMinor] = parseVersion(a);
    const [bMajor, bMinor] = parseVersion(b);
    if (aMajor > bMajor) return true;
    if (aMajor === bMajor && aMinor > bMinor) return true;
    return false;
  };
  useEffect(() => {
    if (typeof window === "undefined") return;
    const {pathname, hash, search} = window.location;
    const match = pathname.match(/\/talos\/(v\d+\.\d+)\//);
    if (!match) return;
    const detectedVersion = match[1];
    if (detectedVersion === latestVersion) return;
    setCurrentVersion(detectedVersion);
    if (isGreaterVersion(detectedVersion, latestVersion)) {
      setIsBeta(true);
    }
    const newPath = pathname.replace(`/talos/${detectedVersion}/`, `/talos/${latestVersion}/`);
    setLatestUrl(`${newPath}${search}${hash}`);
  }, []);
  if (!latestUrl || !currentVersion) return null;
  return <div className="not-prose sticky top-6 z-50 my-6">
      <div className="border border-yellow-500/30 bg-yellow-500/10 px-4 py-3 rounded-xl">
        <div className="text-sm">
          {isBeta ? <>
              ⚠️ You are viewing a <strong>beta version</strong> of Talos ({currentVersion}).
              This version may be unstable.
              <a href={latestUrl} className="ml-2 underline text-yellow-400 hover:text-yellow-300 font-medium">
                View latest stable version {latestVersion} →
              </a>
            </> : <>
              ⚠️ You are viewing an older version of Talos ({currentVersion}).
              <a href={latestUrl} className="ml-2 underline text-yellow-400 hover:text-yellow-300 font-medium">
                View the latest version {latestVersion} →
              </a>
            </>}
        </div>
      </div>
    </div>;
};

<VersionWarningBanner />

User Volumes allow to treat available disk space as a pool of allocatable resource, which can be dynamically allocated to different applications.
The user volumes are supposed to be used mostly for `hostPath` mounts in Kubernetes, but they can be used for other purposes as well.

When a user volume configuration is applied, Talos Linux will either locate an existing volume or provision a new one.
The volume will be created on the disk which satisfies the `diskSelector` expression and has enough free space to satisfy the `minSize` requirement.

The user volume is identified by a unique name, which is used both as a mount location and as a label for the volume.
The volume name must be unique across all user volumes, and it should be between 1 and 34 characters long, and can only contain ASCII letters, digits, and `-` (dash) characters.

The volume label is derived from the volume name as `u-<volume-name>`, and it is used to identify the volume on the disk after initial provisioning.
The volume mount location is `/var/mnt/<volume-name>`, and it gets automatically propagated into the `kubelet` container to provide additional features like `subPath` mounts.

Disk encryption can be optionally enabled for user volumes.

## Create user volumes

To create a user volume, append the following [document](../../../reference/configuration/block/uservolumeconfig) to the machine configuration:

```yaml theme={null}
# user-volume.patch.yaml
apiVersion: v1alpha1
kind: UserVolumeConfig
name: local-volume
provisioning:
  diskSelector:
    match: disk.transport == 'nvme'
  minSize: 100GB
  maxSize: 200GB
```

For example, this machine configuration patch can be applied using the following command:

```bash theme={null}
talosctl --nodes <NODE> patch mc --patch @user-volume.patch.yaml
```

In this example, a user volume named `local-volume` is created on the first NVMe disk which has `100GB` of disk space available, and it will be created as maximum
of `200GB` if that space is available.

The status of the volume can be checked using the following command:

```bash theme={null}
$ talosctl get volumestatus u-local-volume # note u- prefix
NAMESPACE   TYPE           ID            VERSION   TYPE        PHASE   LOCATION         SIZE
runtime     VolumeStatus   u-local-volume   2         partition   ready   /dev/nvme0n1p2   200 GB
```

If the volume fails to be provisioned, use the `-o yaml` flag to get additional details.

The volume is immediately mounted to `/var/mnt/local-volume`:

```bash theme={null}
$ talosctl get mountstatus
NAMESPACE   TYPE          ID           VERSION   SOURCE           TARGET               FILESYSTEM   VOLUME
runtime     MountStatus   u-local-volume  2         /dev/nvme0n1p2   /var/mnt/local-volume   xfs          u-local-volume
```

It can be used in a Kubernetes pod as a `hostPath` mount:

```yaml theme={null}
kind: Pod
spec:
  containers:
    - name: ceph
      volumeMounts:
        - mountPath: /var/lib/ceph
          name: local-volume
  volumes:
    - name: local-volume
      hostPath:
        path: /var/mnt/local-volume
```

Please note, the path inside the container can be different from the path on the host.

## Remove user volumes

Before removing a user volume, ensure that it is not mounted in any Kubernetes pod.

In order to remove a user volume, first remove the configuration document from the machine configuration.
The `VolumeStatus` and `MountStatus` resources will be removed automatically by Talos Linux.

> Note: The actual disk data hasn't been removed yet, so you can re-apply the user volume configuration back
> and it will be re-provisioned on the same disk.

To wipe the disk data, and make it allocatable again, use the following command:

```bash theme={null}
talosctl wipe disk nvme0n1p2 --drop-partition
```

The `nvme0n1p2` is the partition name, and it can be obtained from the `VolumeStatus` resource before the user volume is removed,
or from the `DiscoveredVolume` resource any time later.

> Note: If the `wipe disk` command fails with `blockdevice is in use by volume`, it means the user volume has not been removed from the machine configuration.

## Types of user volumes

`UserVolumeConfig` includes an optional `volumeType` field that controls how a user volume is created and managed.
If omitted, the system defaults to `partition`.
Types `disk` and `directory` are advanced options with specific use cases. If unsure, use the default `partition` type.

### `volumeType: partition` (default)

A standard volume backed by a dedicated partition on the underlying storage device.
If you are unsure which type to choose, this is the recommended option.

### `volumeType: disk`

It is primarily intended for scenarios where you want to dedicate a whole disk to a single workload without partitioning - for example, when provisioning on top of LVM logical volumes or other block devices that do not support partitioning.
When set to `disk`, the volume is provisioned from an entire block device rather than a partition.
If you want to consume the entire disk with partitioning support, use a `partition` user volume instead and set `grow: true` without specifying `maxSize`.

When using `volumeType: disk`, the disk itself is not labeled or partitioned. The disk selector must uniquely and stably identify the device (for example via WWN, serial, or persistent path). If the selector is ambiguous, a different device may be selected after a reboot.

Restrictions for `disk` volumes:

* The provisioning block must not define size-related settings (`minSize`, `maxSize`, or `grow`).
  A full device implies a fixed size.

### `volumeType: directory`

This type is useful for lightweight storage needs where full partitioning is unnecessary or impractical, and all that is required is a simple directory on the EPHEMERAL volume.
When set to `directory`, the system bypasses provisioning and filesystem creation. Instead, it creates a host directory at:

```
/var/mnt/<metadata.name>
```

Characteristics and limitations of `directory` volumes:

* No provisioning, filesystem operations, or encryption are performed.
* The volume is simply a directory on the EPHEMERAL volume.
* This type provides minimal overhead but does not deliver filesystem-level isolation.
* Storage capacity is limited by the host’s EPHEMERAL partition.
* Not suitable for workloads that require predictable or enforceable storage quotas.
