Server Howto: PXE / UEFI network-boot

Pressing F12 during the POST boot cycle of most computers will produce a prompt asking which boot source you require. Some computers will default straight to network booting with F11. Selecting network booting will activate either the PXE function or the UEFI network stack, depending on what is configured in the BIOS. With a PXE / UEFI network boot function on your network, you can run rescue tools, partition tools, and install Linux distributions without needing to burn optical discs.

This howto describes how to set-up PXE/UEFI/BIOS booting on RHEL+clones and assumes you have followed the howtos and set-up: DNS, DHCP, and an in-house mirror as all three of those are needed in order to set-up tftpboot.


Install

The Trivial File Transport Protocol daemon can be installed as a separate system that is controlled via systemd. Install the tftp-server with the following (as root): dnf install tftp-server

You will need to enable the daemon with: systemctl enable tftp.socket --now. The socket daemon still start the tftp.service as required.

This is the first step, and difficult to test until we start to populate the directory. All data served by tftp-server comes from /var/lib/tftpboot and this directory is strictly locked to ensure tftp clients cannot wander off and try to grab files from other parts of the file-system, so do not try to symlink to other files/directories outside of /var/lib/tftpboot as it will not work!


PXE boot

From the DHCP set-up, you may remember the instruction to use core.efi. So where is that?

In order to set-up a pxeboot function, we need to install a set of packages that provide the Grub2 boot-loader.

The GRUB bootloader can be set-up in the /var/lib/tftpboot/ directory to provide a unified BIOS and UEFI boot process.

Install the following packages with the command: dnf install grub2-efi-x64-modules grub2-tools-extra grub2-pc-modules

Create the GRUB directories with the following command: grub2-mknetdir --net-directory /var/lib/tftpboot/

The above process will create a set of directories under /var/lib/tftpboot/boot/grub2/ that includes fonts, i386-pc (BIOS), locale, and x86_64-efi (EFI).

To save the need to create and maintain a large number of grub.conf files, it is recommended to create a directory /var/lib/tftpboot/config to store all of the configurations for both BIOS and EFI PXEbooting.

Symlinks must be created (with ln -s) to the configuration files, as below:

/var/lib/tftpboot/boot/grub2/i386-pc

grub.cfg -> ../../../config/grub.cfg
rocky8.cfg -> ../../../config/rocky8.cfg
rocky9.cfg -> ../../../config/rocky9.cfg
testing.cfg -> ../../../config/testing.cfg
tools.cfg -> ../../../config/tools.cfg

/var/lib/tftpboot/boot/grub2/x86_64-efi

grub.cfg -> ../../../config/grub.cfg
rocky8.cfg -> ../../../config/rocky8.cfg
rocky9.cfg -> ../../../config/rocky9.cfg
testing.cfg -> ../../../config/testing.cfg
tools.cfg -> ../../../config/tools.cfg


/var/lib/tftpboot/config/grub.cfg

This is the primary configuration file. Menu options for booting/installing Rocky Linux, etc., are kept in separate configuration files to avoid editing a huge configuration file.

set default=0
set timeout=-1
set gfxpayload=keep
set gfxmode=auto
insmod all_video
insmod png
insmod gfxterm
insmod gfxterm_background
terminal_output gfxterm
loadfont /boot/grub2/fonts/unicode.pf2
background_image -m stretch /background/spectrum.png

# Menu Colours
#
set color_normal=white/black
set menu_color_normal=white/black
set menu_color_highlight=white/cyan

submenu "System -->" {
    set menu_color_highlight=white/blue
    menuentry 'EFI System Setup' $menuentry_id_option 'uefi-firmware' {
      fwsetup
    }
    menuentry 'Reboot' {
      reboot
    }
    menuentry 'Shutdown' {
      halt
    }
}

submenu "Rocky Linux 9 -->" {
    set menu_color_highlight=white/green
    background_image -m stretch /background/spectrum-rocky.png
    source config/rocky9.cfg
    }

submenu "Rocky Linux 8 -->" {
    set menu_color_highlight=white/green
    background_image -m stretch /background/spectrum-rocky.png
    source config/rocky8.cfg
    }

submenu "Tools -->" {
    set menu_color_highlight=black/yellow
    background_image -m stretch /background/spectrum-tools.png
    source config/tools.cfg
    }

