Build PXE/iPXE Server for Ubuntu 20.04


To verify the PXE function of the network card, you need to build a PXE server. PXE is that the network card starts from the server and then downloads the system image to realize remote system startup or system installation locally.

PXE Server components

DHCP Server
Assign the network IP address to the PXE network card and provide the specified system startup file through the network.
TFTP Server
The PXE network card obtains the boot file through the TFTP protocol, for example: pxelinux 0,vmlinuz,initrd.img, undionly.kpxe et al.
FTP Server
PXE network card downloads the system image file through FTP protocol, including a complete system.
It is a collection of boot loaders, which can boot the system from hard disk, CD or through PXE network.
iPXE is the leading open source network boot firmware. It provides a full PXE implementation enhanced with additional features such as:

  • boot from a web server via HTTP
  • boot from an iSCSI SAN
  • boot from a Fibre Channel SAN via FCoE
  • boot from an AoE SAN
  • boot from a wireless network
  • boot from a wide-area network
  • boot from an Infiniband network
  • control the boot process with a script

Let's take Ubuntu 20.04 as an example to illustrate how to build a personal PXE Server.

Configure Static IP Address

Select a network card as the external port of the next DHCP Server. Select the network card enp1s0 here to configure the static IP

root@pxe-server:/home/pxe/Desktop# cat /etc/netplan/01-network-manager-all.yaml 
# Let NetworkManager manage all devices on this system
 # version: 2
 # renderer: NetworkManager
      dhcp4: no
      dhcp6: no
      addresses: []
        addresses: []

root@pxe-server:/home/pxe/Desktop# ifconfig
enp1s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet  netmask  broadcast
        ether xx:xx:xx:xx:xx:xx  txqueuelen 1000  (Ethernet)

The temporary IP can also be configured through ifconfig. The system needs to be reconfigured after restart. Sometimes it is found that the previously configured static IP is not successful after restarting, you can manually configure it once, and then restart the DHCP Server.

root@pxe-server:/home/pxe/Desktop# ifconfig enp1s0

Configure DHCP Service

  1. Install DHCP Server
root@pxe-server:/home/pxe/Desktop# apt install isc-dhcp-server
  1. Edit / etc / default / ISC DHCP server
    Select the network card enp1s0 to be bound by DHCP Server here
root@pxe-server:/home/pxe/Desktop# cat /etc/default/isc-dhcp-server
# Defaults for isc-dhcp-server (sourced by /etc/init.d/isc-dhcp-server)

# Path to dhcpd's config file (default: /etc/dhcp/dhcpd.conf).

# Path to dhcpd's PID file (default: /var/run/

# Additional options to start dhcpd with.
#	Don't use options -cf or -pf here; use DHCPD_CONF/ DHCPD_PID instead

# On what interfaces should the DHCP server (dhcpd) serve DHCP requests?
#	Separate multiple interfaces with spaces, e.g. "eth0 eth1".
INTERFACES="enp1s0" #This parameter can be set to avoid subsequent Error/warning
  1. Edit / etc / DHCP / DHCP PD conf
    The key information of DHCP Server is configured here, including IP address segment and route. For PXE Server, it also needs to include pxe startup image and next server
root@pxe-server:/home/pxe/Desktop# cat /etc/dhcp/dhcpd.conf
# dhcpd.conf
# Sample configuration file for ISC dhcpd
# Attention: If /etc/ltsp/dhcpd.conf exists, that will be used as
# configuration file instead of this file.

# option definitions common to all supported networks...
option domain-name "";
#option domain-name-servers,;#This line is commented out, which sometimes leads to the failure of DHCP client to obtain IP

default-lease-time 600;
max-lease-time 7200;

# The ddns-updates-style parameter controls whether or not the server will
# attempt to do a DNS update when a lease is confirmed. We default to the
# behavior of the version 2 packages ('none', since DHCP v2 didn't
# have support for DDNS.)
ddns-update-style none;

