dotlinux blog

How to Create and Setup LUNs using LVM in “iSCSI Target Server” on RHEL/CentOS/Fedora

iSCSI (Internet Small Computer System Interface) is a protocol that enables block-level storage sharing over IP networks. It turns a server into an iSCSI target (storage provider) and allows clients (initiators) to access shared storage as if it were a local disk.

When paired with LVM (Logical Volume Manager), iSCSI becomes a flexible, enterprise-grade solution. LVM abstracts physical storage into logical volumes (LVs), enabling:

  • Dynamic resizing of LUNs without downtime
  • Storage pooling (combining multiple disks into a single volume group)
  • Snapshots for backups
  • Isolation of storage for different initiators

In this guide, we’ll walk through end-to-end setup of an iSCSI target server on RHEL/CentOS/Fedora, using LVM to create scalable LUNs. You’ll learn how to:

  • Install and configure LVM
  • Set up an iSCSI target with targetcli
  • Map LVM logical volumes (LVs) as iSCSI LUNs
  • Secure the target with CHAP authentication
  • Test the LUN from an initiator
  • Troubleshoot common issues

By the end, you’ll have a production-ready iSCSI target that leverages LVM’s flexibility for enterprise storage needs.

2026-05

Prerequisites#

Before you start, ensure you have:

  1. RHEL/CentOS 7/8/9 or Fedora 38+ (tested on RHEL 9.3)
  2. Root/sudo access to the target server
  3. At least one additional storage device (physical or virtual) for LVM (do NOT use your root disk!)
  4. Network connectivity between the target and initiator (same subnet recommended)
  5. Basic Linux command-line knowledge

Table of Contents#

  1. Introduction
  2. Prerequisites
  3. Step 1: Install Required Packages
  4. Step 2: Set Up LVM for iSCSI LUNs
  5. Step 3: Configure iSCSI Target with Targetcli
  6. Step 4: Configure Firewall and SELinux
  7. Step 5: Test iSCSI LUN from an Initiator
  8. Step 6: Troubleshooting Common Issues
  9. Step 7: Resizing iSCSI LUNs (Optional)
  10. Conclusion
  11. References

Step 1: Install Required Packages#

First, update your system and install packages for LVM and iSCSI target management:

sudo dnf update -y
sudo dnf install -y lvm2 targetcli
  • lvm2: Provides LVM utilities (e.g., pvcreate, vgcreate, lvcreate).
  • targetcli: A command-line tool for configuring iSCSI targets on RHEL/CentOS/Fedora.

Verify the installation:

rpm -q lvm2 targetcli

Expected Output:

lvm2-2.03.11-5.el9.x86_64
targetcli-2.1.53-1.el9.noarch

Step 2: Set Up LVM for iSCSI LUNs#

LVM uses three layers to manage storage:

  1. Physical Volumes (PVs): Raw storage devices (e.g., /dev/sdb).
  2. Volume Groups (VGs): Pools of PVs that act as a single storage resource.
  3. Logical Volumes (LVs): "Partitions" of VGs that become iSCSI LUNs.

2.1 Identify Storage Devices#

First, identify the storage device you’ll use for LVM. Do NOT use your root disk (e.g., /dev/sda)—use a separate physical or virtual disk.

List available disks with:

lsblk -d -o NAME,SIZE,TYPE

Example Output:

NAME   SIZE TYPE
sda    20G  disk  # Root disk (DO NOT USE!)
sdb    50G  disk  # New storage device for LVM

In this example, we’ll use /dev/sdb.

2.2 Create Physical Volumes (PVs)#

Initialize the disk as a Physical Volume (PV) for LVM:

sudo pvcreate /dev/sdb

Expected Output:

  Physical volume "/dev/sdb" successfully created.

Verify the PV:

sudo pvs

Output:

  PV         VG     Fmt  Attr PSize   PFree  
  /dev/sdb          lvm2 ---   50.00g  50.00g

2.3 Create Volume Groups (VGs)#

Combine PVs into a Volume Group (VG). A VG acts as a pool of storage for LVs.

Create a VG named vg_iscsi using /dev/sdb:

sudo vgcreate vg_iscsi /dev/sdb

Expected Output:

  Volume group "vg_iscsi" successfully created

Verify the VG:

sudo vgs

Output:

  VG       #PV #LV #SN Attr   VSize   VFree  
  vg_iscsi   1   0   0 wz--n-  50.00g  50.00g

2.4 Create Logical Volumes (LVs)#

Create a Logical Volume (LV) from the VG—this will become your iSCSI LUN.

Create an LV named lv_iscsi1 with 20GB of storage:

