Set up a debian pxe server with ipxe using custom compiled files - cesetxeberria/pxeserver GitHub Wiki

Download debian netinst iso, burn it to a cd or a usb and install. Just the minimal install will suffice.

As root user install dnsmasq, git and build-essential

apt-get install dnsmasq git build-essential

Create a new folder for the tftp-root and ipxe.

mkdir -p /home/tftp/ipxe

Create an ipxe script to embed in the boot files. It's based on this one from project FOG.

nano /home/tftp/embed.ipxe

#!ipxe
dhcp && goto netboot || goto dhcperror

:dhcperror
prompt --key s --timeout 10000 DHCP failed, hit 's' for the iPXE shell; reboot in 10 seconds && shell || reboot

:netboot
chain tftp://192.168.1.45/default.ipxe ||
prompt --key s --timeout 10000 Chainloading failed, hit 's' for the iPXE shell; reboot in 10 seconds && shell || reboot

The ip number is just an example, must be replaced with your own ip address.
You can get your ip address with

hostname -I

Download and compile ipxe, embedding previously created file.

git clone https://github.com/ipxe/ipxe
cd ipxe/src
make bin-x86_64-efi/snponly.efi EMBED=/home/tftp/embed.ipxe
make bin/undionly.kpxe EMBED=/home/tftp/embed.ipxe

Copy needed files.

cp ipxe/bin-x86_64-efi/snponly.efi /home/tftp/ipxe/
cp ipxe/bin/undionly.kpxe /home/tftp/ipxe/

Create a simple "Hello world" file for the menu.

nano /home/tftp/default.ipxe

#!ipxe
:MENU
menu
item --gap -- ---------------- iPXE boot menu ----------------
item hello        Hello world
item shell          ipxe shell
choose --default return --timeout 5000 target && goto ${target}
 
:hello
echo "hello world"
boot ||
goto MENU

:shell
shell ||
goto MENU
 
autoboot

Create new file /etc/dnsmasq.d/custom

nano /etc/dnsmasq.d/custom

interface=eth0
bind-dynamic
dhcp-range=192.168.1.54,proxy
enable-tftp
tftp-root=/home/tftp
pxe-service=x86PC, "ipxe bios", ipxe/undionly.kpxe
pxe-service=x86-64_efi, "ipxe efi", ipxe/snponly.efi

'eht0' in the first line and '192.168.1.54' in the third one are just examples. Must be filled with your own interface name and network address. You can get your interface name with

ip -o link | grep "state UP" | awk '{print substr($2, 1, length($2)-1)}'

And your network address with

ip route show | grep src | awk '{print substr($1, 1, length($1)-3)}'

Restart dnsmasq

systemctl restart dnsmasq

Now you can try to pxe boot your client. You shoud see this screen