Deployment guide

iSCSI target LIO

Overview

This guide shows how to deploy and configure an iSCSI target (Linux LIO) on Ubuntu 24.04 on Azure, using the SecureAnyCloud Azure Marketplace image. iSCSI exports raw block devices (LUNs) over ordinary TCP/IP. Any standards-compliant initiator (Linux, Windows, VMware or a hypervisor) can log in and use a LUN exactly as if it were a locally attached disk, which turns a single VM into a software-defined SAN.

The image is built on the Linux kernel LIO subsystem, the in-kernel SCSI target engine (target_core_mod), and is administered with targetcli from the targetcli-fb toolkit. The demo target is a 1 GiB fileio backstore exported as a single LUN behind the IQN iqn.2025-01.co.uk.sac:iscsi-demo, on a portal listening on TCP 3260. Unattended security upgrades keep the base OS patched.

Secure by design: no default credentials, and no target until first boot. A block storage target that anyone can log in to is a data breach waiting to happen. For that reason, the image never ships a fixed or shared credential and exports no target in the captured image.

On the first boot of every VM, the demo backstore, target, LUN and portal are built, and one-way CHAP authentication is enabled on the portal group. A fresh per-instance CHAP username and 16-character secret are generated and written to /root/iscsi-target-credentials.txt (mode 0600, root only). An initiator that presents the wrong secret is refused, and only the correct per-VM secret establishes a session.

Persistent across reboots. The kernel LIO configuration is saved to /etc/rtslib-fb-target/saveconfig.json and restored by rtslib-fb-targetctl.service on every boot, so your target, LUN and access control survive reboots.

What you get:

  • The Linux kernel LIO iSCSI target, administered with targetcli (targetcli-fb, python3-rtslib-fb)
  • A 1 GiB fileio backstore exported as a LUN behind iqn.2025-01.co.uk.sac:iscsi-demo, on a portal on TCP 3260
  • Mandatory one-way CHAP authentication on the target portal group, so an initiator with the wrong secret is refused
  • A per-instance CHAP username and secret generated on first boot and documented in /root/iscsi-target-credentials.txt (0600, root only)
  • Persistent configuration (saveconfig.json restored by rtslib-fb-targetctl.service) and the open-iscsi initiator tools for local verification

Prerequisites

  • An active Azure subscription, an SSH public key, and a virtual network and subnet in the target region
  • A subscription to the iSCSI Target listing on Azure Marketplace
  • Network security group rules that allow TCP 22 (administration) and, for the initiator hosts that will use the storage, TCP 3260 (iSCSI) from your client networks

Recommended virtual machine size: Standard_B2s (2 vCPU, 4 GB RAM) for a demo or light target. For production SANs with larger LUNs and many initiators, use Standard_D2s_v5 or larger and attach dedicated data disks for the backstores.

1

Deploy from the Azure Portal

In the Marketplace, search for iSCSI Target, select the SecureAnyCloud publisher and select Create. Configure the network security group to allow TCP 3260 from your initiator hosts and TCP 22 for administration.

2

Deploy from the Azure CLI

Create the resource group, accept the Marketplace terms once per subscription, create the VM and open port 3260:

RG="iscsi-prod"; LOCATION="eastus"; VM_NAME="iscsi1" IMAGE_URN="sac1647283583153:iscsi-target-lio-ubuntu-24-04:default:latest" SSH_KEY="$(cat ~/.ssh/id_rsa.pub)" az group create --name "$RG" --location "$LOCATION"
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:iscsi-target-lio-ubuntu-24-04:default:latest
az vm create \
  --resource-group "$RG" --name "$VM_NAME" \
  --image "$IMAGE_URN" \
  --size Standard_B2s \
  --admin-username azureuser \
  --ssh-key-values "$SSH_KEY" \
  --public-ip-sku Standard
az vm open-port --resource-group "$RG" --name "$VM_NAME" --port 3260 --priority 1001

When the VM is running, connect over SSH as azureuser.