sudo lvcreate -L 20G -n lv_iscsi1 vg_iscsi

Or use 100% of the VG’s free space (maximize LUN size):

sudo lvcreate -l +100%FREE -n lv_iscsi1 vg_iscsi

Expected Output:

  Logical volume "lv_iscsi1" created.

Verify the LV:

sudo lvs

Output:

  LV         VG       Attr       LSize  Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  lv_iscsi1  vg_iscsi -wi-a----- 20.00g                                                    

Step 3: Configure iSCSI Target with Targetcli#

targetcli is the official tool for managing iSCSI targets on RHEL/CentOS/Fedora. It uses a tree-based hierarchy to configure:

  • Backstores: Storage sources (e.g., LVM LVs).
  • Targets: IQN (unique identifier) for the iSCSI service.
  • Portals: IP/port the target listens on.
  • LUNs: Mapping of backstores to targets.
  • ACLs: Access control lists (for CHAP authentication).

3.1 Launch Targetcli#

Start the targetcli shell:

sudo targetcli

You’ll see a prompt like:

targetcli shell version 2.1.53
Copyright 2011-2013 by Datera, Inc and others.
For help on commands, type 'help'.

/>

3.2 Create a Block Backstore from LVM LV#

iSCSI targets use backstores to map physical storage to LUNs. For LVM, we’ll create a block backstore (since LVs are block devices).

In the targetcli shell:

  1. Navigate to the block backstores directory:
    cd /backstores/block
  2. Create a backstore using your LVM LV:
    create name=iscsi_lun1 dev=/dev/vg_iscsi/lv_iscsi1
  • name=iscsi_lun1: A human-readable name for the backstore.
  • dev=/dev/vg_iscsi/lv_iscsi1: Path to the LVM LV you created earlier.

Verify the backstore:

ls /backstores/block

Output:

iscsi_lun1  (source: /dev/vg_iscsi/lv_iscsi1)

3.3 Create an iSCSI Target IQN#

An IQN (iSCSI Qualified Name) uniquely identifies the iSCSI target. The format is: iqn.yyyy-mm.<reverse-domain>:<identifier>

  • iqn: Mandatory prefix for iSCSI names.
  • yyyy-mm: Year/month the domain was registered.
  • reverse-domain: Your domain name in reverse (e.g., com.example for example.com).
  • identifier: A unique name for the target (e.g., iscsi-target1).

Create the target IQN:

cd /targets
create iqn.2024-05.com.example:iscsi-target1

Replace 2024-05.com.example:iscsi-target1 with your own IQN.

Verify the target:

ls /targets

Output:

iqn.2024-05.com.example:iscsi-target1

3.4 Configure iSCSI Portal#

A portal defines the IP address and port the target listens on. By default, iSCSI uses port 3260.

Create a portal to listen on all interfaces (0.0.0.0):

cd /targets/iqn.2024-05.com.example:iscsi-target1/portals
create 0.0.0.0:3260

Verify the portal:

ls /targets/iqn.2024-05.com.example:iscsi-target1/portals

Output:

0.0.0.0:3260

3.5 Associate LUN with Target#

Now, map the block backstore (your LVM LV) to the target as a LUN (Logical Unit Number). LUNs are numbered sequentially (starting from 0).

In the targetcli shell:

  1. Navigate to the target’s LUNs directory:
    cd /targets/iqn.2024-05.com.example:iscsi-target1/luns
  2. Create a LUN from the backstore:
    create /backstores/block/iscsi_lun1

Verify the LUN:

ls /targets/iqn.2024-05.com.example:iscsi-target1/luns

Output:

0  (backstore: iscsi_lun1)

3.6 Optional: Set Up CHAP Authentication#

CHAP (Challenge-Handshake Authentication Protocol) adds security by requiring initiators to authenticate before accessing the target.

Step 1: Create an ACL for the Initiator#

First, you’ll need the initiator’s IQN (we’ll configure this in Step 5.2). For now, use a placeholder like iqn.2024-05.com.example:iscsi-initiator1.

In the targetcli shell:

cd /targets/iqn.2024-05.com.example:iscsi-target1/acls
create iqn.2024-05.com.example:iscsi-initiator1

Step 2: Set CHAP Credentials#

Configure CHAP credentials for the initiator:

cd iqn.2024-05.com.example:iscsi-initiator1
set auth userid=initiator_user password=StrongPass123!
  • userid: Username the initiator will use.
  • password: A strong password (minimum 12 characters, mix of letters/numbers/symbols).

Step 3: Mutual CHAP (Optional)#

