Coding

Diskless Linux boot using ZFS, iSCSI and PXE

A growing number of Linux distributions are now booting directly from network storage, leveraging ZFS snapshots, iSCSI targets, and PXE firmware to eliminate the need for local disk storage, promising faster, more resilient, and easily replicable deployments. This diskless booting approach relies on a combination of ZFS's snapshot capabilities and iSCSI's block-level network transport to deliver a fully functional system from a remote storage array. Initial implementations focus on server and cloud environments.

A growing number of Linux deployments are moving away from local disk storage, booting directly from network-attached storage using ZFS snapshots, iSCSI targets, and PXE firmware. This approach promises faster provisioning, easier replication, and greater resilience — but it comes with tradeoffs in performance and complexity.

Overview

Diskless booting relies on three components: a ZFS pool on a remote server to provide snapshots and flexible storage, an iSCSI target to expose that storage as a block device over the network, and PXE firmware on the client to load the bootloader and operating system from the network. The result is a fully functional Linux system that has no local disk — the OS, applications, and data all live on the remote storage array.

What you need

  • A server running Debian 13 (or Proxmox) that will act as the netboot, TFTP, iSCSI target, and ZFS host.
  • A DHCP server that supports DNSMasq (e.g., an Asus router with Merlin firmware).
  • A client machine with PXE-capable firmware (UEFI or BIOS).
  • A ZFS pool on the server with a ZVOL of at least 32 GB for the Debian installation.

Step-by-step setup

1. Install and configure Netboot.xyz

On the server, install the required packages:

apt install apache2 git ansible tftpd-hpa targetcli-fb

Clone the Netboot.xyz repository and customize the configuration:

cd /opt
git clone https://github.com/netbootxyz/netboot.xyz.git
cd netboot.xyz

Edit /opt/netboot.xyz/user_overrides.yml to set site_name and boot_domain to the server's IP address (e.g., 192.168.50.167).

Edit /opt/netboot.xyz/roles/netbootxyz/templates/menu/boot.cfg.j2 — find the :end section and change it to:

:end
chain local-vars.ipxe || exit

Edit /opt/netboot.xyz/roles/netbootxyz/templates/local-vars.ipxe.j2 and set:

#!ipxe
set custom_url http://192.168.50.167

Run the Ansible playbook to install Netboot.xyz to /var/www/html:

ansible-playbook -i inventory site.yml

2. Create a custom iPXE boot script

Create /var/www/html/debian13-iscsi.ipxe with the following content, adjusting IP addresses and IQNs to match your setup:

#!ipxe
set iscsi-server 192.168.50.167
set iscsi-target iqn.2026-05.xyz.716697.pve-vt:tank-debian-disk-12700k
set initiator-iqn iqn.2026-05.xyz.716697.pve-vt:12700k
set username myuser
set password mypassword
set reverse-username targetuser
set reverse-password targetpassword

sanboot iscsi:${iscsi-server}::::${iscsi-target} || goto installer

:installer
imgfree
kernel http://${iscsi-server}/assets/debian13/linux
initrd http://${iscsi-server}/assets/debian13/initrd.gz
imgargs linux root=/dev/ram0 initrd=initrd.gz vga=normal
boot

Create /var/www/html/custom.ipxe to add a menu entry:

#!ipxe
menu Local Custom Menu
item --gap --
item debian13-iscsi Debian 13 iSCSI Boot (192.168.50.167)
item --gap --
item back Back to main menu
choose menu || goto back
goto ${menu}

:debian13-iscsi
chain http://192.168.50.167/debian13-iscsi.ipxe || goto back

:back
chain http://192.168.50.167/menu.ipxe

Download the Debian installer files:

mkdir -p /var/www/html/assets/debian13
cd /var/www/html/assets/debian13
wget http://ftp.debian.org/debian/dists/trixie/main/installer-amd64/current/images/netboot/debian-installer/amd64/initrd.gz
wget http://ftp.debian.org/debian/dists/trixie/main/installer-amd64/current/images/netboot/debian-installer/amd64/linux

3. Configure TFTP

Edit /etc/default/tftpd-hpa:

TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/srv/tftp"
TFTP_ADDRESS=":69"
TFTP_OPTIONS="--secure"

Copy the Netboot.xyz binaries:

mkdir -p /srv/tftp/ipxe
cp /var/www/html/ipxe/netboot.xyz-undionly.kpxe /srv/tftp/ipxe/
cp /var/www/html/ipxe/netboot.xyz-snp.efi /srv/tftp/ipxe/
cp /var/www/html/ipxe/netboot.xyz.efi /srv/tftp/ipxe/
chown -R tftp:tftp /srv/tftp/ipxe
service tftpd-hpa restart

4. Configure DNSMasq on the DHCP server

On your router (or DHCP server), add the following to the DNSMasq configuration (e.g., /jffs/configs/dnsmasq.conf.add on Asus Merlin):

# BIOS Clients
dhcp-boot=tag:!ipxe,ipxe/netboot.xyz-undionly.kpxe,,192.168.50.167

# UEFI x86-64 clients
dhcp-match=set:efi-x86_64,option:client-arch,7
dhcp-boot=tag:efi-x86_64,ipxe/netboot.xyz-snp.efi,,192.168.50.167

# Tag iPXE clients (option 175 present)
dhcp-match=set:ipxe,175

# All other iPXE clients get the netboot.xyz menu
dhcp-boot=tag:ipxe,http://192.168.50.167/menu.ipxe

Restart DNSMasq.

5. Create a ZFS ZVOL

zpool create tank /dev/disk/by-id/${DISK_ID}
zfs create -V 32G tank/debian-disk-12700k

6. Configure iSCSI target

Use targetcli to create the iSCSI target and backstore:

cd /backstores/block
create debian-disk-12700k /dev/zvol/tank/debian-disk-12700k
cd /iscsi
create iqn.2026-05.xyz.716697.pve-vt:tank-debian-disk-12700k
cd iqn.2026-05.xyz.716697.pve-vt:tank-debian-disk-12700k/tpg1
set attribute demo_mode_write_protect=1
set attribute generate_node_acls=0
cd acls
create iqn.2026-05.xyz.716697.pve-vt:12700k
cd iqn.2026-05.xyz.716697.pve-vt:12700k
set attribute authentication=1
set auth userid=myuser
set auth password=mypassword
set auth mutual_userid=targetuser
set auth mutual_password=targetpassword
cd ../../luns
create /backstores/block/debian-disk-12700k
cd /
saveconfig

7. Install Debian via the network

Boot the client machine from the network. Select the custom menu entry. The installer will fail to find a local disk — select "Configure iSCSI volumes." Switch to TTY 2 (Super+F2), edit /etc/iscsi/initiatorname.iscsi to match the initiator IQN you configured, kill the iscsid processes, and restart iscsid. Switch back to TTY 1 (Super+F1), log into the iSCSI target with the credentials you set, and proceed with the standard Debian installation. The iSCSI disk will appear as a block device.

Tradeoffs

  • Performance: Installing Debian on a network drive is noticeably slower than a native install. Once booted, performance depends on network speed and RAM — the author notes that with enough RAM, the OS runs smoothly after boot.
  • Complexity: The setup requires multiple services (Apache, TFTP, DNSMasq, iSCSI, ZFS) and careful configuration of authentication and ACLs.
  • Resilience: ZFS snapshots provide easy rollback, and the OS is independent of local disk failures. However, the network boot server becomes a single point of failure.
  • Use case: Best suited for server environments or development machines where local disk is reserved for other purposes (e.g., gaming, model storage).

Bottom line

Diskless Linux boot with ZFS, iSCSI, and PXE is a viable alternative to local disk installations for specific use cases. It requires a dedicated server and careful setup, but offers benefits in terms of manageability, snapshot-based recovery, and the ability to keep local disks free for other workloads. For most desktop users, the performance penalty and complexity outweigh the advantages.

Similar Articles

More articles like this

Coding 1 min

Building the TD4 4-Bit CPU

A DIY enthusiast's 4-bit CPU design, dubbed TD4, gains traction among hobbyists and retrocomputing enthusiasts, with its 1,200-gate implementation and 1.5 MHz clock speed sparking interest in the maker community. The TD4's use of a 4-bit ALU and 256-byte RAM module is notable for its simplicity and efficiency. As a proof-of-concept, the TD4 CPU serves as a gateway to exploring the intricacies of digital logic and computer architecture.

Coding 1 min

How I made $350K from an open-source JavaScript library using dual licensing

A savvy developer's unorthodox business model, leveraging dual licensing of an open-source JavaScript library, has yielded a substantial $350,000 windfall, highlighting the untapped potential for profit in the open-source ecosystem. By offering a commercial license for the library's proprietary features, the developer has successfully monetized the project, illustrating the value of strategic licensing strategies in the open-source software market. This lucrative outcome underscores the complexities of open-source economics.

Coding 1 min

Apple is enforcing an old App Store rule against a new kind of software

Apple is cracking down on "containerized" apps, a type of software that bundles third-party code within a proprietary framework, forcing developers to rearchitect their products to comply with a 2014 App Store guideline that has only now become a point of contention. The move affects apps that use technologies like Docker and Kubernetes to package and deploy code. Developers are scrambling to adapt to the new enforcement.

Coding 2 min

AI Subagents 'Coming Soon' to Visual Studio Copilot

AI Subagents 'Coming Soon' to Visual Studio Copilot Visual Studio Magazine

Coding 1 min

Show HN: PHP-fts – Full-text search engine in pure PHP, no extensions

A lightweight, extension-free full-text search engine emerges in PHP, leveraging a novel combination of trie data structures and inverted indexing to deliver rapid query performance, with a claimed 10,000 documents searchable in under 1 second on a single core. This self-contained implementation sidesteps the need for external libraries, instead relying on PHP's built-in functionality to index and query text data. Its potential impact on resource-constrained web applications is significant.

Coding 2 min

Kubernetes v1.36: Server-Side Sharded List and Watch

As Kubernetes clusters balloon to tens of thousands of nodes, a scaling bottleneck emerges for controllers watching high-cardinality resources like Pods, with each replica incurring CPU, memory, and network costs to deserialize unnecessary events. Kubernetes v1.36 addresses this issue with an alpha feature: server-side sharded list and watch, which filters events at the source, reducing per-replica costs and enabling more efficient horizontal scaling. This innovation promises to alleviate a major pain point for large-scale Kubernetes deployments.