submenu "Testing (Here be Dragons!) -->" {
    set menu_color_highlight=white/light-red
    background_image -m stretch /background/spectrum-dragon.png
    source config/testing.cfg
    }

The background_image can be created by yourself to suit your PXEboot menu. If you are in a business, this might be a plain background with the company logo in the lower right corner.

The colours used for the menu text can be customised to suit your own requirements.

I created this background image in the GNU Image Manipulation Program with a resolution of 1280x800 pixels:

spectrum

The System menu allows access to the UEFI BIOS as well as options to reboot and shutdown the computer.

The next set of submenus load the separate configuration files as detailed below, and each of them has a small custom image:

Rocky Linux

spectrum

Tools

spectrum

Testing

spectrum


/var/lib/tftpboot/config/rocky9.cfg

Note: I prefer to use the older eth0/eth1/wlan0 naming style, so net.ifnames=0 biosdevname=0 are added to revert to the older style behaviour. Remove these if you prefer the en2p09481957 random nonsense. You will also need to remove these lines to install on Dell servers unless you want your eth0/1/2/3 to re-arrange on each boot!

The two menu entries below offer a standard install and a rescue mode to match what you would find if booting from the ISO image.

menuentry "Rocky 9 x86-64 Standard install" --class fedora --class gnu-linux --class gnu --class os {
    linux Rocky/9/x86_64/vmlinuz ramdisk_size=10000 net.ifnames=0 biosdevname=0 ipv6.disable=1 ip=dhcp inst.repo=ftp://mirror.gaztronics.net/rocky/9/BaseOS/x86_64/os
    initrd Rocky/9/x86_64/initrd.img
}

menuentry "Rocky 9 x86-64 Rescue" --class fedora --class gnu-linux --class gnu --class os {
    linux Rocky/9/x86_64/vmlinuz ramdisk_size=10000 net.ifnames=0 biosdevname=0 ipv6.disable=1 ip=dhcp inst.repo=ftp://mirror.gaztronics.net/rocky/9/BaseOS/x86_64/os rescue
    initrd Rocky/9/x86_64/initrd.img
}


/var/lib/tftpboot/config/rocky8.cfg

Note: I prefer to use the older eth0/eth1/wlan0 naming style, so net.ifnames=0 biosdevname=0 are added to revert to the older style behaviour. Remove these if you prefer the en2p09481957 random nonsense. You will also need to remove these lines to install on Dell servers unless you want your eth0/1/2/3 to re-arrange on each boot!

The two menu entries below offer a standard install and a rescue mode to match what you would find if booting from the ISO image.

menuentry "Rocky 8 x86-64 Standard install" --class fedora --class gnu-linux --class gnu --class os {
    linux Rocky/8/x86_64/vmlinuz ramdisk_size=10000 net.ifnames=0 biosdevname=0 ipv6.disable=1 ip=dhcp inst.repo=ftp://mirror.gaztronics.net/rocky/8/BaseOS/x86_64/os
    initrd Rocky/8/x86_64/initrd.img
}

menuentry "Rocky 8 x86-64 Rescue" --class fedora --class gnu-linux --class gnu --class os {
    linux Rocky/8/x86_64/vmlinuz ramdisk_size=10000 net.ifnames=0 biosdevname=0 ipv6.disable=1 ip=dhcp inst.repo=ftp://mirror.gaztronics.net/rocky/8/BaseOS/x86_64/os rescue
    initrd Rocky/8/x86_64/initrd.img
}


/var/lib/tftpboot/config/tools.cfg

The tools menu can be configured to provide Memtest, Clonezilla, gparted, and Rocky Linux Live images. Details on how to set these up are shown further down.

menuentry "Memtest86+ 64-bit EFI" {
    linux memtest86/memtest64.efi
}

menuentry "Memtest86+ 64-bit BIOS" {
    linux memtest86/memtest64.bin
}

menuentry "Clonezilla (3.2.0-5) [UEFI]" {
    linux clonezilla/vmlinuz boot=live union=overlay config components quiet noswap edd=on nomodeset nodmraid locales="en_US.UTF-8" keyboard-layouts="gb" ocs_live_run="ocs-live-general" ocs_live_extra_param="" ocs_live_batch=no net.ifnames=0 nosplash noprompt fetch=tftp://mail.gaztronics.net/clonezilla/filesystem.squashfs
    initrd clonezilla/initrd.img
}