For mutual authentication (target authenticates to the initiator), add:

set auth mutual_userid=target_user mutual_password=AnotherStrongPass!

Verify the ACL and CHAP settings:

ls /targets/iqn.2024-05.com.example:iscsi-target1/acls

Output:

iqn.2024-05.com.example:iscsi-initiator1  (userid=initiator_user, password=StrongPass123!)

3.7 Save and Persist Configuration#

By default, targetcli does not save changes across reboots. Use the saveconfig command to write your configuration to /etc/target/saveconfig.json:

saveconfig

Enable and start the target service to load the configuration on boot:

systemctl enable --now target

Verify the service status:

systemctl status target

Expected Output:

● target.service - Kernel Target Manager
     Loaded: loaded (/usr/lib/systemd/system/target.service; enabled; preset: disabled)
     Active: active (running) since Tue 2024-05-21 14:30:00 UTC; 1min ago

Step 4: Configure Firewall and SELinux#

Firewall Setup#

The iSCSI target uses TCP port 3260. Allow this port through the firewall (permanent):

sudo firewall-cmd --add-service=iscsi-target --permanent
sudo firewall-cmd --reload

Verify the rule:

sudo firewall-cmd --list-services --permanent

Output:

cockpit dhcpv6-client iscsi-target ssh

SELinux Configuration#

SELinux is enabled by default on RHEL/CentOS. For most setups, the default policies work with iSCSI targets. If you encounter issues (e.g., initiators can’t access LUNs), check the audit log:

sudo ausearch -m AVC -ts recent

Fix SELinux Denials (If Needed)#

If SELinux blocks access to the LVM LV, add the correct context:

sudo semanage fcontext -a -t iscsi_target_var_lib_t "/dev/vg_iscsi/lv_iscsi1"
sudo restorecon -v /dev/vg_iscsi/lv_iscsi1

For temporary testing, set SELinux to permissive mode (not recommended for production):

sudo setenforce 0

Step 5: Test iSCSI LUN from an Initiator#

Now, we’ll configure an initiator (a RHEL/CentOS/Fedora client) to connect to the target and use the LUN.

5.1 Install Initiator Packages#

On the initiator, install the iscsi-initiator-utils package:

sudo dnf install -y iscsi-initiator-utils

5.2 Configure Initiator IQN#

The initiator needs a unique IQN. Edit /etc/iscsi/initiatorname.iscsi:

sudo nano /etc/iscsi/initiatorname.iscsi

Replace the existing line with your IQN (e.g., iqn.2024-05.com.example:iscsi-initiator1):

InitiatorName=iqn.2024-05.com.example:iscsi-initiator1

Save the file and restart the iscsid service:

sudo systemctl restart iscsid
sudo systemctl enable iscsid

5.3 Discover and Log In to Target#

Step 1: Discover the Target#

Use the target’s IP address (e.g., 192.168.1.100) to discover the iSCSI target:

sudo iscsiadm -m discovery -t st -p 192.168.1.100:3260
  • -m discovery: Enter discovery mode.
  • -t st: Use SendTarget discovery (standard for iSCSI).
  • -p 192.168.1.100:3260: Target IP and port.

Expected Output:

192.168.1.100:3260,1 iqn.2024-05.com.example:iscsi-target1

Step 2: Log In to the Target#

Log in to the target using its IQN:

sudo iscsiadm -m node -T iqn.2024-05.com.example:iscsi-target1 -p 192.168.1.100:3260 -l
  • -m node: Manage iSCSI nodes (targets).
  • -T: Specify the target IQN.
  • -l: Login to the target.

Step 3: Configure CHAP Credentials (If Enabled)#

If you set up CHAP in Step 3.6, edit /etc/iscsi/iscsid.conf to add credentials:

sudo nano /etc/iscsi/iscsid.conf

Add:

# CHAP credentials for initiator -> target
node.session.auth.authmethod = CHAP
node.session.auth.username = initiator_user
node.session.auth.password = StrongPass123!
 
# Mutual CHAP (target -> initiator, optional)
node.session.auth.username_in = target_user
node.session.auth.password_in = AnotherStrongPass!

Save and restart iscsid:

sudo systemctl restart iscsid

5.4 Verify LUN Detection#

List active iSCSI sessions:

sudo iscsiadm -m session

Output:

tcp: [1] 192.168.1.100:3260,1 iqn.2024-05.com.example:iscsi-target1

Verify the LUN is detected as a block device:

lsblk -d -o NAME,SIZE,TYPE

Example Output:

NAME   SIZE TYPE
sda    20G  disk  # Root disk
sdb    20G  disk  # iSCSI LUN from target!

