Set up PXE Server on Ubuntu20.04 and Window 10

In this post, I would like to show you how to setup PXE (Pre-boot Execution Environment)server. If you don’t know what is PXE server, you can refer it as Install OS over Network or automate OS installation. There are many resources online, but I just wish to use the easiest way. In this post, I will teach you how to set up under Ubuntu20.04 and Windows 10, which you can set on any platform you prefer. There are many resources on setting up using CENTOS, so I will not show you, it’s nearly the same as UBUNTU. You will use these packages:

  • DHCPD (DHCP server): DHCP server, you need to also install tftp server

You can select DHCPD or DNSMAQ either one, the only difference is DHCPD you have to install and configure DHCP server, and TFTP server separately while DNSMASQ just configures DHCP and TFTP server in one file. I will teach both methods.

I will make a table to let you know more clearly :



Architecture & Structure:

├── bios
│ ├── kernel -> /tftpboot/kernels
│ ├── ldlinux.c32
│ ├── libcom32.c32
│ ├── libutil.c32
│ ├── pxelinux.0
│ ├── pxelinux.cfg -> /tftpboot/pxelinux.cfg
│ └── vesamenu.c32
├── efi
│ ├── ldlinux.e64
│ ├── libcom32.c32
│ ├── libutil.c32
│ ├── menu.c32
│ ├── pxelinux.cfg -> /tftpboot/pxelinux.cfg
│ ├── syslinux.efi
│ └── vesamenu.c32
├── images
│ └── ubuntu2004
├── kernelS
│ ├── ubuntu1804
│ │ ├── initrd
│ │ └── vmlinuz
│ └── ubuntu2004
│ ├── initrd
│ └── vmlinuz
└── pxelinux.cfg
├── default
└── default.bk

There are many ways to download images using different protocols to transfer files, the most commonly used are: HTTP, FTP, or NFS.

If you want to install Windows OS you have to use a samba server and put your image inside. You have to first create windowPE ISO images and access the samba server to install Windows OS. I will teach you how to make your own WinPE ISO file.

There are Three-Part in this post, you can select which one you like.

part 1: setup under Ubuntu

Part 2 Setup under window(only use BIOS as example)

Part3: create winPE iso image

Part 1 Setup under Ubuntu

Step 1. Install packages

You can decide which dhcp server package you want to install. I will teach both using dhcp or dnsmasq method.

- If you decide to use DHCPD server, you need to also install tftp server

- If you choose DNSMASQ then you don’t need to install tftpserver. DNSMASQ has dhcp, tftp, and DNS.

We will also need to install FTP or HTTP or NFS and SAMBA server. You can decide to download which one you like.

For DHCP method please use this command to install :

apt-get update && apt-get install samba isc-dhcp-server tftpd-hpa vsftpd apache2 nfs-kernel-server -y

For DNSMASQ please use this method:

apt-get update && apt-get install -y dnsmasq nfs-kernel-server vsftpd apache2 samba

Step 2 Create TFTP directory to store PXE boot files

2.1 Create tftpboot directory as the root directory. Inside it, we will this subdirectory:

kernels: store OS’s kernel file

Images: Store OS images

UEFI/BIOS: put pxeboot related file.

$mkdir -pv /tftpboot/{images,kernels,BIOS,UEFI}

2.2 change tftpboot permission

$chmod 777 -R /tftpboot

Step 3 Install required pxe boot files

This step is important it contains pxe bootable file, if you don’t have this file is not going to work. There are a couple of ways you can do get the file.

Method1: install syslinux and pxelinux packages

$sudo apt-get install syslinux pxelinux

You can decide to copy or use symbol link (ln-s)

UEFI Files:

cp -av /usr/lib/syslinux/modules/efi64/{ldlinux.e64,libcom32.c32,libutil.c32,vesamenu.c32} /tftpboot/UEFI
cp -av /usr/lib/SYSLINUX.EFI/efi64/syslinux.efi /tftpboot/UEFI

BIOS Files:

