PXE booting my custom AlmaLinux Live Image
Introduction
In my last blog post, we have already built an ISO image
containing the anaconda
installer using livemedia-creator
.
Of course, it is far too annoying if you have to mount the ISO again after every build, etc.
That is why we now want to automatically start an installation via PXE after every new build.
The idea of this article is to show which services are necessary for this and how to provide them under AlmaLinux 9.4.
Important: Layer 2
Before you start setting up a DHCP server, you should be aware that there may be problems if a standard DHCP server is already running in your home network. My recommendation is to operate this build- and test infrastructure in a separate Layer 2. I will use a separte VLAN for this.
Building for PXE booting
livemedia-creator --make-pxe-live \
--iso AlmaLinux-9.4-x86_64-boot.iso \
--ks lukas.ks \
--nomacboot \
--resultdir /root/isobuild/result_pxe \
--project LukasOS \
--releasever 2024.1
This will result in the result_pxe
directory containing the following files:
[root@localhost isobuild]# ls -1 --size -h result_pxe/
total 4.8G
4.0K PXE_CONFIG
58M initramfs-5.14.0-427.37.1.el9_4.x86_64.img
1011M live-rootfs.squashfs.img
3.8G lmc-disk-yicryf70.img
13M vmlinuz-5.14.0-427.37.1.el9_4.x86_64
Netbooting under Linux
This is the sequence for booting a Linux using the network (simplified):
- DHCP:
- The UEFI initializes the network stack and requests a DHCP Lease.
- The DHCP server offers a DHCP lease and sets the following DHCP options 1:
- 66:
tftp-server-name
: name or IP address of the TFTP Server - 67:
boot-file-name
: filename to load from the TFTP Server
- 66:
- TFTP Boot:
- The PXEClient will connect to the tftp server (DHCP Option 66) and request the filename given in option 67.
- Boot Procedure:
- The PXEClient will hand over to
shimx64.efi
. shimx64.efi
is required for Secure Boot to work. Shim is signed by the “Microsoft 3rd Party UEFI CA”.shimx64.efi
will then loadgrubx64.efi
.grubx64.efi
will loadgrub.cfg
via TFTP.grubx64.efi
will hand over tovmlinuz
andinitramfs
.
- The PXEClient will hand over to
initramfs
(dracut
)- it will evalute the kernel command line argument (
root
) - the initramfs will mount the soon-to-be root under
/sysroot
- and then it will switch-root to
/sysroot
- it will evalute the kernel command line argument (
Setting up DHCP
To run network based installations we need a DHCP Server that tells the clients which file to boot and a TFTP Server which offers the files to boot.
Under CentOS/Alma/Rocky Linux 9 the default is still the isc-dhcp-server.
But the ISC has already moved their development to the new kea
server. 2
Fedora 39 and 40 already provide kea
in the default package repositories 3,
hence I will focus on kea
.
To install kea
we need to enable EPEL first:
dnf install epel-release
crb enable
dnf list kea*
The most important configuration is the following section inside /etc/kea/kea-dhcp4.conf
:
{
// ...
"client-classes": [
{
"name": "pxe_uefi_x64",
"test": "substring(option[60].hex,0,9) == 'PXEClient' and option[93].hex == 0x0007",
"option-data": [
{
"name": "tftp-server-name",
"data": "192.168.99.3"
},
{
"name": "boot-file-name",
"data": "shimx64.efi"
}
]
}
]
// ...
}
Setting up TFTP
yum install tftp-server
firewall-cmd --add-service=tftp
systemctl enable tftp.socket
After the installation and activation, in.tftpd
will serve the directory /var/lib/tftpboot
.
Then we can copy the files to the directory:
cp /boot/efi/EFI/almalinux/shimx64.efi /var/lib/tftpboot/
cp /boot/efi/EFI/almalinux/grubx64.efi /var/lib/tftpboot/
cp /root/isobuild/result_pxe/initramfs-*.x86_64.img /var/lib/tftpboot/
cp /root/isobuild/result_pxe/initramfs-*.x86_64.img /var/lib/tftpboot/
cp /root/isobuild/result_pxe/vmlinuz-*.x86_64 /var/lib/tftpboot/
We also have to set the correct permissions:
chmod -R 0755 /var/lib/tftpboot/
Now we are only missing the configuration for grub:
[root@localhost ~]# cat /var/lib/tftpboot/grub.cfg
function load_video {
insmod efi_gop
insmod efi_uga
insmod video_bochs
insmod video_cirrus
insmod all_video
}
load_video
set gfxpayload=keep
insmod gzio
menuentry 'Netboot my custom AlmaLinux' --class gnu-linux --class gnu --class os {
linux $fw_path/vmlinuz ip=dhcp root=live:http://192.168.99.3/live.img
initrd $fw_path/initramfs.img
}
menuentry 'Leave GRUB' {
exit
}
Setting up HTTP
I will be using caddy
as a small HTTP server.
[root@localhost ~]# yum install caddy
[root@localhost ~]# cat /etc/caddy/Caddyfile
http:// {
root * /var/www
file_server
}
And we have to copy the built image:
cp /root/isobuild/result_pxe/live-rootfs.squashfs.img /var/www/live.img
Booting via PXE
That’s it, now we are ready to boot via PXE.
Debugging DHCP Leases
[root@localhost kea]# tcpdump -i ens18 -n port 67 and port 68
dropped privs to tcpdump
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on ens18, link-type EN10MB (Ethernet), snapshot length 262144 bytes
12:41:48.010159 IP 0.0.0.0.bootpc > 255.255.255.255.bootps: BOOTP/DHCP, Request from bc:24:11:5a:68:a7, length 347
12:41:51.969200 IP 0.0.0.0.bootpc > 255.255.255.255.bootps: BOOTP/DHCP, Request from bc:24:11:5a:68:a7, length 347
12:41:59.969826 IP 0.0.0.0.bootpc > 255.255.255.255.bootps: BOOTP/DHCP, Request from bc:24:11:5a:68:a7, length 347