5.5 Format and Mount the LUN#

Step 1: Format the LUN#

Format the LUN with XFS (recommended for RHEL/CentOS):

sudo mkfs.xfs /dev/sdb

Or use ext4:

sudo mkfs.ext4 /dev/sdb

Step 2: Create a Mount Point#

Create a directory to mount the LUN:

sudo mkdir -p /mnt/iscsi

Step 3: Mount the LUN#

Mount the LUN to /mnt/iscsi:

sudo mount /dev/sdb /mnt/iscsi

Step 4: Test Write Access#

Create a test file to verify the LUN works:

sudo touch /mnt/iscsi/test.txt
sudo echo "Hello from iSCSI!" > /mnt/iscsi/test.txt
cat /mnt/iscsi/test.txt

Expected Output:

Hello from iSCSI!

Step 5: Mount on Boot (Optional)#

To mount the LUN automatically on boot, add an entry to /etc/fstab:

sudo nano /etc/fstab

Add:

/dev/sdb /mnt/iscsi xfs defaults,_netdev 0 0
  • _netdev: Ensures the mount waits for the network to be active (critical for iSCSI).

Test the fstab entry:

sudo umount /mnt/iscsi
sudo mount /mnt/iscsi

Step 6: Troubleshooting Common Issues#

6.1 Firewall Blocking iSCSI Traffic#

Symptom: Initiator can’t discover the target.
Fix: Re-add the iSCSI target firewall rule:

sudo firewall-cmd --add-service=iscsi-target --permanent
sudo firewall-cmd --reload

6.2 SELinux Denials#

Symptom: Initiator can’t mount the LUN, error: Permission denied.
Fix: Restore the SELinux context for the LV:

sudo restorecon -v /dev/vg_iscsi/lv_iscsi1

6.3 Target Not Discovered#

Symptom: iscsiadm -m discovery returns no results.
Check:

  1. Is the target service running?
    sudo systemctl status target
  2. Is the target IP correct? Ping the target from the initiator:
    ping 192.168.1.100
  3. Is the portal configured correctly?
    sudo targetcli ls /targets/iqn.2024-05.com.example:iscsi-target1/portals

6.4 LUN Not Visible After Login#

Symptom: lsblk doesn’t show the LUN.
Fix: Rescan the iSCSI bus:

sudo iscsiadm -m node -R

6.5 CHAP Authentication Failures#

Symptom: Initiator can’t log in, error: authentication failed.
Check:

  1. Did you set the correct credentials in /etc/iscsi/iscsid.conf?
  2. Are the credentials the same on the target? Verify with:
    sudo targetcli ls /targets/iqn.2024-05.com.example:iscsi-target1/acls

Step 7: Resizing iSCSI LUNs (Optional)#

One of the biggest benefits of using LVM with iSCSI is dynamic resizing. Here’s how to extend a LUN:

On the Target Server#

  1. Extend the LVM LV (add 10GB):
    sudo lvresize -L +10G /dev/vg_iscsi/lv_iscsi1
    Or use all free space in the VG:
    sudo lvresize -l +100%FREE /dev/vg_iscsi/lv_iscsi1
  2. Verify the new size:
    sudo lvs /dev/vg_iscsi/lv_iscsi1

On the Initiator#

  1. Rescan the iSCSI bus:
    sudo iscsiadm -m node -R
  2. Resize the filesystem:
    • For XFS:
      sudo xfs_growfs /mnt/iscsi
    • For ext4:
      sudo resize2fs /dev/sdb
  3. Verify the new size:
    df -h /mnt/iscsi

Conclusion#

You’ve successfully set up an iSCSI target server using LVM on RHEL/CentOS/Fedora! By combining iSCSI with LVM, you’ve created a scalable, flexible storage solution that:

  • Lets you dynamically resize LUNs
  • Aggregates multiple disks into a single storage pool
  • Supports snapshots for backups
  • Secures access with CHAP authentication

This setup is ideal for:

  • Virtualization (e.g., VM storage for KVM/Xen)
  • Network-attached storage (NAS)
  • Backup targets
  • Enterprise applications requiring block storage

References#

  1. RHEL iSCSI Target Documentation: Configuring iSCSI Targets
  2. LVM Administration Guide: Logical Volume Manager
  3. Targetcli Man Page: targetcli(8)
  4. iSCSI Initiator Documentation: Configuring iSCSI Initiators
  5. FirewallD Documentation: firewall-cmd(1)
  6. SELinux Documentation: SELinux User’s and Administrator’s Guide

Let me know if you have any questions or need help troubleshooting!