Inspired by this article. Sometimes I use barebone machines to test or run something, and I already have a server machine, so it’s better to use diskless PXE boot. Enjoy!

Prerequisites

To run PXE we need:

  • DHCP server to serve PXE boot record
  • TFTP server with PXE boot kernel
  • NFS server as shared file storage for client

You can have other storage options too.

I used router with dnsmasq and client with realtek ethernet adapter.

Configure server

apt-get install tftpd-hpa syslinux pxelinux nfs-kernel-server

mkdir -p /srv/tftp /srv/nfs1
###cp -vax /srv/nfs1/boot/*.pxe /srv/tftp/ WE WILL DO THIS LATER
cp -vax /usr/lib/PXELINUX/pxelinux.o /srv/tftp/
cp -vax /usr/lib/syslinux/modules/bios/ldlinux.c32 /srv/tftp/
mkdir /srv/tftp/pxelinux.cfg

Create /srv/tftp/pxelinux.cfg/default file (if you have more than one diskless node — you may want to set different pxelinux.cfg configs instead of default one):

default Debian
prompt 1
timeout 3
label Debian
kernel vmlinuz.pxe
append rw initrd=initrd.pxe root=/dev/nfs ip=dhcp nfsroot=192.168.111.1:/srv/nfs1

Edit /etc/exports:

/srv/nfs1 192.168.111.0/24(rw,async,no_subtree_check,no_root_squash)

Reload services

systemctl restart tftpd-hpa
systemctl restart nfs-kernel-server

Create system on NFS share

Here we can install fresh system, or copy already working one.

See this article to copy system.

To install fresh one — you can use debootstrap.

Configure client to boot from NFS server

On server, edit /srv/nfs1/etc/fstab:

#192.168.111.1:/srv/nfs1 / nfs rw,noatime,nolock 1 1
/dev/nfs                 / nfs tcp,nolock 0 0
proc /proc    proc  defaults 0 0
none /tmp     tmpfs defaults 0 0
none /var/tmp tmpfs defaults 0 0
none /media   tmpfs defaults 0 0
none /var/log tmpfs defaults 0 0

Configure network, for example — edit /srv/nfs1/etc/network/interfaces:

iface eth0 inet dhcp

Add line to /srv/nfs1/etc/initramfs-tools/initramfs.conf:

BOOT=nfs

Start chroot:

mount --rbind /dev  /srv/nfs1/dev
mount --rbind /proc /srv/nfs1/proc/
mount --rbind /sys /srv/nfs1/sys/
chroot /srv/nfs1/  /bin/bash --login

Inside chroot

If your client ethernet adapter needs kernel module to work — add it to /etc/initramfs-tools/modules, example for realtek r8169:

echo "r8169" >> /etc/initramfs-tools/modules

Generate initramfs:

mkinitramfs -d /etc/initramfs-tools -o /boot/initrd.pxe
update-initramfs -u
cp -vax /boot/initrd.img[TAB] /boot/initrd.pxe
cp -vax boot/vmlinuz[TAB] boot/vmlinuz.pxe

On server

Copy INITRD.IMG and VMLINUZ to tftp:

cp -vax /srv/nfs1/boot/*.pxe /srv/tftp/

Congratulations, you can boot diskless machine!

There is one sidenote — you have to manually update boot kernel via

# 1) (on client) update client via it's package manager and get new kernel version
# 2) (on server) prepare and copy it into PXE boot dir
cp -vax /srv/nfs1/boot/initrd.img[TAB] /boot/initrd.pxe
cp -vax /srv/nfs1/boot/vmlinuz[TAB] /srv/nfs1/boot/vmlinuz.pxe
cp -vax /srv/nfs1/boot/*.pxe /srv/tftp/