# If this DHCP server is the official DHCP server for the local
# network, the authoritative directive should be uncommented.

# Use this to send dhcp log messages to a different log file (you also
# have to hack syslog.conf to complete the redirection).
#log-facility local7;

# No service will be given on this subnet, but declaring it helps the 
# DHCP server to understand the network topology.

#subnet netmask {

# This is a very basic subnet declaration.

#subnet netmask {
#  range;
#  option routers,;

# This declaration allows BOOTP clients to get dynamic addresses,
# which we don't really recommend.

#subnet netmask {
#  range dynamic-bootp;
#  option broadcast-address;
#  option routers;

# A slightly different configuration for an internal subnet.
#subnet netmask {
#  range;
#  option domain-name-servers;
#  option domain-name "";
#  option subnet-mask;
#  option routers;
#  option broadcast-address;
#  default-lease-time 600;
#  max-lease-time 7200;
option client-architecture code 93 = unsigned integer 16;
subnet netmask {
#  option domain-name-servers,;
#  option domain-name "";
#  option subnet-mask;
  option routers;
#  option broadcast-address;
#  default-lease-time 600;
#  max-lease-time 7200;
  # tftp server IP Address
  # ++++++++++++++++++++++++ For PXE Boot file
  #filename "pxelinux.0";
  # ------------------------ For PXE Boot file
  # ++++++++++++++++++++++++ For iPXE Boot files
  if exists user-class and option user-class = "iPXE" {
      filename "ipxe.script";   # for iPXE booting scripts
  } elsif option client-architecture = 00:00 {
      filename "undionly.kpxe"; # for booting legacy PXE
  } else {
      filename "ipxe.efi";      # for booting UFEI PXE
  # ------------------------ For iPXE Boot files

# Hosts which require special configuration options can be listed in
# host statements.   If no address is specified, the address will be
# allocated dynamically (if possible), but the host-specific information
# will still come from the host declaration.

#host passacaglia {
#  hardware ethernet 0:0:c0:5d:bd:95;
#  filename "vmunix.passacaglia";
#  server-name "";

# Fixed IP addresses can also be specified for hosts.   These addresses
# should not also be listed as being available for dynamic assignment.
# Hosts for which fixed IP addresses have been specified can boot using
# BOOTP or DHCP.   Hosts for which no fixed address is specified can only
# be booted with DHCP, unless there is an address range on the subnet
# to which a BOOTP client is connected which has the dynamic-bootp flag
# set.
#host fantasia {
#  hardware ethernet 08:00:07:26:c0:a5;
#  fixed-address;

# You can declare a class of clients and then do address allocation
# based on that.   The example below shows a case where all clients
# in a certain class get addresses on the 10.17.224/24 subnet, and all
# other clients get addresses on the 10.0.29/24 subnet.

#class "foo" {
#  match if substring (option vendor-class-identifier, 0, 4) = "SUNW";

#shared-network 224-29 {
#  subnet netmask {
#    option routers;
#  }
#  subnet netmask {
#    option routers;
#  }
#  pool {
#    allow members of "foo";
#    range;
#  }
#  pool {
#    deny members of "foo";
#    range;
#  }

  1. Enable DHCP service
    After the configuration is completed, restart the DHCP service. If DHCP does not work, you can restart it in this way to correct it.
root@pxe-server:/home/pxe/Desktop# service isc-dhcp-server restart
root@pxe-server:/home/pxe/Desktop# service isc-dhcp-server status
● isc-dhcp-server.service - ISC DHCP IPv4 server
     Loaded: loaded (/lib/systemd/system/isc-dhcp-server.service; enabled; vendor preset: enabled)
     Active: active (running) since Thu 2021-04-22 17:16:17 CST; 1s ago
       Docs: man:dhcpd(8)
   Main PID: 2827 (dhcpd)
      Tasks: 4 (limit: 8778)
     Memory: 4.8M
     CGroup: /system.slice/isc-dhcp-server.service
             └─2827 dhcpd -user dhcpd -group dhcpd -f -4 -pf /run/dhcp-server/ -cf /etc/dhcp/dhcpd.conf enp1s0

4 June 22-17:16:17 pxe-server sh[2827]: Wrote 1 leases to leases file.
4 June 22-17:16:17 pxe-server dhcpd[2827]: Listening on LPF/enp1s0/xx:xx:xx:xx:xx:xx/
4 June 22-17:16:17 pxe-server sh[2827]: Listening on LPF/enp1s0/xx:xx:xx:xx:xx:xx/
4 June 22-17:16:17 pxe-server sh[2827]: Sending on   LPF/enp1s0/xx:xx:xx:xx:xx:xx/
4 June 22-17:16:17 pxe-server sh[2827]: Sending on   Socket/fallback/fallback-net
4 June 22-17:16:17 pxe-server dhcpd[2827]: Sending on   LPF/enp1s0/xx:xx:xx:xx:xx:xx/
4 June 22-17:16:17 pxe-server dhcpd[2827]: Sending on   Socket/fallback/fallback-net
4 July 22:16:17 pxe-server dhcpd[2827]: Server starting service.
4 June 22-17:16:18 pxe-server dhcpd[2827]: reuse_lease: lease age 118 (secs) under 25% threshold, reply with unaltered, existing lease for
4 June 22-17:16:18 pxe-server dhcpd[2827]: DHCPREQUEST for from xx:xx:xx:xx:xx:xx ( ) via enp1s0

Configure TFTP Service

  1. Install TFTP service
root@pxe-server:/home/pxe/Desktop# apt install tftpd-hpa
  1. Configure / etc / default / tftpd HPA
root@pxe-server:/home/pxe/Desktop# cat /etc/default/tftpd-hpa
# /etc/default/tftpd-hpa

TFTP_DIRECTORY="/srv/tftp" #Download file directory
  1. Enable TFTP service
root@pxe-server:/home/pxe/Desktop# service tftpd-hpa restart
root@pxe-server:/home/pxe/Desktop# service tftpd-hpa status
● tftpd-hpa.service - LSB: HPAs tftp server
     Loaded: loaded (/etc/init.d/tftpd-hpa; generated)
     Active: active (running) since Thu 2021-04-22 17:44:09 CST; 1s ago
       Docs: man:systemd-sysv-generator(8)
    Process: 1817 ExecStart=/etc/init.d/tftpd-hpa start (code=exited, status=0/SUCCESS)
      Tasks: 1 (limit: 8778)
     Memory: 1.0M
     CGroup: /system.slice/tftpd-hpa.service
             └─1825 /usr/sbin/in.tftpd --listen --user tftp --address :69 --secure /srv/tftp

4 June 22-17:44:09 pxe-server systemd[1]: Starting LSB: HPAs tftp server...
4 June 22-17:44:09 pxe-server tftpd-hpa[1817]:  * Starting HPAs tftpd in.tftpd
4 June 22-17:44:09 pxe-server tftpd-hpa[1817]:    ...done.
4 June 22-17:44:09 pxe-server systemd[1]: Started LSB: HPA's tftp server.

PXE verification

Configure FTP Service

There are several options for downloading the system installation image, such as FTP, HTTP, NFS, etc. select FTP here

  1. Install FTP Server
root@pxe-server:/home/pxe/Desktop# apt install vsftpd

The default folder of FTP is "/ srv/ftp /". You need to copy OS image to this directory. The following is redhat8 1 OS images

root@pxe-server:/home/pxe/Desktop# ls /srv/
ftp  tftp
root@pxe-server:/home/pxe/Desktop# ls /srv/ftp/
AppStream  EFI   extra_files.json  images    media.repo               RPM-GPG-KEY-redhat-release
BaseOS     EULA  GPL               isolinux  RPM-GPG-KEY-redhat-beta  TRANS.TBL
  1. Configure / etc / vsftpd conf

  2. Enable FTP service

root@pxe-server:/home/pxe/Desktop#service vsftpd status
● vsftpd.service - vsftpd FTP server
     Loaded: loaded (/lib/systemd/system/vsftpd.service; enabled; vendor preset: enabled)
     Active: active (running) since Tue 2021-04-13 05:36:40 CST; 12h ago
   Main PID: 32304 (vsftpd)
      Tasks: 1 (limit: 154342)
     Memory: 21.5M
     CGroup: /system.slice/vsftpd.service
             └─32304 /usr/sbin/vsftpd /etc/vsftpd.conf

4 13 05:36:40 pxeserver systemd[1]: Starting vsftpd FTP server...
4 13 05:36:40 pxeserver systemd[1]: Started vsftpd FTP server.

Configure Syslinux for PXE verification

If you do not need to verify PXE, you can skip this chapter and go directly to the next chapter to configure iPXE.

  1. install Syslinux
root@pxe-server:/home/pxe/Desktop# apt install syslinux

After installation, you can find legacy/uefi boot image in the following directory

root@pxe-server:/home/pxe/Desktop# ls /usr/lib/syslinux
mbr  memdisk  modules
root@pxe-server:/home/pxe/Desktop# ls /usr/lib/syslinux/modules
bios  efi32  efi6
  1. Copy pxelinux.0 file to "/ srv/tftp /" directory, where all boot image s used, including iPXE, should be included. The names of these files are contained in "/ etc / DHCP / DHCP pd.conf"

  2. Copy initrd. From OS image file IMG, vmlinuz to tftp/pxeboot / directory

root@pxe-server:/home/pxe/Desktop# ls /srv/ftp/images/pxeboot/ #redhat8. OS images for 1
initrd.img  vmlinuz
root@pxe-server:/home/pxe/Desktop# ls /srv/tftp/pxeboot/
initrd.img  vmlinuz
  1. Configure pxelinux CFG / default file
root@pxe-server:/home/pxe/Desktop# cat /srv/tftp/pxelinux.cfg/default
default redhat81
timeout 3
prompt 0
label redhat81
menu title redhat 8.1 pxe installtion
kernel /pxeboot/vmlinuz
append initrd=/pxeboot/initrd.img inst.stage2=

At this time, the configuration of legacy PXE is completed and can be used to verify the function of PXE.

iPXE validation

Install HTTP Server

iPXE is not a support FTP server by default. You need to install HTTP Server to complete the transmission of installation files. The installation process is very simple.

root@pxe-server:/home/pxe/Desktop# apt install apache2
root@pxe-server:/home/pxe/Desktop# service apache2 status

After installation, copy the installation file to the / var/www/html directory and put the default index HTML can be deleted.

root@pxe-server:/home/pxe/Desktop# ls /var/www/html

iPXE verification

This is used to configure iPXE, which can support legacy and uefi PXE at the same time.

root@pxe-server:/home/pxe/Desktop# apt install ipxe
root@pxe-server:/home/pxe/Desktop# cp /usr/lib/ipxe/{ipxe.efi,undionly.kpxe} /srv/tftp/ 
root@pxe-server:/home/pxe/Desktop# ls /srv/tftp/ 
ipxe.efi undionly.kpxe ipxe.script

For ipxe Script, an example is given here:


menu iPXE Boot Options
item shell iPXE shell
item linux-net Linux OS installation
item exit  Exit to BIOS
choose --default linux-net --timeout 10000 option && goto ${option}
set server_root
initrd ${server_root}/RHEL8.3/images/pxeboot/initrd.img
kernel ${server_root}/RHEL8.3/images/pxeboot/vmlinuz inst.repo=${server_root}/RHEL8.3/ initrd=initrd.img

Added by kumar_ldh on Sat, 19 Feb 2022 08:27:43 +0200