Debian 9: Install PXE Boot server for thin client with NFS

This article will run PXE Boot server with NFS for thin client, and run Debian 9 on client which is connected to PXE Boot server via network. You do not need to install Debian 9 on client.

1 Install PXE Boot server

The following script will install PXE Boot server. Change the variables to your environment.

  • SERVER_IPADDR is IP adress of PXE Boot server.
  • DHCP_SERVER_INTERFACESv4 is network interface name for DHCP. DHCP will be provided via this network interface.
  • DHCP_SUBNET is network address for DHCP.
  • DHCP_NETMASK is subnet for DHCP.
  • DHCP_DNS is DNS for DHCP.
  • DHCP_ROUTER is gateway for DHCP.
  • DHCP_CLIENT_HOSTNAME is hostname of client.
  • DHCP_CLIENT_IPADDR is IP address of client.
  • DHCP_CLIENT_MACADDR is MAC address of client.

NFS root filesystem is set to the following.

  • Set root user password to "debian".
  • Create user which name is "debian" and password is "debian".
  • Install task-gnome-desktop package and openssh-server package.
#!/bin/sh

set -e

# Change the following variable to yours.
[ -z "${SERVER_IPADDR}" ] && \
  SERVER_IPADDR=$(hostname -I | awk '{ print $1 }')
[ -z "${DHCP_SERVER_INTERFACESv4}" ] && DHCP_SERVER_INTERFACESv4=ens3
[ -z "${DHCP_SUBNET}" ] && DHCP_SUBNET=192.168.11.0
[ -z "${DHCP_NETMASK}" ] && DHCP_NETMASK=255.255.255.0
[ -z "${DHCP_DOMAIN}" ] && DHCP_DOMAIN=hiroom2.com
[ -z "${DHCP_DNS}" ] && DHCP_DNS="192.168.11.2, 192.168.11.1"
[ -z "${DHCP_ROUTER}" ] && DHCP_ROUTER=192.168.11.1
[ -z "${DHCP_CLIENT_HOSTNAME}" ] && \
  DHCP_CLIENT_HOSTNAME=debian-9-pxeboot-client
[ -z "${DHCP_CLIENT_IPADDR}" ] && DHCP_CLIENT_IPADDR=192.168.11.254
[ -z "${DHCP_CLIENT_MACADDR}" ] && DHCP_CLIENT_MACADDR=52:54:00:5e:7a:a4

atftpd_install()
{
  sudo apt install -y atftpd
  sudo systemctl enable atftpd
  sudo systemctl restart atftpd
}

isc_dhcp_server_install()
{
  sudo apt install -y isc-dhcp-server

  sudo sed -e 's/^#DHCPDv4_CONF=/DHCPDv4_CONF=/g' \
       -e 's/^#DHCPDv4_PID=/DHCPDv4_PID=/g' \
       -e "s/INTERFACESv4=\"\"/INTERFACESv4=\"${DHCP_SERVER_INTERFACESv4}\"/g" \
       -i /etc/default/isc-dhcp-server

  cat <<EOF | sudo tee /etc/dhcp/dhcpd.conf
subnet ${DHCP_SUBNET} netmask ${DHCP_NETMASK} {
  option domain-name "${DHCP_DOMAIN}";
  option domain-name-servers ${DHCP_DNS};
  option routers ${DHCP_ROUTER};
  next-server ${SERVER_IPADDR};
  filename "pxelinux.0";
}

host ${DHCP_CLIENT_HOSTNAME} {
  hardware ethernet ${DHCP_CLIENT_MACADDR};
  fixed-address ${DHCP_CLIENT_IPADDR};
}
EOF

  sudo systemctl restart isc-dhcp-server
}