menuentry "Clonezilla (3.2.0-5) [BIOS]" {
    linux16 clonezilla/vmlinuz boot=live union=overlay config components quiet noswap edd=on nomodeset nodmraid locales="en_US.UTF-8" keyboard-layouts="gb" ocs_live_run="ocs-live-general" ocs_live_extra_param="" ocs_live_batch=no net.ifnames=0 nosplash noprompt fetch=tftp://mail.gaztronics.net/clonezilla/filesystem.squashfs
    initrd16 clonezilla/initrd.img
}

menuentry "gparted Live (1.5.0-6 amd64)" {
    linux gparted/vmlinuz boot=live union=overlay username=user config components quiet net.ifnames=0 vga=788 locales="en_US.UTF-8" keyboard-layouts="NONE" fetch=tftp://192.168.10.253/gparted/filesystem.squashfs
    initrd gparted/initrd.img
}

menuentry "gparted Live (1.5.0-6 amd64) [BIOS]" {
    linux16 gparted/vmlinuz boot=live union=overlay username=user config components quiet net.ifnames=0 vga=788 locales="en_US.UTF-8" keyboard-layouts="NONE" fetch=tftp://192.168.10.253/gparted/filesystem.squashfs
    initrd16 gparted/initrd.img
}

menuentry "Rocky 9 Live MATE" {
    linux live/rocky/9/vmlinuz root=live:http://mirror.gaztronics.net/Live/Rocky/9/mate/squashfs.img ipv6.disable=1 ip=dhcp ro rd.live.image rd.luks=0 rd.md=0 rd.dm=0
    initrd live/rocky/9/initrd.img
}
menuentry "Rocky 9 Live Gnome" {
    linux live/rocky/9/vmlinuz root=live:http://mirror.gaztronics.net/Live/Rocky/9/gnome/squashfs.img ipv6.disable=1 ip=dhcp ro rd.live.image rd.luks=0 rd.md=0 rd.dm=0
    initrd live/rocky/9/initrd.img
}


/var/lib/tftpboot/config/testing.cfg

You can create a testing menu to hold kickstart-driven installations that are separate from the main configurations. This is handy if you are operating in a business and you need to keep the test installations separate from "live".

menuentry "Rocky 9 Test Server" --class fedora --class gnu-linux --class gnu --class os {
    linux rocky/9/x86_64/vmlinuz ramdisk_size=10000 net.ifnames=0 biosdevname=0 ipv6.disable=1 ip=dhcp inst.repo=ftp://mirror.gaztronics.net/rocky/9/BaseOS/x86_64/os inst.ks=ftp://mirror.gaztronics.net/kickstart/r9-test-server.cfg
    initrd rocky/9/x86_64/initrd.img
}

menuentry "Rocky 8 Test Server" --class fedora --class gnu-linux --class gnu --class os {
    linux rocky/8/x86_64/vmlinuz ramdisk_size=10000 net.ifnames=0 biosdevname=0 ipv6.disable=1 ip=dhcp inst.repo=ftp://mirror.gaztronics.net/rocky/8/BaseOS/x86_64/os inst.ks=ftp://mirror.gaztronics.net/kickstart/r8-test-server.cfg
    initrd rocky/8/x86_64/initrd.img
}

You may notice the addition of a inst.ks=ftp://mirror.gaztronics.net/kickstart/r8-test-server.cfg on the above config. This tells the installer to download and follow a kickstart script. The script is used to define partition layouts, network and authentication configuration, plus the packages to be installed, and from which repositories. See my Rocky Linux page for examples of installing with kickstart files.


sync-netboot

The set-up in this section is also needed to provide the vmlinuz and initrd files used by the PXEboot process to launch the installers/tools/etc.

The case and naming of the directories we are about to create are important as they are referenced in the Grub2 config files detailed above, so remain consistent with how you create your directory layout.

As mentioned earlier, /var/lib/tftpboot is locked down to stop tftp clients from stealing important files, like /etc/passwd or /etc/shadow. We cannot symlink to the files we might find in the /mirror directory, so assuming you followed the mirror howto, we need to create a folder structure to contain files, such as vmlinuz and initrd.img, that are used to provide a network boot function. As these files tend to be different between versions and distributions, we need to create an array of containing directories.

