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:
.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"
Next you can check the content of the service unit file:
~]# cat /usr/lib/systemd/system/tftp.service
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
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 check CONFIGURING 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:
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 check Apache 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
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:
Similarly try to access the kickstart config file on the web browser:
/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 .treeinfo
 file and reads the runtime image location from the .treeinfo
 file.
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
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:
Hit Enter to start the installation. If you see the following screen, that would mean you can now sit back and have your coffee!!
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.
To check the contents of tftp system files, you can simply run:
systemctl cat tftp.socket
systemctl cat tftp.server
Hey Admin
when i start the installation from pxe i get the message:
“disk sda given in ignoredisk command does not exist”
what im gonna do?
You will have to update kickstart file based on your environment.
If you don’t have sda then remove it from ignoredisk. Accordingly update your disk configuration or else that will also fail
Hey Admin
when i try to boot pxe i get this line:
and i get in blue window:
can you explaine me what is the problem and how to fix it?
i did it according the guide
The TFTP server seems to be working as it is able to serve request but the file download is failing means some problem in network/firewall/permission
Try to access the same locally using tftp client with GET. If that works then try disabling the firewall and re-try.
Is SELinux in Enforcing state?
Hai excellent set up. Can u do it for Ubuntu as well. Since many are starting to shift from centos/rhel to Ubuntu . Please do it and update here. Eagerly waiting
Thanks for your feedback, Ubuntu looks tricky as it doesn’t directly support kickstart. Anyhow I am trying to make it work, fingers crossed!
Thank you for the response. Even i’ve started checking now.
Hai guys. Ubuntu 18.04. and 20.04 uses different mechanism for kickstarting installation from each other.
Admin, hope you are trying to do for 20.04 since that it widely being adopted
Here you go, this is with cloud-init as kickstart is deprecated with Ubuntu 20.04
https://www.golinuxcloud.com/pxe-boot-server-cloud-init-ubuntu-20-04/
Hope this helps admin
https://www.pugetsystems.com/labs/hpc/How-To-Make-Ubuntu-Autoinstall-ISO-with-Cloud-init-2213/
Thanks Marvin, I will check this.
But just FYI, I was able to successfully install Ubuntu 20.04 using Kickstart. Although some post install issues are there and also the installation currently prompts for few inputs which I am trying to fix. So hopefully I should have one article soon.
Hai admin. I have followed the mentioned post. There they are passing user-data(kind of kickstart) into the extracted iso and then creating a new iso. And booting the machine with that iso to perform automatic installation. My bad it havent worked for me.
During integrity check it states error in 2 files ( i guess in grub.cfg and txt.cfg at line append initrd=/casper/hwe-initrd quiet autoinstall ds=nocloud;s=/cdrom/server —)
Eagerly waiting for your post to give it try. ATB
I skipped kickstart for now due to many reasons (will also explain this in my next article). Luckily for me I was able to successfully install Ubuntu 20.04 using cloud-init. My article is almost ready on cloud-init using legacy BIOS (Next would be UEFI). It should be published in few hours. I will update the same here.
Here you go
https://www.golinuxcloud.com/pxe-boot-server-cloud-init-ubuntu-20-04/
Thank you. Eagerly waiting for this 😉
Hai great work. Have you done pxe with kickstart for Ubuntu server? if so please share me the link it.
If not please, can u create one article on pxe+kickstart+ubuntu. It would be very useful.
That is definitely on my TODO list
Here you go, this is with cloud-init as kickstart is deprecated with Ubuntu 20.04
https://www.golinuxcloud.com/pxe-boot-server-cloud-init-ubuntu-20-04/
Hai,
I am inserting iso file directly in virtual box. I want to kickstart the installation . Kickstart is hosted through nfs.
Once i get the installation page i type “e” to edit and at the end of linuxefi…..quit, i type “inst.ks=nfs:nfsip:/kickstart/ks.cfg
I think there is some parameter issue in the above line
Note: Using centos8.3 UEFI mode
Please let me know what has gone wrong
You can follow this article which I have just written for configuring kickstart with UEFI and IPv6 network
Configure IPv6 UEFI PXE Boot with Kickstart [RHEL/CentOS 8]
I also encountered the same error with NFS, I tried to lookup official documentation but none of them seems to mention NFS support for IPv6 using dracut kernel menu for kickstart. So I switched to HTTP in my article, if you find any thing please do update here!
Hai admin, good job.
I am in a critical situation where I want to configure the same for dhcpv6. That is for ipv6.
1.Can u please mention the changes to be done in /etc/dhcp/dhcpd6.conf
2.Can you share reference link to configure dhcpv6, where i need to send ipv6 to client requesting for ip
Facing the same challenge. Working on dhcpv6 to provide ipv6 to client. No success. Do share info if anybody possess. Thank you
At what stage you are facing issue? DHCP itself or later stage? Any specific error you are getting?
Actually ive setup dhcpv6 with /118 subnet.
dhcp is giving the ip in the range which i have specified in the file (to 2 machines as per my setup).
But subnet in client is changed to /128 to both machines.
So 2 machines are not able to ping each other.
The subnet should be assigned based on the DHCP configuration.
I have written another article for IPv6, you can check the steps:
Configure IPv6 UEFI PXE Boot with Kickstart [RHEL/CentOS 8]
I actually don’t have an IPv6 setup handy so can’t test but here is a sample /etc/dhcp/dhcpd6.conf config file
In kickstart you can add
ip=dhcp6
Okay. will give it a try. If possible you could create a post on this concept. Many organizations has started transition to ipv6 already i hope.
Thanks in advance
yes, it is just that I have reconfigure the entire switch and my Virtual Connect to test this. I will definitely keep it in my TODO list.
Here you go
Configure IPv6 UEFI PXE Boot with Kickstart [RHEL/CentOS 8]
Wow. Thank you so much admin. Really appreciate your work. Will give it a try.
Its working well and good. Thank you for the post
One doubt is, authconfig is replaced by authselect in Kickstart (throwing a warning message, but doesnt affect the flow)
how can i convert the above line to authselect in Kickstart. can you help me with the changes?
I am afraid, I am also not very familiar with authselect. May be you can check this page https://www.mankier.com/7/authselect-migration, it can help.
Excellent. Thank you for the post admin. Will give this a try