TrueNAS CSI Driver
March 3, 2026 ยท View on GitHub
A Container Storage Interface (CSI) driver for TrueNAS 25.10.0+, enabling dynamic provisioning of persistent volumes in Kubernetes using TrueNAS storage.
Features
- NFS volumes - ReadWriteMany (RWX) access mode for shared storage
- iSCSI volumes - Block storage with ReadWriteOnce (RWO) and ReadWriteMany (RWX) access modes (RWX requires cluster filesystem like GFS2/OCFS2)
- Dynamic provisioning - Automatic volume creation and deletion
- Volume expansion - Online resize of volumes
- Snapshots and clones - CSI snapshot support for backup and cloning
- CHAP authentication - Secure iSCSI connections
- ZFS compression - LZ4, ZSTD, GZIP, and other algorithms
- ZFS encryption - Dataset-level encryption with key management
- Automatic snapshot scheduling - Periodic snapshots via StorageClass
- TrueNAS Websocket API - Uses the modern TrueNAS Websocket API
Requirements
TrueNAS
- TrueNAS SCALE 25.10.0+
- API access enabled
- At least one ZFS pool configured
Kubernetes
- Kubernetes 1.26+
- For snapshots: snapshot-controller installed
Node Requirements
- NFS volumes: No additional requirements
- iSCSI volumes:
open-iscsipackage installed on worker nodes
Quick Start
-
Create an API key in TrueNAS
- Log into TrueNAS web UI
- Navigate to your profile โ API Keys
- Create a new API key and copy it
-
Configure the driver
# Edit the deployment manifest vi deploy/truenas-csi-driver.yamlUpdate the ConfigMap with your TrueNAS connection details and the Secret with your API key.
-
Deploy the driver
kubectl apply -f deploy/truenas-csi-driver.yaml -
Create a StorageClass and PVC
kubectl apply -f examples/storageclass-nfs.yaml kubectl apply -f examples/pvc-nfs.yaml
Installation
Prerequisites
Install the snapshot controller (required for snapshot support):
kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/client/config/crd/snapshot.storage.k8s.io_volumesnapshotclasses.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/client/config/crd/snapshot.storage.k8s.io_volumesnapshotcontents.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/client/config/crd/snapshot.storage.k8s.io_volumesnapshots.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/deploy/kubernetes/snapshot-controller/rbac-snapshot-controller.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/deploy/kubernetes/snapshot-controller/setup-snapshot-controller.yaml
Deploy the Driver
- Edit
deploy/truenas-csi-driver.yamlwith your configuration - Apply the manifest:
kubectl apply -f deploy/truenas-csi-driver.yaml
Verify Installation
# Check driver pods are running
kubectl get pods -n truenas-csi
# Verify CSI driver is registered
kubectl get csidrivers
Non-Standard Kubelet Paths
The default deployment manifest uses /var/lib/kubelet as the kubelet root directory. Some Kubernetes distributions use a different path. If your distribution uses a non-standard path, you must update the following in deploy/truenas-csi-driver.yaml before deploying:
- All
hostPathvalues containing/var/lib/kubelet - The
DRIVER_REG_SOCK_PATHenvironment variable - The
--kubelet-registration-pathargument - The
mountPathfor thekubelet-dirvolume mount on thecsi-nodecontainer
| Distribution | Kubelet Path |
|---|---|
| Standard Kubernetes | /var/lib/kubelet (default) |
| MicroK8s | /var/snap/microk8s/common/var/lib/kubelet |
| K3s | /var/lib/rancher/k3s/agent/kubelet |
Important: The
kubelet-dirmountPathmust match thehostPath. If they differ, NFS mounts will succeed inside the CSI container but will not propagate to kubelet, causing pods to see local storage instead of NFS.
MicroK8s Mount Propagation
MicroK8s runs inside a snap with its own mount namespace. For CSI mount propagation to work, the host root filesystem must have shared propagation before MicroK8s starts:
sudo mount --make-rshared /
microk8s start
To make this persistent across reboots, create a systemd unit:
sudo tee /etc/systemd/system/microk8s-mount-propagation.service <<EOF
[Unit]
Description=Ensure shared mount propagation for MicroK8s
Before=snap.microk8s.daemon-containerd.service
[Service]
Type=oneshot
ExecStart=/bin/mount --make-rshared /
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl enable microk8s-mount-propagation
Configuration
Driver Configuration (ConfigMap)
| Setting | Description | Example |
|---|---|---|
truenasURL | WebSocket URL to TrueNAS API | wss://10.0.0.100/api/current |
truenasInsecure | Skip TLS verification | true (for self-signed certs) |
defaultPool | Default ZFS pool for volumes | tank |
nfsServer | NFS server address | 10.0.0.100 |
iscsiPortal | iSCSI portal address | 10.0.0.100:3260 |
iscsiIQNBase | Base IQN for iSCSI targets | iqn.2024-01.com.example |
StorageClass Parameters
General Parameters
| Parameter | Description | Values |
|---|---|---|
protocol | Storage protocol | nfs, iscsi |
pool | ZFS pool (overrides default) | pool name |
compression | ZFS compression algorithm | OFF, LZ4, GZIP, ZSTD, ZLE, LZJB |
sync | ZFS sync mode | STANDARD, ALWAYS, DISABLED |
NFS Parameters
| Parameter | Description | Example |
|---|---|---|
nfs.hosts | Allowed hosts | 10.0.0.0/8,192.168.1.0/24 |
nfs.networks | Allowed networks | 10.0.0.0/8 |
nfs.mountOptions | Client mount options | hard,nfsvers=4.1 |
nfs.mapAllUser | NFS user mapping (default: root) | postgres |
nfs.mapAllGroup | NFS group mapping (default: wheel) | postgres |
iSCSI Parameters
| Parameter | Description | Values |
|---|---|---|
volblocksize | ZVOL block size | 512, 1K, 2K, 4K, 8K, 16K, 32K, 64K, 128K |
iscsi.blocksize | iSCSI logical block size | 512, 1024, 2048, 4096 |
iscsi.chapUser | CHAP username | string |
iscsi.chapSecret | CHAP password (12-16 chars) | string |
iscsi.chapPeerUser | Mutual CHAP peer user | string |
iscsi.chapPeerSecret | Mutual CHAP peer password | string |
iscsi.initiators | Allowed initiator IQNs | comma-separated |
iscsi.networks | Allowed network CIDRs | comma-separated |
Snapshot Task Parameters
| Parameter | Description | Values |
|---|---|---|
snapshot.schedule | Cron schedule (5 fields) | 0 0 * * * |
snapshot.retention | Retention period | 1-365 |
snapshot.retentionUnit | Retention unit | HOUR, DAY, WEEK, MONTH, YEAR |
snapshot.naming | Naming schema | auto-%Y-%m-%d_%H-%M |
snapshot.recursive | Include child datasets | true, false |
Encryption Parameters
| Parameter | Description | Values |
|---|---|---|
encryption | Enable encryption | true, false |
encryption.algorithm | Encryption algorithm | AES-256-GCM, AES-128-CCM |
encryption.passphrase | Passphrase (min 8 chars) | string |
encryption.key | Hex-encoded key (64 chars) | string |
encryption.generateKey | Auto-generate key | true, false |
Examples
See the examples/ folder for sample configurations:
storageclass-nfs.yaml- Basic NFS StorageClassstorageclass-nfs-compressed.yaml- NFS with ZSTD compressionstorageclass-iscsi.yaml- Basic iSCSI StorageClassstorageclass-iscsi-chap.yaml- iSCSI with CHAP authenticationstorageclass-encrypted.yaml- Encrypted storagepvc-nfs.yaml/pvc-iscsi.yaml- PVC examplespod-with-pvc.yaml- Pod using a PVCvolumesnapshotclass.yaml/volumesnapshot.yaml- Snapshot examples
Building
Build the binary
make build
Build container images
# Build Alpine-based image (standard Kubernetes)
make docker-build
# Build UBI-based image (Red Hat OpenShift certification)
make build-ubi
Push to quay.io
# Login to quay.io
docker login quay.io
# Push UBI image to quay.io/truenas_solutions
make push-ubi
# Push all images (driver, operator, bundle)
make push-all
Run tests
make test
Container Images
| Image | Description |
|---|---|
ghcr.io/truenas/truenas-csi | CSI driver (Alpine-based, for standard Kubernetes) |
quay.io/truenas_solutions/truenas-csi | CSI driver (UBI-based, for Red Hat OpenShift) |
quay.io/truenas_solutions/truenas-csi-operator | Kubernetes operator |
quay.io/truenas_solutions/truenas-csi-operator-bundle | OLM bundle for OperatorHub |
Running the Demo
For an interactive demonstration of all driver features using a local Kind cluster, see docs/demo.md.
OpenShift
The TrueNAS CSI Driver supports Red Hat OpenShift 4.20+ and is designed for OperatorHub distribution.
Quick Start (OpenShift)
-
Install via OperatorHub
- Navigate to Operators > OperatorHub
- Search for "TrueNAS CSI"
- Click Install
-
Create credentials secret
apiVersion: v1 kind: Secret metadata: name: truenas-api-credentials namespace: truenas-csi stringData: api-key: "YOUR-API-KEY" -
Create TrueNASCSI resource
apiVersion: csi.truenas.io/v1alpha1 kind: TrueNASCSI metadata: name: truenas spec: truenasURL: "wss://your-truenas-ip/api/current" credentialsSecret: "truenas-api-credentials" defaultPool: "tank" nfsServer: "your-truenas-ip"
OpenShift Documentation
- Installation Guide - Detailed installation steps
- Configuration Reference - CRD and StorageClass options
- Upgrade Guide - Upgrade procedures
- Red Hat Certification Guide - Certification process and requirements
Demo Scripts
Interactive demo scripts are provided to test the CSI driver:
Standard Kubernetes (Kind)
# Set TrueNAS connection details in deploy/truenas-csi-driver.yaml, then:
./demo-simple.sh
OpenShift (CRC/OpenShift Local)
# Set environment variables
export TRUENAS_IP=192.168.1.100
export TRUENAS_API_KEY=your-api-key
export TRUENAS_POOL=tank
# Run the demo
./demo-openshift.sh
Both demos provide interactive menus to test NFS/iSCSI provisioning, volume expansion, snapshots, and cloning.
Contributing
- Report issues: https://github.com/truenas/truenas-csi/issues
- Submit pull requests: https://github.com/truenas/truenas-csi/pulls
License
GNU General Public License 3.0