For Rocky Linux 9, I recommend creating a directory in /var/lib/tftpboot with: mkdir -p Rocky/9/x86_64

For Rocky Linux 8, I recommend creating a directory in /var/lib/tftpboot with: mkdir -p Rocky/8/x86_64

We now need to populate the x86_64 folders with the files used for network-booting. Assuming you followed the mirror howto, the simplest solution is to rsync the files lurking in /mirror. These files are updated each time there is a release; i.e. 9.4 to 9.5, so it is a good idea to create a script to do the heavy lifting. As ever, this script lives in /root/scripts

#!/bin/bash
#
# Script to rsync netboot images to PXE
#
# Variables
#
OPT=var

#################################################################
# Rocky Linux
#################################################################

# 9
echo -e "\nRocky 9\n"
rsync -$OPT --delete --exclude="README*" \
/mirror/rocky/9/BaseOS/x86_64/os/images/pxeboot/ \
/var/lib/tftpboot/Rocky/9/x86_64/

# 8
echo -e "\nRocky 8\n"
rsync -$OPT --delete --exclude="README*" \
/mirror/rocky/8/BaseOS/x86_64/os/images/pxeboot/ \
/var/lib/tftpboot/Rocky/8/x86_64/

#################################################################

# Clean-up
unset OPT

exit 0

This script is called sync-netboot and has 755 permissions. The script should be run each time a new minor release is made live and your mirror is up to date.


Memtest86+

Make a directory in /var/lib/tftpboot called memtest86.

The memtest website is here: External link  https://www.memtest.org/

On the right-hand side, select to download the Binary files; e.g. https://www.memtest.org/download/v7.00/mt86plus_7.00.binaries.zip

Un-pack the zip and save the files to: /var/lib/tftpboot/memtest86/

Check the files match the filename references in the tools.cfg listed above; namely memtest64.efi and memtest64.bin.


Clonezilla

Make a directory in /var/lib/tftpboot called clonezilla.

Download the latest Clonezilla zip from: External link  https://clonezilla.org/downloads.php

Extract the required files with the following (changing the version number for the latest):

unzip -j clonezilla-live-3.1.1-27-amd64.zip live/vmlinuz live/initrd.img live/filesystem.squashfs -d /var/lib/tftpboot/clonezilla/


gparted

Make a directory in /var/lib/tftpboot called gparted.

Download the latest gparted zip from: External link  https://gparted.org/download.php

Extract the required files with the following (changing the version number for the latest):

unzip -j gparted-live-1.5.0-6-amd64.zip live/vmlinuz live/initrd.img live/filesystem.squashfs -d /var/lib/tftpboot/gparted/


Rocky Live

The Live images allow the booting of a MATE or Gnome desktop version of Rocky Linux that loads into RAM. The Live image can be used for diagnostics and/or testing of a desktop/laptop/server.

The squashfs.img file is too large to download over TFTP. It is best to download it via HTTP. To facilitate this, you will need to create a folder in /mirror called live, followed by rocky/9/mate and rocky/9/gnome if you want to provide both MATE and Gnome desktop Live images.

Create a directory in /mnt called extract: mkdir /mnt/extract

MATE Live

Mount the ISO image with loop, for example:

mount -o loop /mirror/dl.rockylinux.org/9/live/x86_64/Rocky-9-MATE-x86_64-latest.iso /mnt/extract

Copy the required files as in the example:

cp /mnt/extract/isolinux/initrd.img /var/lib/tftpboot/live/rocky/9/

cp /mnt/extract/isolinux/vmlinuz /var/lib/tftpboot/live/rocky/9/

cp /mnt/extract/LiveOS/squashfs.img /mirror/live/rocky/9/mate/

Un-mount the ISO image with: umount /mnt/extract


Gnome Live

Mount the ISO image with loop, for example:

mount -o loop /mirror/dl.rockylinux.org/9/live/x86_64/Rocky-9-Workstation-x86_64-latest.iso /mnt/extract

Copy the required file as in the example:

cp /mnt/extract/isolinux/initrd.img /var/lib/tftpboot/live/rocky/9/

cp /mnt/extract/isolinux/vmlinuz /var/lib/tftpboot/live/rocky/9/

cp /mnt/extract/LiveOS/squashfs.img /mirror/live/rocky/9/gnome/

Un-mount the ISO image with: umount /mnt/extract


Page updated: 4th April 2025