3

Retrieve your per-VM CHAP credentials

Every VM generates its own CHAP username and secret on first boot. They are written to a root-only file, together with the target IQN and portal:

sudo grep -E '^CHAP_USERNAME=|^TARGET_IQN=|^PORTAL=' /root/iscsi-target-credentials.txt

The output looks like this. The full file, including the CHAP secret, is readable only by root:

CHAP_USERNAME=chap_1d87eb66 TARGET_IQN=iqn.2025-01.co.uk.sac:iscsi-demo PORTAL=10.0.0.27:3260

The PORTAL value is the VM's primary IP. Initiators inside the same virtual network connect on that address. Internet clients connect on the VM's public IP on TCP 3260, after you open that port in the network security group.

4

Inspect the iSCSI target

The demo target, LUN, portal and backstore are already live. View the object tree with targetcli, and confirm that the portal is listening on TCP 3260:

sudo targetcli ls /iscsi
sudo ss -tlnp | grep ':3260 '

The output looks like this:

o- iscsi ...................................................... [Targets: 1] o- iqn.2025-01.co.uk.sac:iscsi-demo ....................... [TPGs: 1] o- tpg1 ............................... [gen-acls, tpg-auth, 1-way auth] o- acls .................................................... [ACLs: 0] o- luns .................................................... [LUNs: 1] | o- lun0 ....... [fileio/demo (/var/lib/iscsi-demo/demo.img) (default_tg_pt_gp)] o- portals .............................................. [Portals: 1] o- 0.0.0.0:3260 ............................................... [OK] LISTEN 0.0.0.0:3260

The tpg-auth, 1-way auth flags confirm that CHAP is enforced at the portal group level.

5

Verify a real iSCSI session locally

You can prove the target end to end from the VM itself, using the bundled open-iscsi initiator over the loopback address. A wrong CHAP secret is refused. The correct per-VM secret establishes a real session, and a new block device appears:

sudo systemctl start iscsid open-iscsi IQN=iqn.2025-01.co.uk.sac:iscsi-demo
sudo iscsiadm -m discovery -t sendtargets -p 127.0.0.1:3260
sudo iscsiadm -m node -T "$IQN" -p 127.0.0.1:3260 --op update -n node.session.auth.authmethod -v CHAP
sudo iscsiadm -m node -T "$IQN" -p 127.0.0.1:3260 --op update -n node.session.auth.username -v <CHAP_USERNAME>
sudo iscsiadm -m node -T "$IQN" -p 127.0.0.1:3260 --op update -n node.session.auth.password -v <CHAP_PASSWORD>
sudo iscsiadm -m node -T "$IQN" -p 127.0.0.1:3260 --login sudo iscsiadm -m session ls -l /dev/disk/by-path/ | grep iscsi
sudo iscsiadm -m node -T "$IQN" -p 127.0.0.1:3260 --logout

The output shows a live session and a new /dev/sd* device backed by the LUN:

127.0.0.1:3260,1 iqn.2025-01.co.uk.sac:iscsi-demo Login to [iface: default, target: iqn.2025-01.co.uk.sac:iscsi-demo, portal: 127.0.0.1,3260] successful. tcp: [1] 127.0.0.1:3260,1 iqn.2025-01.co.uk.sac:iscsi-demo (non-flash) ip-127.0.0.1:3260-iscsi-iqn.2025-01.co.uk.sac:iscsi-demo-lun-0 -> ../../sdc Logout of [iface: default, target: iqn.2025-01.co.uk.sac:iscsi-demo, portal: 127.0.0.1,3260] successful.
6

Connect from a remote initiator

On a remote Linux host with open-iscsi installed, point the same commands at the target VM's IP. Use the private IP inside the virtual network, or the public IP with TCP 3260 open in the network security group. Substitute the CHAP username and secret from Step 3:

