Debian diskless using PXE and root on NFS.

Howto

I wanted to have a debian bootable using PXE with full persistency so I opted for root on NFS.

It use debian stretch for both the server and the target.

The pxelinux config by default select to boot on the local drive, so I can set my workstation to boot by default on PXE and be able to boot the debian without having to spawn the bios to select the PXE.

Conventions I used at this time

  • PXE/tftp server IP: 192.168.10.11
  • TFTP root dir: /mnt/zfs/deadpool0/public/TFTP
  • NFS root dir: /nfsroot
  • OS on PXE/tftp server: debian stretch, same for the target nfs root
  • Kernel for target (if your debian/version have a newer, use the latest): 4.9.0-4-amd64
  • My NFS root is shared from ZFS using parameters: rw=@192.168.10.0/24,no_root_squash,async,insecure
    • You should be able to use the same parameters with /etc/exports

EdgeRouter

To be able to PXE boot I needed to add the following in my DHCP "vlan_lan" service:

bootfile-server 192.168.10.11
bootfile-name /pxelinux.0

Prerequisite

apt install tftpd-hpa syslinux initramfs-tools pxelinux debootstrap

Configuring TFTP server

I use TFTPD-HPA so I changed the config file /etc/default/tftpd-hpa to:

TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/mnt/zfs/deadpool0/public/TFTP"
TFTP_ADDRESS="0.0.0.0:69"
TFTP_OPTIONS="--secure --create"

Configure pxelinux

cd /mnt/zfs/deadpool0/public/TFTP
cp /usr/lib/PXELINUX/pxelinux.0 .
mkdir -p pxelinux.cfg boot/isolinux/
cp -r /usr/lib/syslinux/modules/bios/* boot/isolinux/
cp /boot/initrd.img-4.9.0-4-amd64 /boot/initrd.img-4.9.0-6-amd64 .

In file pxelinux.cfg/default:

DEFAULT menu.c32

PROMPT 0
TIMEOUT 300
ONTIMEOUT local

LABEL reboot
        MENU LABEL reboot computer
        COM32 reboot.c32

LABEL local
        MENU LABEL boot local drive
        LOCALBOOT 0

LABEL linux
        MENU LABEL Linux Debian 4.9.0-4-amd64
        KERNEL vmlinuz-4.9.0-4-amd64
        APPEND root=/dev/nfs initrd=initrd.img-4.9.0-4-amd64 nfsroot=192.168.10.11:/nfsroot ip=dhcp rw

Install target nfs root

# create /nfsroot if not exists, don't forget the NFS export
debootstrap stretch /nfsroot
# Then after finish:
cp /etc/network/interfaces /nfsroot/etc/network/interfaces
cp /etc/hosts /nfsroot/etc/
cp /etc/fstab /nfsroot/etc/

File /nfsroot/etc/hosts should looks like:

127.0.0.1       localhost
127.0.1.1       pxeboot

# The following lines are desirable for IPv6 capable hosts

::1     localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

File /nfsroot/etc/fstab should looks like:

# /etc/fstab: static file system information.

#
# Use 'blkid' to print the universally unique identifier for a

# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).

#
# `<file system>` `<mount point>`   `<type>`  `<options>`       `<dump>`  `<pass>`

/dev/ram0  /       ext4   defaults    0   0
proc       /proc      proc   defaults    0   1
tmpfs      /tmp       tmpfs  defaults    0   1

Then chroot to the target and edit some more things:

chroot /nfsroot
echo pxeboot > /etc/hostname
apt update
# If you want more stuff and a GUI like MATE:
apt install task-mate-desktop openssh-server screen tmux sudo htop vim
# Don't forget a root password
passwd root
# And an user with the right groups!
useradd -m -G adm,dialout,cdrom,sudo,dip,plugdev,users dashie
passwd dashie

Now you can boot any computer on PXE and it should get a full diskless debian!

References