Skip to content
Français
Account: not signed in, sync available My learning
Select theme
Français

Use iSCSI on Linux

By updated

Improve this page

iSCSI lets you present a remote disk to a Linux server as if it were plugged in locally, using the standard IP network. Unlike NFS, which shares files, iSCSI shares raw blocks: the client sees a real disk (/dev/sda), formats it and mounts it like a local disk. This guide covers the full configuration of a target (server) with targetcli and of an initiator (client) with open-iscsi on Ubuntu 24.04; every command was tested in a KVM lab.

What you will learn

  • How iSCSI works: protocol, vocabulary, architecture
  • Target (server): targetcli, block and fileio backstores, IQN, TPG
  • LUNs and ACLs: expose disks and control access
  • Initiator (client): open-iscsi, discovery, login, mount
  • CHAP security: one-way and mutual authentication
  • Persistent mount: /etc/fstab with _netdev
  • Troubleshooting: frequent errors and tested fixes

What is iSCSI?

iSCSI (Internet Small Computer Systems Interface) is a protocol that carries SCSI commands (the standard language of hard disks) across a classic TCP/IP network. It turns any server into a network storage array (SAN) without specialised hardware.

iSCSI vs NFS: two complementary approaches

CriterioniSCSINFS
Type of sharingBlock (raw disk)Files (directory)
What the client sees/dev/sdX, a disk/mnt/nfs, a folder
File systemChosen by the client (ext4, xfs...)Managed by the server
Multi-clientA single client per LUN (except clustered FS)Several clients at once
PerformanceExcellent (close to a local disk)Good
Use casesDatabases, VMs, block storageFile shares, configs, homes
Port3260/tcp2049/tcp

The iSCSI vocabulary

Before starting, here are the terms you will come across:

TermDefinition
TargetThe server that exposes the disks
InitiatorThe client that connects and uses the disks
IQNUnique identifier (iSCSI Qualified Name), format: iqn.YYYY-MM.domain:identifier
TPGTarget Portal Group, network access point (IP:port)
LUNLogical Unit Number, a disk exposed in a TPG
BackstoreThe physical storage behind a LUN (partition, file, LVM volume)
ACLAccess Control List, controls which initiator reaches which LUN
CHAPChallenge-Handshake Authentication Protocol, password authentication
PortalIP:port pair the target listens on (default: 0.0.0.0:3260)

Prerequisites

  • 2 Ubuntu 24.04 machines (physical or virtual)
  • Network connectivity between the two
  • root or sudo access on both machines
  • Port 3260/tcp open between the target and the initiator
  • On the target: an additional disk or partition to expose

To reproduce this lab, two KVM VMs are enough: a target (192.168.122.50, with a 10 GB /dev/vdb disk) and an initiator (192.168.122.225).

Lab architecture

The lab links two machines through the single port 3260. The target exposes two LUNs of different kinds, a partition in block mode and an image file in fileio mode, to compare both backstores on the same initiator:

┌──────────────────────────┐ TCP/3260 ┌──────────────────────────┐
│ storage-srv │◄────────────────────────►│ storage-cli │
│ (iSCSI target) │ │ (iSCSI initiator) │
│ │ │ │
│ targetcli-fb │ │ open-iscsi │
│ /dev/vdb1 (5 GB block) │ ──── LUN 0 ────► │ /dev/sda → /mnt/iscsi │
│ 1 GB file (fileio) │ ──── LUN 1 ────► │ /dev/sdb → /mnt/file │
│ │ │ │
│ IP: 192.168.122.50 │ │ IP: 192.168.122.225 │
└──────────────────────────┘ └──────────────────────────┘

Configure the target (server)

The target is the server that exposes its disks via iSCSI. On Linux, you use LIO (Linux-IO Target), the iSCSI target framework built into the kernel, driven by the targetcli command.

Install targetcli

Terminal window
sudo apt update
sudo apt install targetcli-fb