sudo iscsiadm -m discovery -t sendtargets -p <TARGET_IP>:3260
sudo iscsiadm -m node -T iqn.2025-01.co.uk.sac:iscsi-demo -p <TARGET_IP>:3260 \
  --op update -n node.session.auth.authmethod -v CHAP
sudo iscsiadm -m node -T iqn.2025-01.co.uk.sac:iscsi-demo -p <TARGET_IP>:3260 \
  --op update -n node.session.auth.username -v <your-chap-username>
sudo iscsiadm -m node -T iqn.2025-01.co.uk.sac:iscsi-demo -p <TARGET_IP>:3260 \
  --op update -n node.session.auth.password -v <your-chap-secret>
sudo iscsiadm -m node -T iqn.2025-01.co.uk.sac:iscsi-demo -p <TARGET_IP>:3260 --login

On Windows, use the built-in iSCSI Initiator control panel. Add the target VM's IP under Discovery. Then, under Targets, connect with Advanced, then CHAP log on, using the username and secret from Step 3.

7

Review the CHAP security model

The credentials file is 0600 root:root. The CHAP secret is unique to this VM, generated on first boot and never shipped in the image:

sudo stat -c 'file: %n perms: %a owner: %U:%G' /root/iscsi-target-credentials.txt
sudo grep -E '^CHAP_USERNAME=' /root/iscsi-target-credentials.txt

The output looks like this. The secret itself stays root only:

file: /root/iscsi-target-credentials.txt perms: 600 owner: root:root CHAP_USERNAME=chap_1d87eb66

The captured image exports no target at all until first boot, so there is no window in which a default CHAP secret is live. Each VM builds its own target with its own secret.

8

Persist and customize your target

The configuration is persisted to /etc/rtslib-fb-target/saveconfig.json and restored on every boot by rtslib-fb-targetctl.service:

sudo systemctl is-enabled rtslib-fb-targetctl.service
sudo python3 -c "import json;d=json.load(open('/etc/rtslib-fb-target/saveconfig.json'));print('targets:',len(d['targets']),'storage objects:',len(d['storage_objects']))"

The output looks like this:

enabled targets: 1 storage objects: 1

To add your own LUN, use targetcli and then run sudo targetctl save to persist the change. For example, add a larger fileio backstore or a block-backed LUN on a dedicated Azure data disk. Run these commands on the target VM; they are illustrative:

# a larger file backed LUN
sudo targetcli /backstores/fileio create name=data1 file_or_dev=/var/lib/iscsi-demo/data1.img size=50G
sudo targetcli /iscsi/iqn.2025-01.co.uk.sac:iscsi-demo/tpg1/luns create /backstores/fileio/data1
# or a block backed LUN on an attached data disk (/dev/sdX)
sudo targetcli /backstores/block create name=disk1 dev=/dev/disk/azure/scsi1/lun0
sudo targetcli /iscsi/iqn.2025-01.co.uk.sac:iscsi-demo/tpg1/luns create /backstores/block/disk1
sudo targetctl save

Manage the service

sudo systemctl status rtslib-fb-targetctl.service --no-pager sudo targetcli ls /iscsi
  • Reload the persisted config after manual edits: sudo targetctl restore
  • Persist live changes: sudo targetctl save
  • The LIO target runs in the kernel, so there is no user-space daemon to restart.

Troubleshooting

  • Initiator cannot discover the target: confirm that TCP 3260 is open in the network security group from the client, and that sudo ss -tlnp | grep ':3260 ' shows a LISTEN socket on the VM.
  • Login refused: the CHAP username or secret is wrong. Read them again from /root/iscsi-target-credentials.txt (Step 3). CHAP is mandatory, so anonymous logins are always refused.
  • No new block device after login: run sudo iscsiadm -m session to confirm that the session is up, then check ls -l /dev/disk/by-path/ | grep iscsi.

Support

Every SecureAnyCloud deployment is backed by 24/7 support. For help, email sales@secureanycloud.com or visit secureanycloud.com.

Deploy on Azure

Launch iSCSI Target (Linux LIO) on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.

View this image

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure