In this tutorial I will share step by step instructions to configure UEFI PXE Boot using Kickstart. I have tested these steps on RHEL/CentOS 8 environment. We will perform the setup in the following order
Order of Performing UEFI PXE Boot with Kickstart
- Setup Installation Repo
- Install and Configure TFTP
- Install and Configure DHCP
- Install and Configure HTTP
- Prepare kickstart file
- Perform UEFI PXE Boot
Lab Environment
I have two physical hardware with support of UEFI BIOS. The first server is installed with CentOS 8 while we plan to UEFI PXE Boot the second server which also has UEFI BIOS. Here are my server details:
Hostname: server.example.com
Release: CentOS Linux release 8.2.2004 (Core)
IP Address: 192.151.6.151/26
Pre-requisite
- You must have RHEL/CentOS 8 installed OS on a server. Now this server may or may not have UEFI BIOS.
- If you are using RHEL 8 then you must have an active RHN subscription
- If you are using CentOS 8 then you must have an active internet connection to download and install package. Although you may also configure offline repository if your server doesn’t have active internet connection
Steps to configure UEFI PXE Boot Server using Kickstart
Step-1: Setup Installation Repository
First of all we would have to setup our installation repo which will be used for the installation over network. I have mounted the CentOS 8 ISO image on the server
~]# mount /dev/sr0 /mnt
mount: /mnt: WARNING: device write-protected, mounted read-only.
Next I will copy the content of this ISO to a local directory so that I don’t have to rely on the ISO image. I will create a local directory:
~]# mkdir /image
Next copy all the files from the ISO to this directory
~]# cp -apr /mnt/* /images/
After copying all the files:
![Configure UEFI PXE Boot with Kickstart [RHEL/CentOS 8]](/configure-uefi-pxe-boot-with-kickstart/pxe-14.webp)
.treeinfo and .discinfo from the image or
else your installation is expected to fail. These are referred during
the installation over the network using PXE to validate the integrity of
the repository.
Step-2: Install and Configure TFTP Server
Next we would need a TFTP server to transfer the UEFI PXE Boot files required for installing the target nodes over network. Use the following command to install tftp packages:
~]# dnf install tftp-server xinetd -y
With later releases of RHEL/CentOS, we may not need xinetd as in previous releases the tftp was managed by xinetd. But now it is managed by systemd so you may choose to exclude it but I have kept it for legacy reasons.
Once the package is installed, you can check for the path of systemd unit file using following command:
~]# rpm -ql tftp-server | grep -E "service|socket"
![Configure UEFI PXE Boot with Kickstart [RHEL/CentOS 8]](/configure-uefi-pxe-boot-with-kickstart/pxe-2.webp)
Next you can check the content of the service unit file:
~]# cat /usr/lib/systemd/system/tftp.service
![Configure UEFI PXE Boot with Kickstart [RHEL/CentOS 8]](/configure-uefi-pxe-boot-with-kickstart/pxe-3.webp)
Here you see that by default the tftp service will search for TFTP files
inside /var/lib/tftpboot. So we will place all our UEFI PXE Boot
files under this location. If you plan to use a different path then
you can modify this service file and execute following command to update
your changes:
]# systemctl daemon-reload
]# systemctl restart tftp.service
Next enable and start this service to make sure the service is started automatically post reboot.
]# systemctl enable tftp.service --now
Created symlink /etc/systemd/system/sockets.target.wants/tftp.socket → /usr/lib/systemd/system/tftp.socket.
Check the status of the service to make sure it was started successfully
~]# systemctl status tftp.service
![Configure UEFI PXE Boot with Kickstart [RHEL/CentOS 8]](/configure-uefi-pxe-boot-with-kickstart/pxe-4.webp)
tftp.service is controlled via tftp.socket. So
if there is no active connection for tftp.service then the service
become inactive and as soon as tftp.socket gets any TFTP request, it
will activate the service again.
Step-3: Configure UEFI PXE Boot Server
Next to perform UEFI {XE Boot installation, we will need PXE boot files.
Normally for Legacy BIOS PXE boot we needed pxelinux.0 and
ldlinux.c32 part of syslinux-tftpboot rpm.
But for UEFI BIOS we need following files:
- grubx64.efi provided by grub2-efi-x64 rpm
- shimx64.efi provided by shim-x64 rpm
- BOOTX64.EFI provided by shim-x64 rpm
You can copy the mentioned rpms from the image to some temporary
location such as /tmp and extract the rpm to get the required files:
]# cp /image/BaseOS/Packages/grub2-efi-x64-2.02-81.el8.x86_64.rpm /tmp/
]# cp /image/BaseOS/Packages/shim-x64-15-11.el8.x86_64.rpm /tmp/
Next extract these rpms using rpm2cpio command.
]# cd /tmp
]# rpm2cpio shim-x64-15-11.el8.x86_64.rpm | cpio -idm
]# rpm2cpio grub2-efi-x64-2.02-81.el8.x86_64.rpm | cpio -idm
We will store all our PXE files inside /var/lib/tftpboot/pxelinux. Now
if you recall, by default TFTP will look into /var/lib/tftpboot so we
must handle the extra pxelinux directory while setting up our UEFI PXE
Boot server.
]# mkdir /var/lib/tftpboot/pxelinux
Copy the PXE boot files from /tmp where we extracted the rpm to this location:
]# cp /tmp/boot/efi/EFI/BOOT/BOOTX64.EFI /var/lib/tftpboot/pxelinux/
]# cp /tmp/boot/efi/EFI/centos/shimx64.efi /var/lib/tftpboot/pxelinux/
]# cp /tmp/boot/efi/EFI/centos/grubx64.efi /var/lib/tftpboot/pxelinux/
Next we need initrd and vmlinuz file to load the Operating System
until hard disk and other interfaces are detected. I hope you are
familiar with the steps of
Linux Boot Process. These files can again be copied from the image,
so we will copy and place them also inside /var/lib/tftpboot/pxelinux/
]# cp /image/isolinux/vmlinuz /var/lib/tftpboot/pxelinux/
]# cp /image/isolinux/initrd.img /var/lib/tftpboot/pxelinux/
Following is the content of my /var/lib/tftpboot/pxelinux at this
stage:
~]# ls -l /var/lib/tftpboot/pxelinux/
total 78460
-rwx------. 1 root root 1877384 Jan 2 11:02 ,
-rwxr-xr-x. 1 root root 1211224 Jan 2 11:00 BOOTX64.EFI
-rwxr-xr-x. 1 root root 1877384 Jan 2 11:02 grubx64.efi
-r--r--r--. 1 root root 65114456 Jan 2 11:01 initrd.img
-rwxr-xr-x. 1 root root 1211224 Jan 2 11:02 shimx64.efi
-r-xr-xr-x. 1 root root 8913656 Jan 1 22:17 vmlinuz
Step-4: Configure DHCP for UEFI PXE Boot
Next we need to install and configure DHCP to support UEFI PXE Boot installation.
]# dnf -y install dhcp-server
Next we need to configure our dhcp server configuration file available
at /etc/dhcp/dhcpd.conf. Here is my sample DHCP configuration file:
# cat /etc/dhcp/dhcpd.conf
#
# DHCP Server Configuration file.
# see /usr/share/doc/dhcp-server/dhcpd.conf.example
# see dhcpd.conf(5) man page
#
non-authoritative;
allow bootp;
option space pxelinux;
option pxelinux.magic code 208 = string;
option pxelinux.configfile code 209 = text;
option pxelinux.pathprefix code 210 = text;
option pxelinux.reboottime code 211 = unsigned integer 32;
option architecture-type code 93 = unsigned integer 16;
subnet 192.151.6.128 netmask 255.255.255.192 {
option routers 192.151.6.190;
range 192.151.6.170 192.151.6.180;
class "pxeclients" {
match if substring (option vendor-class-identifier, 0, 9) = "PXEClient";
next-server 192.151.6.151;
filename "pxelinux/BOOTX64.EFI";
}
}
I will not be able to explain the entire configuration file, you can
checkCONFIGURING A DHCPV4 SERVER for
more information. Although let me explain at least the important part of
this configuration file i.e. below subnet section:
subnet 192.151.6.128 netmask 255.255.255.192 {
option routers 192.151.6.190;
range 192.151.6.170 192.151.6.180;
class "pxeclients" {
match if substring (option vendor-class-identifier, 0, 9) = "PXEClient";
next-server 192.151.6.151;
filename "pxelinux/BOOTX64.EFI";
}
}
Here we have basically defined our subnet and netmask value. You can get this using different linux commands such as:
# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 192.151.6.190 0.0.0.0 UG 100 0 0 eno49
192.151.6.128 0.0.0.0 255.255.255.192 U 100 0 0 eno49
192.168.122.0 0.0.0.0 255.255.255.0 U 0 0 0 virbr0
Here eno49 is our primary interface which has 192.151.6.128 as the
subnet and 255.255.255.192 as the netmask value. The option routers
contain the gateway of your server IP, which we can again get using
following command:
~]# ip route
default via 192.151.6.190 dev eno49 proto static metric 100
192.151.6.128/26 dev eno49 proto kernel scope link src 192.151.6.151 metric 100
192.168.122.0/24 dev virbr0 proto kernel scope link src 192.168.122.1 linkdown
Here 192.151.6.190 is our default gateway which will act as a router
for all incoming DHCP request.
Next under the class section we have defined next-server as the IP
address of our Kickstart server i.e. localhost and filename contains
the path of BOOTX64.EFI which will be used to perform the UEFI PXE
Boot over the network.
We have defined a range between 192.151.6.170 and 192.151.6.180 to
assign the IP address to our destination nodes which will be installed
over the network. This range must be free and must not be in use by any
other server.
Next enable and start the DHCP server service:
# systemctl enable dhcpd --now
Created symlink /etc/systemd/system/multi-user.target.wants/dhcpd.service → /usr/lib/systemd/system/dhcpd.service.
Check the status of the service to make sure it has started successfully:
![Configure UEFI PXE Boot with Kickstart [RHEL/CentOS 8]](/configure-uefi-pxe-boot-with-kickstart/pxe-7.webp)
Step-5: Configure Kickstart file for automated installation
Next we will create our kickstart file to have an un-attended automated installation. Now I have already explained different syntax and parameters used in kickstart file so I will not repeat the same here.
By default, when we install CentOS or RHEL server, we will have
/root/anaconda.cfg file available which will contain the parameters
used for the current installation. You can always take this file as your
base and further modify it based on your requirement.
I will create a new directory to store our kickstart file for the UEFI PXE Boot purpose:
~]# mkdir /ks
~]# cp /root/anaconda-ks.cfg /ks/kickstart.conf
Make sure the kickstart.conf file is readable for all users:
# ls -l /ks/kickstart.conf
-rw-r--r--. 1 root root 1608 Nov 28 15:09 /ks/kickstart.conf
Here is my sample kickstart configuration file:
~]# cat /ks/kickstart.conf
#version=RHEL8
ignoredisk --only-use=sda,sdb
autopart --type=lvm
# Partition clearing information
clearpart --all --initlabel --drives=sda,sdb
# Use graphical install
graphical
# Use CDROM installation media
cdrom
# Keyboard layouts
keyboard --vckeymap=us --xlayouts='us'
# System language
lang en_US.UTF-8
# Network information
network --bootproto=dhcp --onboot=off --ipv6=auto
network --hostname=server.example.com
# Create AppStream repo
repo --name="AppStream" --baseurl=http:///run/install/repo/AppStream
# Root password
rootpw --iscrypted $6$tGzXiAuBPTVcSiLX$4YD9A43gq2QJ7r5TqtL8uCwtQQWRON.CDYNkRkEx2vcsnrA5Jbv44jvZUyhS28VrKr0aU8/E8csTDZcb.VYUY.
# X Window System configuration information
xconfig --startxonboot
# Run the Setup Agent on first boot
firstboot --enable
# System services
services --enabled="chronyd"
# System timezone
timezone Asia/Kolkata --isUtc
user --groups=wheel --name=deepak --password=$6$.TNszXKGs9V0flRV$J.1piXFKbXJHHH9dkZdIfWfoUdWkfWAgz5ZNHdoN42VudL.1rehBONmkEZv/nRyyWUDt3puHJIlAhIYRFGB7y. --iscrypted --gecos="deepak"
%packages
@^minimal-environment
%end
%addon com_redhat_kdump --enable --reserve-mb='auto'
%end
%anaconda
pwpolicy root --minlen=6 --minquality=1 --notstrict --nochanges --notempty
pwpolicy user --minlen=6 --minquality=1 --notstrict --nochanges --emptyok
pwpolicy luks --minlen=6 --minquality=1 --notstrict --nochanges --notempty
%end
python -c 'import crypt,getpass;pw=getpass.getpass();print(crypt.crypt(pw) if (pw==getpass.getpass("Confirm: ")) else exit())'
command to generate an encrypted password which can be used in the
kickstart file for any user.
Step-6: Configure HTTP Server
Now we also need a service to host our image repository, we can use FTP or HTTP or NFS to host our image repository which we created in Step-1 of this tutorial. In my previous example where I had setup kickstart server using Legacy BIOS, I had used NFS so this time I decided to use HTTP server.
~]# dnf -y install httpd
Next we will configure Virtual Hosting to host our image repo path. I
have created a new file ks-server.conf under /etc/httpd/conf.d/ with
the following content:
<VirtualHost 192.151.6.151:80>
ServerAdmin root@server1.example.com
DocumentRoot /
ServerName server.example.com
ErrorLog logs/ks-server.example.com-error_log
CustomLog logs/ks-server.example.com-access_log common
<Directory /ks>
AllowOverride All
Require all granted
</Directory>
<Directory /image>
Options Indexes MultiViews
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
So here I am basically serving two different PATH over my HTTP server i.e. my kickstart configuration file and my image repository. I have also provided the required permission to access these path, you may checkApache DirectoryListings for more information.
Next enable and start the httpd service:
# systemctl enable httpd --now
Make sure the service has started successfully:
~]# systemctl status httpd
![Configure UEFI PXE Boot with Kickstart [RHEL/CentOS 8]](/configure-uefi-pxe-boot-with-kickstart/pxe-8.webp)
The next important thing we must do is to allow visibility of hidden
files in the HTTP server as I mentioned earlier, installation over
network requires validation of the repository using .treeinfo file
which is basically a hidden file in Linux. So by default this file will
not be visible on the web server.
So to fix this we must remove .??* from IndexIgnore parameter of
/etc/httpd/conf.d/autoindex.conf file.
Change
IndexIgnore .??* *~ *# HEADER* README* RCS CVS *,v *,t
To
IndexIgnore *~ *# HEADER* README* RCS CVS *,v *,t
and restart the httpd service.
~]# systemctl restart httpd
Next try to access the image repository path over the web server:
![Configure UEFI PXE Boot with Kickstart [RHEL/CentOS 8]](/configure-uefi-pxe-boot-with-kickstart/pxe-15.webp)
Similarly try to access the kickstart config file on the web browser:
![Configure UEFI PXE Boot with Kickstart [RHEL/CentOS 8]](/configure-uefi-pxe-boot-with-kickstart/pxe-10.webp)
/etc/httpd/logs/ks-server.example.com-error_log or
ks-server.example.com-access_log file which we had mentioned in our
virtual hosting config file.
Step-7: Update kickstart configuration file
Next update the image repository location in the kickstart file i.e.
/ks/kickstart.conf which we created above. Since we are using HTTP, so
we need to replace cdrom with following line:
# Use CDROM installation media
url --url=http://192.151.6.151/image/AppStream
By default if you had installed your server using DVD Media, then you
will have cdrom as the installation media. So, we will change that to
our HTTP url which contains the image for the installation.
Update the AppStream repo url, as with CDROM by default file://
handler is used but since we place to use HTTP so we will have to use
following path, additionally also mention the path of BaseOS repository.
# Create AppStream repo
repo --name="AppStream" --baseurl=http://192.151.6.151/image/AppStream
repo --name="BaseOS" --baseurl=http://192.151.6.151/image/BaseOS
Step-8: Create grub.cfg file
For UEFI PXE Boot we need a grub.cfg file with the details of PXE boot
files required for installation over network. Following is the content
from my grub.cfg file:
~]# cd /var/lib/tftpboot/pxelinux
~]# cat grub.cfg
set timeout=30
menuentry 'Install CentOS 8' {
linuxefi pxelinux/vmlinuz inst.ks=http://192.151.6.151/ks/kickstart.conf inst.stage2=http://192.151.6.151/image/ quiet
initrdefi pxelinux/initrd.img
}
Here we have created a single menu entry with the location of our
kickstart configuration file. The inst.stage2=boot option specifies
the location of the installation program’s runtime image. This option
expects the path to a directory that contains a valid.treeinfofile
and reads the runtime image location from the.treeinfofile.
Step-9: Configure Firewall
We have three services which must be allowed in the firewall i.e. DHCP, TFTP and HTTP. Since we are using firewalld, we will use firewall-cmd to enable these service/ports:
~]# firewall-cmd --add-service=http --add-service=tftp --add-service=dhcp --permanent
~]# firewall-cmd --reload
success
Verify the rules are added properly
~]# firewall-cmd --list-service
cockpit dhcp dhcpv6-client http ssh tftp
Step-10: Configure SELinux
I have kept my SELinux into Permissive mode for the sake of this tutorial.
~]# getenforce
Permissive
You can also set it to permissive mode using following command
~]# setenforce 0
or you may also choose to completely disable it.
Step-11: Perform PXE Boot
We are all setup to perform UEFI PXE Boot of our target blades to install them over network. Boot your client node and perform a network based installation. Now the shortcut button to boot over network may vary for different hardware but on most cases we are expected to press F12 to boot from network:
If your UEFI PXE Boot Server configuration is proper, then the TFTP files should get successfully downloaded as shown below
![Configure UEFI PXE Boot with Kickstart [RHEL/CentOS 8]](/configure-uefi-pxe-boot-with-kickstart/pxe-12.webp)
In the next screen you will see the boot menu entry as we had configured
in our grub.cfg file. Hit Enter to start the automated installation
using kickstart configuration file:
![Configure UEFI PXE Boot with Kickstart [RHEL/CentOS 8]](/configure-uefi-pxe-boot-with-kickstart/pxe-13.webp)
Hit Enter to start the installation. If you see the following screen, that would mean you can now sit back and have your coffee!!
![Configure UEFI PXE Boot with Kickstart [RHEL/CentOS 8]](/configure-uefi-pxe-boot-with-kickstart/pxe-16.webp)
Summary
In this tutorial we learned how to create UEFI PXE Boot server using RHEL/CentOS 8 Linux server. I have shared step by step instructions to create and setup your kickstart server. Although there are many other ways to achieve the same, for example you could use DNSMASQ instead of DHCP or use FTP or NFS instead of HTTP to host your kickstart file and image repository. So you can customize the installation steps as per your requirement. Although this article should give you a base to setup your first every PXE boot server.
Let me know if you face any issues via comments section.

![Configure IPv4 UEFI PXE Boot with Kickstart [RHEL/CentOS 8]](/configure-uefi-pxe-boot-with-kickstart/uefi_pxe_boot.jpg)