The targetcli-fb package ("free branch") is the actively maintained version of the project. It provides the targetcli command to configure backstores, targets and ACLs through an interactive shell.

Enable the service so that the configuration persists after a reboot:

Terminal window
sudo systemctl enable rtslib-fb-targetctl

Prepare the storage

iSCSI can expose several types of storage as a backend (called backstores). The two most common:

TypeDescriptionPerformanceUse case
blockPartition, disk or LVM volumeExcellentDatabases, production
fileioImage file on the file systemGoodTests, prototyping

For the lab, create both types:

block backstore: partition the additional disk.

Terminal window
sudo parted /dev/vdb mklabel gpt
sudo parted /dev/vdb mkpart iscsi-lun1 ext4 0% 50%
sudo parted /dev/vdb mkpart iscsi-lun2 ext4 50% 100%

fileio backstore: create an image file.

Terminal window
sudo mkdir -p /srv/iscsi
sudo dd if=/dev/zero of=/srv/iscsi/lun-file.img bs=1M count=1024

Configure with targetcli

Start the interactive targetcli shell and create the whole structure:

Terminal window
sudo targetcli
  1. Create the backstores: declare the physical storage media.

    /> cd /backstores/block
    /backstores/block> create lun-data /dev/vdb1
    /backstores/block> cd /backstores/fileio
    /backstores/fileio> create lun-file /srv/iscsi/lun-file.img

    Each backstore gets a logical name (lun-data, lun-file) that identifies it in the configuration.

  2. Create the iSCSI target: define the identity of the storage server.

    /> cd /iscsi
    /iscsi> create iqn.2026-03.lab.storage:target01

    The IQN (iSCSI Qualified Name) follows the format iqn.YYYY-MM.reversed.domain:identifier. It identifies the target uniquely on the network. A TPG (Target Portal Group) is created automatically.

  3. Create an ACL for the initiator: allow the client to connect.

    /> cd /iscsi/iqn.2026-03.lab.storage:target01/tpg1/acls
    /iscsi/.../acls> create iqn.2026-03.lab.storage:client01

    The ACL controls which initiator can reach the target. The IQN must match exactly the name configured on the client.

  4. Map the LUNs: attach the backstores to the target.

    /> cd /iscsi/iqn.2026-03.lab.storage:target01/tpg1/luns
    /iscsi/.../luns> create /backstores/block/lun-data
    /iscsi/.../luns> create /backstores/fileio/lun-file

    Each LUN gets an automatic number (LUN 0, LUN 1...). LUNs are automatically mapped to the existing ACLs.

  5. Check and save:

    /> ls /
    /> saveconfig
    /> exit

Expected result of ls /:

o- / .............................................................. [...]
o- backstores ................................................... [...]
| o- block ........................................... [Storage Objects: 1]
| | o- lun-data ................ [/dev/vdb1 (5.0GiB) write-thru activated]
| o- fileio .......................................... [Storage Objects: 1]
| o- lun-file . [/srv/iscsi/lun-file.img (1.0GiB) write-back activated]
o- iscsi ................................................. [Targets: 1]
o- iqn.2026-03.lab.storage:target01 ........................ [TPGs: 1]
o- tpg1 ........................................ [gen-acls, no-auth]
o- acls ............................................... [ACLs: 1]
| o- iqn.2026-03.lab.storage:client01 ......... [Mapped LUNs: 2]
o- luns ............................................... [LUNs: 2]
| o- lun0 .................. [block/lun-data (/dev/vdb1) (default)]
| o- lun1 .. [fileio/lun-file (/srv/iscsi/lun-file.img) (default)]
o- portals ........................................ [Portals: 1]
o- 0.0.0.0:3260 .......................................... [OK]

Check: port 3260 is indeed listening.

Terminal window
sudo ss -tlnp | grep 3260
LISTEN 0 256 0.0.0.0:3260 0.0.0.0:*