nfs_kernel_server_install()
{
  # Set NFS server.
  sudo apt install -y nfs-kernel-server debootstrap systemd-container
  sudo mkdir /srv/nfs4
  echo "/srv/nfs4 *(rw,sync,no_root_squash,no_subtree_check)" | \
    sudo tee /etc/exports
  sudo exportfs -ra

  # Create root filesystem.
  URL=$(grep "^deb .* stretch main" /etc/apt/sources.list | awk '{ print $2 }')
  sudo debootstrap stretch /srv/nfs4 "${URL}"

  # Get debconf from server for locale and keyboard.
  sudo apt install -y debconf-utils systemd-container
  sudo debconf-get-selections | grep locale | sudo tee /srv/nfs4/debconf.txt
  sudo debconf-get-selections | grep keyboard-configuration | \
    sudo tee -a /srv/nfs4/debconf.txt

  sudo systemd-nspawn -D /srv/nfs4 sh -c "
apt update -y
apt upgrade -y

# Set debconf to client for locale and keyboard.
cat debconf.txt | debconf-set-selections
apt install --reinstall -y locales keyboard-configuration
rm -f debconf.txt

# Install kernel and create initrd.
apt install -y initramfs-tools linux-image-amd64
cat <<EOF > /etc/initramfs-tools/initramfs.conf
MODULES=netboot
BUSYBOX=auto
KEYMAP=n
COMPRESS=gzip
DEVICE=
NFSROOT=${SERVER_IPADDR}:/srv/nfs4
BOOT=nfs
EOF
update-initramfs -tu

# Install GNOME desktop and OpenSSH server.
apt install -y task-gnome-desktop openssh-server

# Set root password and create user.
yes debian | passwd
useradd -m -s /bin/bash debian
yes debian | passwd debian

# systemd needs /etc/fstab entry too while using nfsroot.
echo '${SERVER_IPADDR}:/srv/nfs4 / nfs defaults 0 0' > /etc/fstab

# Generate /etc/resolv.conf with dhclient.
rm -f /etc/resolv.conf
cat <<EOF > /lib/systemd/system/dhclient.service
[Unit]
Description=Run dhclient to generate /etc/resolv.conf
After=network.target

[Service]
ExecStart=/sbin/dhclient
ExecReload=/sbin/dhclient

[Install]
WantedBy=multi-user.target
EOF
ln -s /lib/systemd/system/dhclient.service \
  /etc/systemd/system/multi-user.target.wants/dhclient.service
"
}

pxelinux_install()
{
  cd /srv/tftp

  sudo apt install -y pxelinux syslinux
  sudo ln -s /usr/lib/syslinux/modules/bios
  sudo ln -s /usr/lib/PXELINUX/pxelinux.0
  sudo ln -s /usr/lib/syslinux/modules/bios/ldlinux.c32
  sudo ln -s /srv/nfs4/vmlinuz
  sudo ln -s /srv/nfs4/initrd.img

  sudo mkdir pxelinux.cfg
  cat <<EOF | sudo tee pxelinux.cfg/default
path bios
include menu.cfg
default bios/vesamenu.c32
prompt 0
timeout 10
EOF

  cat <<EOF | sudo tee menu.cfg
menu hshift 13
menu width 49
menu margin 8
menu tabmsg

menu title Thin client boot menu
label debian-9-thin-client
  menu label ^Debian 9 thin client
  kernel vmlinuz
  append vga=788 initrd=initrd.img ip=dhcp nfsroot=${SERVER_IPADDR}:/srv/nfs4 rw
menu end
EOF
}

pxeboot_main()
{
  atftpd_install
  isc_dhcp_server_install
  nfs_kernel_server_install
  pxelinux_install
}

pxeboot_main

2 Run Debian 9 thin client with NFS

This article runs Debian 9 thin client on virtual machine on KVM. Virtual machine on VirtualBox and real machine too can run Debian 9 thin client with enabling network boot. Please check your BIOS setting.

Enable "NIC" of "Boot device order" and make it top of order with virt-manager.

0001_BootDeviceOrder.png

iPXE sends DHCP requests, receives DHCP response from PXE Boot server, download and run boot image.

0002_iPXE.png

syslinux's menu is displayed. After 1 second, "Debian 9 thin client" will be selected automatically.

0003_syslinux.png

Debian 9 thin client is started.

0004_BootDebian.png

Login is displayed.

0005_Login.png