Files
docs/platforms/virtualization/proxmox/configuring-iscsi-based-cluster-storage.md
Nicole Rappe e73bb0376f
All checks were successful
GitOps Automatic Documentation Deployment / Sync Docs to https://kb.bunny-lab.io (push) Successful in 4s
GitOps Automatic Documentation Deployment / Sync Docs to https://docs.bunny-lab.io (push) Successful in 6s
Documentation Restructure
2026-01-27 05:25:22 -07:00

7.0 KiB

Purpose

This document describes the end-to-end procedure for creating a thick-provisioned iSCSI-backed shared storage target on TrueNAS CORE, and consuming it from a Proxmox VE cluster using shared LVM.

This approach is intended to:

  • Provide SAN-style block semantics
  • Enable Proxmox-native snapshot functionality (LVM volume chains)
  • Avoid third-party plugins or middleware
  • Be fully reproducible via CLI

Assumptions

  • TrueNAS CORE (not SCALE)
  • ZFS pool already exists and is healthy
  • SSH service is enabled on TrueNAS
  • Proxmox VE nodes have network connectivity to TrueNAS
  • iSCSI traffic is on a reliable, low-latency network (10GbE recommended)
  • All VM workloads are drained from at least one Proxmox node for maintenance

!!! note "Proxmox VE Version Context" This guide assumes Proxmox VE 9.1.4 (or later). Snapshot-as-volume-chain support on shared LVM (e.g., iSCSI) is available and improved, including enhanced handling of vTPM state in offline snapshots.

!!! warning "Important" volblocksize cannot be changed after zvol creation. Choose carefully.

Target Architecture

ZFS Pool
 └─ Zvol (Thick / Reserved)
    └─ iSCSI Extent
       └─ Proxmox LVM PV
          └─ Shared VG
             └─ VM Disks

Create a Dedicated Zvol for Proxmox

Variables

Adjust as needed before execution.

POOL_NAME="CLUSTER-STORAGE"
ZVOL_NAME="iscsi-storage"
ZVOL_SIZE="14T"
VOLBLOCKSIZE="16K"

Create the Zvol (Thick-Provisioned)

zfs create -V ${ZVOL_SIZE} \
  -o volblocksize=${VOLBLOCKSIZE} \
  -o compression=lz4 \
  -o refreservation=${ZVOL_SIZE} \
  ${POOL_NAME}/${ZVOL_NAME}

!!! note The refreservation enforces true thick provisioning and prevents overcommit.

Configure iSCSI Target (TrueNAS CORE)

This section uses a hybrid approach:

  • CLI is used for ZFS and LUN (extent backing) creation
  • TrueNAS GUI is used for iSCSI portal, target, and association
  • CLI is used again for validation

Enable iSCSI Service

service ctld start
sysrc ctld_enable=YES

Create the iSCSI LUN Backing (CLI)

This step creates the actual block-backed LUN that will be exported via iSCSI.

# Sanity check: confirm the backing zvol exists
ls -l /dev/zvol/${POOL_NAME}/${ZVOL_NAME}

# Create CTL LUN backed by the zvol
ctladm create -b block \
  -o file=/dev/zvol/${POOL_NAME}/${ZVOL_NAME} \
  -S ISCSI-STORAGE \
  -d ISCSI-STORAGE

Verify the LUN is real and correctly sized

ctladm devlist -v

!!! tip Size (Blocks) must be non-zero and match the zvol size. If it is 0, stop and correct before proceeding.

Configure iSCSI Portal, Target, and Extent Association (CLI Only)

!!! warning "Do NOT Use the TrueNAS iSCSI GUI" Once you choose a CLI-managed iSCSI configuration, the TrueNAS Web UI must never be used for iSCSI. Opening or modifying Sharing → Block Shares (iSCSI) in the GUI will overwrite CTL runtime state, invalidate manual ctladm configuration, and result in targets that appear correct but expose no LUNs to initiators.

This configuration is CLI-owned and CLI-managed.

  • Do not add, edit, or view iSCSI objects in the GUI
  • Do not use the iSCSI wizard
  • Do not mix GUI extents with CLI-created LUNs

Create iSCSI Portal (Listen on All Interfaces)

# Backup any existing ctl.conf
cp -av /etc/ctl.conf /etc/ctl.conf.$(date +%Y%m%d-%H%M%S).bak 2>/dev/null || true