The line carries no process, even with -p: the LIO target listens from the kernel, not from targetcli, which is only a configuration tool and exits once the session is closed.

Configure the initiator (client)

The initiator is the client that connects to the target to use the remote disks. On Linux, the open-iscsi package provides the necessary tools.

Install open-iscsi

Terminal window
sudo apt update
sudo apt install open-iscsi lsscsi

The lsscsi package is optional but very useful to list the detected SCSI devices.

Configure the initiator name

Each initiator has a unique IQN stored in /etc/iscsi/initiatorname.iscsi. This name must match exactly the ACL configured on the target:

Terminal window
echo "InitiatorName=iqn.2026-03.lab.storage:client01" | sudo tee /etc/iscsi/initiatorname.iscsi
sudo systemctl restart iscsid

Discover the target

Discovery queries the target to list the available resources:

Terminal window
sudo iscsiadm -m discovery -t sendtargets -p 192.168.122.50
192.168.122.50:3260,1 iqn.2026-03.lab.storage:target01

The target answers with its IQN and its portal (IP:port). This information is stored locally for future connections.

Connect (login)

Terminal window
sudo iscsiadm -m node \
-T iqn.2026-03.lab.storage:target01 \
-p 192.168.122.50 --login
Logging in to [iface: default, target: iqn.2026-03.lab.storage:target01, portal: 192.168.122.50,3260]
Login to [...] successful.

Check: list the active sessions.

Terminal window
sudo iscsiadm -m session -o show
tcp: [1] 192.168.122.50:3260,1 iqn.2026-03.lab.storage:target01 (non-flash)

Check the disks

After the login, the LUNs appear as classic SCSI disks:

Terminal window
lsscsi
[0:0:0:0] cd/dvd QEMU QEMU DVD-ROM 2.5+ /dev/sr0
[6:0:0:0] disk LIO-ORG lun-data 4.0 /dev/sda
[6:0:0:1] disk LIO-ORG lun-file 4.0 /dev/sdb

The two LUNs are visible: lun-data (5 GB, block) on /dev/sda and lun-file (1 GB, fileio) on /dev/sdb. The LIO-ORG vendor confirms that they come from the LIO target.

Terminal window
lsblk /dev/sda /dev/sdb
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sda 8:0 0 5G 0 disk
sdb 8:16 0 1G 0 disk

Format and mount the LUNs

iSCSI LUNs are raw disks. Format them and mount them like any local disk:

Terminal window
# Format as ext4
sudo mkfs.ext4 /dev/sda
sudo mkfs.ext4 /dev/sdb
# Create the mount points
sudo mkdir -p /mnt/iscsi-data /mnt/iscsi-file
# Mount
sudo mount /dev/sda /mnt/iscsi-data
sudo mount /dev/sdb /mnt/iscsi-file

Check: write data and verify.

Terminal window
echo "Données critiques sur iSCSI block" | sudo tee /mnt/iscsi-data/test.txt
cat /mnt/iscsi-data/test.txt
Données critiques sur iSCSI block

Performance benchmark

Terminal window
# Write (100 MB, direct I/O)
dd if=/dev/zero of=/mnt/iscsi-data/bench bs=1M count=100 oflag=direct
# Read
dd if=/mnt/iscsi-data/bench of=/dev/null bs=1M iflag=direct

On our lab (virtio network, same KVM host):

DirectionMeasured throughput
Write~866 MB/s
Read~1.7 GB/s

On this lab, iSCSI in block mode writes much faster than NFS, because the client handles the file system directly, without the overhead of a file protocol. Both measurements share the same limit: client and server on the same host, so a throughput that mostly reflects memory.

Persistent mount via /etc/fstab

For the LUNs to mount automatically at boot:

/etc/fstab
/dev/sda /mnt/iscsi-data ext4 defaults,_netdev 0 0
/dev/sdb /mnt/iscsi-file ext4 defaults,_netdev 0 0