cp -av /usr/lib/PXELINUX/pxelinux.0 /tftpboot/BIOS
cp -av /usr/lib/syslinux/modules/bios/{ldlinux.c32,libcom32.c32,libutil.c32,vesamenu.c32} /tftpboot/BIOS

Method2: Download syslinux package from syslinux official site or using wget method


unzip the file and copy these file to tftpboot directory

UEFI Files:

BIOS Files:

Below is the Architecture of the system, these files will be used in DHCP setting:

Step 5 Setting up static IP address

You can set it under GUI

or usingnetplan method to set static IP

cat << EOF > /etc/netplan/00-installer-config.yaml
version: 2
#renderer: networkd
renderer: NetworkManager
dhcp4: no


Networkd: for server

NetworkManager: for desktop

After setting it please apply it using this command:

$sudo netplan apply

after it you can use the try method, please enter after setting, if not after 180 seconds it will return default

$sudo netplan try

Step 6 Setting up DHCP Server and TFTP configure

For DHCP Server, we have two options, one is DHCPD, another one is DNSMASQ. In this section we will need to configure these settings:

  • TFTP location

6. 1 For DHCPD Setting

6.1.1 Assign DHCP Lan interface

Use command $ip a to see your Lan interface name

edit this file $vi /etc/default/tftp-hpa


6.1.2 Set DHCPD configure the setting