# Write a clean /etc/ctl.conf
cat > /etc/ctl.conf <<'EOF'
# --- Bunny Lab: Proxmox iSCSI (CLI-only) ---
auth-group "no-auth" {
  auth-type none
  initiator-name "iqn.1993-08.org.debian:01:5b963dd51f93"   # cluster-node-01 ("cat /etc/iscsi/initiatorname.iscsi")
  initiator-name "iqn.1993-08.org.debian:01:1b4df0fa3540"   # cluster-node-02 ("cat /etc/iscsi/initiatorname.iscsi")
  initiator-name "iqn.1993-08.org.debian:01:5669aa2d89a2"   # cluster-node-03 ("cat /etc/iscsi/initiatorname.iscsi")
}

# Listen on all interfaces on the default iSCSI port
portal-group "pg0" {
  listen 0.0.0.0:3260
  discovery-auth-group "no-auth"
}

# Create a target IQN
target "iqn.2026-01.io.bunny-lab:storage" {
  portal-group "pg0"
  auth-group "no-auth"

  # Export LUN 0 backed by the zvol device
  lun 0 {
    path /dev/zvol/CLUSTER-STORAGE/iscsi-storage
    serial "ISCSI-STORAGE"
    device-id "ISCSI-STORAGE"
  }
}
EOF

# Restart ctld to apply the configuration file
service ctld restart

# Verify the iSCSI listener is actually up
sockstat -4l | grep ':3260'

# Verify CTL now shows an iSCSI frontend
ctladm portlist -v | egrep -i '(^Port|iscsi|listen=)'

!!! success At this point, the iSCSI target is live and correctly exposing a block device to initiators. You may now proceed to Connect from ProxmoxVE Nodes section.

Connect from ProxmoxVE Nodes

Perform the following on each Proxmox node.

# Install iSCSI Utilities
apt update
apt install -y open-iscsi lvm2

# Discover Target
iscsiadm -m discovery -t sendtargets -p <TRUENAS_IP>

# Log In
iscsiadm -m node --login

# Rescan SCSI Bus
iscsiadm -m session -P 3

### Verify Device
# If everything works successfully, you should see something like "sdi 8:128 0 8T 0 disk".
lsblk

Create Shared LVM (Execute on One Node Only)

!!! warning "Important" Only run LVM creation on ONE node. All other nodes will only scan.

# Initialize Physical Volume
pvcreate /dev/sdX

# Create Volume Group
vgcreate vg_proxmox_iscsi /dev/sdX

Register Storage in Proxmox

Rescan LVM (Other Nodes)

pvscan
vgscan

Add Storage (GUI)

Datacenter → Storage → Add → LVM

  • ID: iscsi-cluster-lvm
  • Volume Group: vg_proxmox_iscsi
  • Content: Disk image, Container
  • Shared: ✔️
  • Allow Snapshots as Volume-Chain: ✔️

Validation

  • Snapshot create / revert / delete
  • Live migration between nodes
  • PBS backup and restore test

!!! success If all validation tests pass, the storage is production-ready.

Expanding iSCSI Storage (No Downtime)

If you need to expand the storage space of the newly-created iSCSI LUN, you can run the ZFS commands seen below on the TrueNAS Core server. The first command increases the size, the second command pre-allocated the space (thick-provisioned).

!!! warning "ProxmoxVE Cluster-specific Notes"

- `pvresize` must be executed on **exactly one** ProxmoxVE node.
- All other nodes should only perform `pvscan` / `vgscan` after the resize.
- Running `pvresize` on multiple nodes can corrupt shared LVM metadata.
# Expand Zvol (TrueNAS)
zfs set volsize=16T CLUSTER-STORAGE/iscsi-storage
zfs set refreservation=16T CLUSTER-STORAGE/iscsi-storage
service ctld restart

# Rescan the block device on all ProxmoxVE nodes
echo 1 > /sys/class/block/sdX/device/rescan

# Verify on all nodes that the new size is displayed
lsblk /dev/sdX

# Run this on only ONE of the ProxmoxVE nodes.
pvresize /dev/sdX

# Rescan on the other nodes that you did not run the pvresize command on.  They will now see the expanded free space.
pvscan
vgscan