The _netdev option is essential: it tells the system to wait for the network (and therefore the iSCSI session) to be up before mounting.

Automatic connection at boot

For the initiator to reconnect automatically to the target at boot:

Terminal window
sudo iscsiadm -m node \
-T iqn.2026-03.lab.storage:target01 \
-p 192.168.122.50 \
-o update -n node.startup -v automatic

Check that the parameter is saved:

Terminal window
sudo iscsiadm -m node \
-T iqn.2026-03.lab.storage:target01 \
-p 192.168.122.50 | grep node.startup
node.startup = automatic

Secure with CHAP

By default, any initiator knowing the IQN and the IP of the target can connect. The CHAP protocol (Challenge-Handshake Authentication Protocol) adds authentication by user name and password.

One-way CHAP (the most common)

The target checks the identity of the initiator. It is enough in most cases.

Target side (in targetcli):

Terminal window
sudo targetcli
/> cd /iscsi/iqn.2026-03.lab.storage:target01/tpg1
/iscsi/.../tpg1> set attribute authentication=1
/iscsi/.../tpg1> cd acls/iqn.2026-03.lab.storage:client01
/iscsi/.../client01> set auth userid=labuser
/iscsi/.../client01> set auth password=S3cur3P4ssw0rd
/> saveconfig
/> exit

Initiator side: log out, configure CHAP, then log in again.

Terminal window
# Log out
sudo iscsiadm -m node \
-T iqn.2026-03.lab.storage:target01 \
-p 192.168.122.50 --logout
# Configure CHAP
sudo iscsiadm -m node \
-T iqn.2026-03.lab.storage:target01 \
-p 192.168.122.50 \
-o update -n node.session.auth.authmethod -v CHAP
sudo iscsiadm -m node \
-T iqn.2026-03.lab.storage:target01 \
-p 192.168.122.50 \
-o update -n node.session.auth.username -v labuser
sudo iscsiadm -m node \
-T iqn.2026-03.lab.storage:target01 \
-p 192.168.122.50 \
-o update -n node.session.auth.password -v S3cur3P4ssw0rd
# Log in again with CHAP
sudo iscsiadm -m node \
-T iqn.2026-03.lab.storage:target01 \
-p 192.168.122.50 --login
Login to [...] successful.

Check: the session is active with authentication.

Terminal window
sudo iscsiadm -m session -o show
tcp: [2] 192.168.122.50:3260,1 iqn.2026-03.lab.storage:target01 (non-flash)

The disks are available again. Mount them again:

Terminal window
sudo mount /dev/sda /mnt/iscsi-data
sudo mount /dev/sdb /mnt/iscsi-file
cat /mnt/iscsi-data/test.txt
Données critiques sur iSCSI block

The data is intact after the logout/login.

Mutual (two-way) CHAP

For environments where the target must also prove its identity to the initiator (preventing spoofing), configure mutual CHAP:

Target side: add the reverse credentials.

/iscsi/.../client01> set auth mutual_userid=target-srv
/iscsi/.../client01> set auth mutual_password=T4rg3tS3cur3d

Initiator side:

Terminal window
sudo iscsiadm -m node \
-T iqn.2026-03.lab.storage:target01 \
-p 192.168.122.50 \
-o update -n node.session.auth.username_in -v target-srv
sudo iscsiadm -m node \
-T iqn.2026-03.lab.storage:target01 \
-p 192.168.122.50 \
-o update -n node.session.auth.password_in -v T4rg3tS3cur3d

Manage iSCSI sessions

List the active sessions

A session matches an open connection to a target. Listing them is the first gesture before any logout or any diagnosis:

Terminal window
sudo iscsiadm -m session -o show

Log out cleanly

Before logging out, unmount the file systems:

Terminal window
sudo umount /mnt/iscsi-data /mnt/iscsi-file
sudo iscsiadm -m node \
-T iqn.2026-03.lab.storage:target01 \
-p 192.168.122.50 --logout

Delete a recorded target

To forget a target completely (discovery + node):

Terminal window
sudo iscsiadm -m node \
-T iqn.2026-03.lab.storage:target01 \
-p 192.168.122.50 -o delete

See the configuration on the target side

On the server, look at the active configuration:

Terminal window
sudo targetcli ls /

The full configuration is saved in /etc/rtslib-fb-target/saveconfig.json. Back up this file for recovery after an incident.

Good practices in production

Dedicated network

In production, isolate iSCSI traffic on a dedicated network or VLAN:

  • Avoids congestion with application traffic
  • Reduces the attack surface (CHAP is not encryption)
  • Lets you configure jumbo MTU (9000) for performance

Multipath (high availability)

For critical servers, configure multipath-tools to use several network paths to the same target:

Terminal window
sudo apt install multipath-tools

Multipath provides:

  • Redundancy: if a path goes down, traffic fails over automatically
  • Performance: bandwidth aggregation over the active paths

Sizing

These values are starting points for production, to compare with your own measurements: an undersized storage network shows up first in database latency.

ParameterRecommendation
Network10 Gbps minimum for databases
MTU9000 (jumbo frames) if the network supports it
BackstoresBlock (partition/LVM) for production, fileio for tests
CHAPAlways enabled, even on an isolated network
Config backupCopy /etc/rtslib-fb-target/saveconfig.json regularly

Troubleshooting

SymptomLikely causeFix
Discovery returns nothingPort 3260 filteredsudo ufw allow 3260/tcp then ss -tlnp | grep 3260 on the target
Login refused without a clear messageInitiator IQN matches no ACLCheck that the IQN in /etc/iscsi/initiatorname.iscsi is identical to the ACL in targetcli
Login fails with CHAPWrong password, or outside the 12 to 16 character range some initiators requireCheck userid/password on the target AND on the initiator
Disks not visible after loginLUNs not mapped in the TPGIn targetcli: check ls /iscsi/.../tpg1/luns
/dev/sdX changes after rebootDynamic device namesUse UUID=... in /etc/fstab instead of /dev/sdX
Mount at boot failsiSCSI session not yet establishedAdd _netdev in fstab + node.startup = automatic
Read-only file system after reconnectionFile system flagged in errorsudo fsck /dev/sda then mount again
Slow performanceMTU 1500 on a dedicated networkSwitch to MTU 9000 (jumbo frames) on all interfaces
Target does not start at bootrtslib-fb-targetctl service disabledsudo systemctl enable rtslib-fb-targetctl

Key points

  • iSCSI carries disk commands (SCSI) over the TCP/IP network: the client sees a real block disk (/dev/sdX)
  • The target (server) exposes the disks via targetcli, the initiator (client) connects to it via open-iscsi
  • Backstores define the physical storage: block (partition, LVM) for production, fileio (file) for tests
  • Each target and initiator is identified by a unique IQN, the match between the ACLs and the initiatorname is mandatory
  • Enable CHAP systematically: it is the only authentication built into the protocol
  • The _netdev option in /etc/fstab is essential for iSCSI mounts at boot
  • In production, dedicate a network or VLAN to iSCSI traffic and use multipath for high availability

Knowledge check

Check that the essentials of this guide are acquired. The questions only cover what has just been explained here.

Knowledge check

Check what you have learned with this interactive quiz

6 questions
6 min
70% to pass

How it works

  • The timer starts when you click Start
  • Multiple choice, true/false and short answer questions
  • You can move between questions
  • Detailed results are shown at the end

Starts the quiz and the timer

Is this project useful to you?

The guides, courses, quizzes and labs stay free. If you use them regularly, you can contribute to their upkeep and development.

Become a supporting member (new tab) One-time support (new tab) Learn more

Follow the project on LinkedIn