cat << EOF > /etc/dhcp/dhcpd.conf
ddns-update-style none;
default-lease-time 43200;
max-lease-time 86400;
option arch code 93 = unsigned integer 16; # RFC4578
subnet netmask {
option routers;
option broadcast-address;
#range dynamic-bootp;
if option arch = 00:07 or option arch = 00:09 {
filename "UEFI/syslinux.efi";
#arm platform
else if option arch = 00:0b {
filename "/UEFI/aarch64/bootaa64.efi";
else {
filename "BIOS/pxelinux.0";

6.1.3 Configure TFTP setting

edit this file $vi /etc/default/tftp-hpa

Add your tftpboot directory in this file

OPTIONS="-l -s /tftpboot"

-c: Allow new files to be created
-s: Change root directory on startup.
-l: Run the server in standalone (listen) mode, rather than run from inetd.

6.1.4 restart services

restart dhcp server

$sudo systemctl restart isc-dhcp-server
$sudo systemctl status isc-dhcp-server

restart tftp server

$ sudo service tftpd-hpa restart
$ sudo systemctl status tftpd-hpa
$service tftpd-hpa status

6. 2For DNSMASQ setting

We don’t need to configure tftp server, DNSMASQ support tftpserver, so we just enter tftp directory and DHCP IP range.

6.2.1 edit /etc/dnsmasq.conf as below:

cat << EOF > /etc/dnsmasq.conf


pxe-prompt="Press F8 for PXE Network boot.", 2
# PXEClient:Arch:00000
pxe-service=X86PC, "Boot BIOS PXE", BIOS/pxelinux
# PXEClient:Arch:00007
pxe-service=BC_EFI, "Boot UEFI PXE-BC", UEFI/syslinux.efi
# PXEClient:Arch:00009
pxe-service=X86-64_EFI, "Boot UEFI PXE-64", UEFI/syslinux.efi

6.2.1 restart dnsmasq

systemctl restart dnsmasq
systemctl status dnsmasq

Step 7 Copy OS images and kernels

For Linux images and kernel:

7.1 mount your OS to mnt to copy kernel file (Ex: ubuntu20.04)

$mount -o loop ubuntu-20.04.3-desktop-amd64.iso /mnt

7.2 copy kernels file of OS

#Ubuntu kernel location
$mkdir –pv /tftpboot/kernels/ubuntu2004
$cp -av /mnt/casper/{initrd,vmlinuz} /tftpboot/kernels/ubuntu20.04
#Fedora/RHEL/Centos kernel location
$cp -av /mnt/isolinux/{initrd.img,vmlinuz} /tftpboot/kernels/centos

$cp -av /usr/lib/syslinux/memdisk /tftpboot/kernels

7.3 copy the entire OS images to the /images directory

$mkdir –pv /tftpboot/images/ubuntu2004
$rsync -av --progress /mnt/* /tftpboot/images/ubuntu2004
$umount /mnt

you can also use cp -av command to copy file, rsynch is another option you can use.

For window images and kernel:

For window we need one more step, we need a kernel and windpe ISO file. If you want to create WINPE.iso images, please refer PART 3.

#copy window kernel
$cp -av /usr/lib/syslinux/memdisk /tftpboot/kernels
#copy window PW iso file inside /tftpboot/kernels
$cp -av windpw.iso /tftpboot/kernels
$mkdir –pv /tftpboot/images/window10
$mount -o loop window10.iso /mnt
$rsync -av --progress /mnt/* /tftpboot/images/window10
$umount /mnt

Step 8 Setup different download protocol server

Please select which download server you want to use. Please noted that iset my images directory in /tftpboot/images, you can also change to any other directory.

8.1 HTTP server

Since we create images under /tftpboot/images/ we can use ln-s method to link to HTTP directory.

ln -s /tftpboot/images /var/www/html/

if you don’t want to put it under/tftpboot/images, then you can copy all the images into /var/www/html/

8.2 VSFTP Server

8.2.1 Create images directory under FTP

$cd /srv/ftp/
$mkdir –pv pub
#change permission
$chmod –R 777 /srv/ftp/pub

8.2.2 configure vstfpd setting

Edit /etc/vsftpd.config, change anonymnous_enable=yes, to enable an anonymous account.

anonymous_enable = yes

8.2.3 copy OS images to FTP directory

For the images part, you can’t use ln-n to link tftpoot/images, it will not work. You can either use the below method:

  • Change your images directory into /srv/ftp/pub/images instead of /tftpboot/images
#create a images directory to store your images
$mkdir –pv /srv/ftp/pub/images
#since we can't use ln-s method, we can use mount method
sudo mount — bind /tftpboot/images /srv/ftp/pub/images/

Note: I am showing many different way of downloading the image, most people will only choose 1 type of way either FTP/http/nfs method.

8.2.4 restart vsftp server

systemctl enable vsftpd
systemctl restart vsftpd
systemctl status vsftpd

8.3 Configure NFS server

8.3.1 edit NFS share settings /etc/exports file to add the images directory path

$vi /etc/exports

8.3.2 make share available

$exportfs -a

8.3.3 restart nfs-server

systemctl restart nfs-kernel-server
systemctl status nfs-kernel-server

8.4 SAMBA server

edit smb configuration /etc/samba/smb.conf

workgroup = WORKGROUP
map to guest = bad user
usershare allow guests = yes
browsable = true
read only = yes
guest ok = yes
path = /tftpboot/images/windows

Note: we set samba without an account, you can test under window \\ it will show as below. You can put all your window OS in this directory

restart SMB server

systemctl restart smbd

I have shown you all 4 methods HTTP, FTP, NFS, and samba method. I just want to show you all the different ways, but you can choose which one you like the most. You don’t have to set all of these protocols.

For Windows you MUST use SAMBA, Linux you can use any other 3 protocols.

Step 9 adding pxe Boot menu option

This step is the most important part, and much more complicated. This part is to create a PXE Boot Menu, which will have different OS options you want to install.

9.1 creating boot menu:

$mkdir -vp /tftpboot/pxelinux.cfg/
$touch /tftpboot/pxelinux.cfg/default

9.2 edit default file

default menu.c32
prompt 0
timeout 300
menu title ########## PXE Boot Menu ##########

For CENTOS Example:

kernel /images/centos7/vmlinuz
append initrd=/kernels/centos7/initrd.img \ method= ip=dhcp
label CentOS 7x64 http 2021
MENU LABEL CentOS 7 x64 http
kernel /images/centos7/vmlinuz
append initrd=/kernels/centos7/initrd.img method= ip=dhcp
label install ^Install centos 7
menu label ^Install centos 7 NFS
kernel /kernels/centos7/vmlinuz keymap=us lang=en_US ip=dhcp method=nfs:
append initrd=/images/centos7/initrd.img
label CentOS 8.5x64 ftp 2021
MENU LABEL AlmaLinux-8.5 x64 FTP [ok]
kernel /images/AlmaLinux-8.5/vmlinuz
append initrd=/images/AlmaLinux-8.5/initrd.img \ method= ip=dhcp
title [Leopard_uEFI] CentOS 6.4 x64 for guifullap ks
kernel /kernel/centos6.4/vmlinuz ip=dhcp #ks=
initrd /kernel/centos6.4/initrd.img

For Automation install Centos/RHEL/Fedora uses kickstart, in CentOS_8.x version is unable to install this package. It will automatically generate after first installation. Please refer to more information in the next step.

Note: Centos8.5 images have a problem, and CENTOS is EOF after 2021, it’s migrating to Rocky/Alma/OEL/Springdale.

For Ubuntu Example:

HTTP and FTP we can use live images such as .iso files, and NFS we can use the images in a directory.

label install1
menu label ^Install Ubuntu NFS
kernel /kernels/ubuntu2004/vmlinuz
append initrd=/kernels/ubuntu2004/initrd \ nfsroot= ro netboot=nfs boot=casper ip=dhcp ---
label UBUNTU test
MENU LABEL UBUNTU 2004 test x64 http ISO file
kernel kernel_boot/ubuntu/ubuntu20.04/vmlinuz
initrd= kernel_boot/ubuntu/ubuntu20.04/initrd
append ip=dhcp vga=normal method=
label install
menu label ^Install Ubuntu 20.04 LTS Desktop try and install
kernel ubuntu2004/vmlinuz
initrd ubuntu2004/initrd
append ip=dhcp netboot=nfs \ nfsroot= boot=casper auto=true root=/dev/ram0 maybe-ubiquity
label install
menu label ^Install Ubuntu 20.04 LTS Desktop automatic install
kernel ubuntu2004/vmlinuz
initrd ubuntu2004/initrd
append ip=dhcp netboot=nfs automatic-ubiquity boot=casper nfsroot= auto=true url= splash toram ---

For the ubuntu setting, if you don’t include below this parameter, you have to manually press the install application.

automatic-ubiquity ==>will automatic execute install file

maybe-ubiquity ==>will occur try and install option like usb drive

For Automation install, UBUNTU/Debian distribution it’s called pressed file. In the next step more description.

For Window Example:

LABEL      winpe
MENU LABEL Boot Windows PE from network
KERNEL /kernels/memdisk
INITRD /images/winpe_amd64.iso
APPEND iso raw

Go to part3 to see how to create winPE, and please modify the startnet.cmd as below

net use z: /delete
net use z: \\\windows
cd window10

Step 8 Automation unattended installation (options)

So unattended installation means it will run a file and automatic install for you, this is when you have many clients and you want to automatically install by itself.

8.1 go to HTTP server (/var/www/html/) or FTP server(/srv/ftp/pub) and create a file just like below, or you can customize it.

For ubuntu: local-sources.seed

# ubiquity ubiquity/summary
# Choices: Dialog, Readline, Gnome, Kde, Editor, Noninteractive
d-i debconf debconf/frontend select Noninteractive
### Localization
d-i debian-installer/locale string en_GB
### Keyboard selection
d-i console-setup/ask_detect boolean false
d-i console-setup/layout select us
d-i console-setup/variant select us
ubiquity languagechooser/language-name select English (US)
ubiquity countrychooser/shortlist select FI
ubiquity keyboard-configuration/layoutcode select fi
ubiquity keyboard-configuration/modelcode select pc105
ubiquity localechooser/supported-locales multiselect en_US.UTF8
ubiquity console-keymaps-at/keymap select fi
ubiquity console-keymaps-at/variant select fi
d-i kbd-chooser/method select British English
### Network
d-i netcfg/get_hostname string de-vm
d-i netcfg/get_domain string unassigned-domain
### Clock and time zone setup
d-i time/zone string Europe/Helsinki
d-i clock-setup/utc-auto boolean true
d-i clock-setup/utc boolean true
### Partitioning
d-i partman-auto/method string regular
d-i partman-auto/choose_recipe select atomic
d-i partman-partitioning/confirm_write_new_label boolean true
d-i partman/choose_partition select finish
d-i partman/confirm boolean true
d-i partman/confirm_nooverwrite boolean true
### Account setup
d-i passwd/user-fullname string de
d-i passwd/username string test
d-i passwd/user-password password 123456
d-i passwd/user-password-again password 123456
d-i passwd/auto-login boolean true
d-i user-setup/encrypt-home boolean false
d-i user-setup/allow-password-weak boolean true
### Package installation
# Enable
d-i apt-setup/extras boolean true
# Install the Ubuntu desktop.
tasksel tasksel/first multiselect ubuntu-desktop,standard
choose-mirror-bin mirror/http/proxy string
#For the update
d-i pkgsel/update-policy select none
d-i pkgsel/install-language-support boolean false
### Bootloader
d-i grub-installer/only_debian boolean true
d-i grub-installer/with_other_os boolean true
### Reboot after preseeding
d-i finish-install/reboot_in_progress note
ubiquity ubiquity/reboot boolean true
#ubiquity ubiquity/poweroff boolean true
#### Advanced options
#in-target /bin/sh -c 'echo "cp /etc/rc.local.bak /etc/rc.local" >> /etc/rc.local' ;\
#in-target sh -c 'wget -O /home/pixellab/ #' ;\
#in-target sh -c 'wget -O /etc/apt/sources.list #'

For Centos: guifullap.ks

# Kickstart file automatically generated by anaconda.#Install OS instead of upgrade
#Use network installation
# Network information
network --bootproto=dhcp --device=eno16777736 --onboot=off --ipv6=auto
network --hostname=localhost.localdomain
#network --onboot yes --device eth0 --bootproto dhcp --noipv6
#network --onboot yes --device eth1 --bootproto dhcp --noipv6
#nfs --server= --dir=/install/nfs_share/centos6.4
url --url=""
#System language
lang en_US.UTF-8
#System keyboard
keyboard us
lang en_US.UTF-8
#Root password
rootpw --iscrypted $6$xY2tioS3mrtkbBsv$HQGUhCW.jjnMwTOFz1XM/1OjsrP3BdE4sJZUDd1Zr.iNhqkjQJj4.gkn70aMwYsouY4mpbBrW.DRBeXQ9krap0
#Firewall configuration
#firewall --service=ssh
firewall –disabled
#SELinux configuration
selinux --enforcing
#Run the Setup Agent on first boot
firstboot --disable
#System authorization information
authconfig --enableshadow --passalgo=sha512
#System timezone
timezone --utc America/Danmarkshavn
#System bootloader configuration
bootloader --append=" crashkernel=auto" --location=mbr --boot-drive=sda
autopart --type=lvm
#bootloader --location=partition --driveorder=sda --append="crashkernel=auto console=ttyS1,57600"
#Partition clearing informatio
clearpart --all –initlabel
#set boot 200mb
part /boot --fstype=ext4 --size=200 --ondisk=sda
part swap --size=2000 --ondisk=sda
part / --fstype=ext4 --grow --size=1 --ondisk=sda
# autopart
#Reboot after installation
reboot –eject
service NetworkManager stop
chkconfig NetworkManager off
service network restart
#wget -r -nH
#tar -zxvf /V10_20141030.tar.gz
wget -r -nH
tar -zxvf /other_file_pxeramdisk.tar.gz

After you have these files, then got back to pxe boot menu and add the file into the menu like this:

#or ubuntu

There are many examples on the web, you can set many more examples.

Part 2 Setup PXE under Window

If you are Lazy to learn using Ubuntu, you can also use the window to set up, but the disadvantage is the window is unable to detect which architecture your client is bios/uefi/arm platform.

We will need third-party tools, both of them are free. There a1re many other tools you can use, but I prefer using this tool.

I will only show you BIOS/Legacy method.

DHCP&TFTP Server:tftp64

HTTP server: HFS

  1. Please download the above tool
C:\>mkdir tftpboot\images\pxelinux.cfg

3. Download syslinux file on the official site

copy the file in the directory

syslinux-6.03\bios\com32\chain\chain.c32 c:\tftpboot \
syslinux-6.03\bios\com32\mboot\mboot.c32 c:\tftpboot \
syslinux-6.03\bios\com32\menu\menu.c32 c:\tftpboot \
syslinux-6.03\bios\memdisk\memdisk c::\tftpboot \
syslinux-6.03\bios\core\pxelinux.0 c:\tftpboot \
syslinux-6.03\bios\com32\elflink\ldlinux.c32 c:\tftpboot \
syslinux-6.03\bios\com32\libutil\libutil.c32 c:\tftpboot \
syslinux-6.03\bios\com32\menu\vesamenu.c32 c:\tftpboot \
syslinux-6.03\bios\com32\lib\libcom32.c32 c:\tftpboot \

it will look like this:

4. set the static IP address

5. open tftp64.exe tool

assign TFTP location

setup dhcp server as below

6. sharing images directory for samba for window OS

7. Setup http server, open HFS.

8. disable the firewall

9. setup pxe boot menu (C:\tftpboot\pxelinux.cfg\default )

please refer for creating winpe iso file. If you want to install Window this step is a must

default menu.c32
prompt 0
timeout 300
label CentOS 7x64 html 2021
kernel /images/centos7/isolinux/vmlinuz
append initrd=/images/centos7/isolinux/initrd.img \ method= ip=dhcp
LABEL winpe
MENU LABEL Boot Windows PE from network
KERNEL /memdisk
INITRD /winpe_amd64.iso
APPEND iso raw

I put my winpe_amd64.iso and memdisk under /tftpboot directory

Part 3 Creating Window PE images for installing window OS

please refer to more information on how to create WinPE on Microsoft official site

  1. download window ADK and install it

2. go to adk directory

C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Windows Preinstallation Environment

3. copy windpe image to c:\ using below command

copype.cmd amd64 C:\winpe_amd64

if it’s not working please modify the script(copype.cmd) to the correct location:

set WinPERoot=C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Windows Preinstallation Environment
Set OSCDImgRoot=C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Deployment Tools\amd64\Oscdimg
set FWFILESROOT=%OSCDImgRoot%\..\..\%WINPE_ARCH%\Oscdimg
set DEST=%~2
set WIMSOURCEPATH=%SOURCE%\en-us\winpe.wim

4. after running success under c:\ drive you will see winpe_amd64 directory.

5. delete this file C:\winpe_amd64\media\Boot\bootfix.bin

if you don’t delete it will occur this "press any key to boot from CD or DVD”. Since we are running automation we shouldn’t include this.

6. add startnet.cmd script for auto network mount

net use z: /delete
net use z: \\\images /user:test\login ""
cd window10

My account is test, and no password, so I will use this /user:test\login “”

7. drag the script (startnet.cmd) inside boot.wim

  • please download 7-zip to open boot.wim file

8. build winpe iso file

# go to adk drirectory 
cd C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Windows Preinstallation Environment
#create iso image
MakeWinPEMedia /iso C:\WinPE_amd64 c:\WinPE_amd64\winpe_amd64.iso

9. put your winpe.iso file into tftpboot directory

10. Test it select your last option


So wrapping up to all of the settings, we need a DHCP to assign all IP addresses to each client to boot from pxe(you can set under bios in boot option, or press boot option). After DHCP is successful, it will use TFTP to download related files and show the pxe menu, you can select which OS you want to install.

You can use many ways to download OS, the most common protocol to transfer files is HTTP, NFS, and FTP. I have written a bash script, you can use it to help you automate all the settings.

I have written an automation script to auto-setup as below.

Flow of PXE Server

Topology of PXE Server

Let me give you a quick procedure:

  1. Download package DHCP, TFTP server

Note Any of these steps you can try in any order, but TFTP directory must be created first.

You can just use one type of download service, which you prefer. I just want to show you how to configure with different services. But for Windows, you have no other option than Samba services.

I hope this article is able to help you. I know it’s a lot, but it’s quite useful, you can learn how to set up PXE server, or learn how to set up FTP, HTTP, NFS, and samba these remote transferring tools.



Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store

I self study technology, and likes to exchange knowledge with people. I try writing complex tech blog into simple and various ways for people to understand.