Home VPN WorkPlace Web Sites/Apps Small Business Other Apps Contact Guides

PXE Booting Ubuntu 20.04 (Example)

This is an example of setting up persistent network installs of Ubuntu 20.04 (Not deploying installs over the network.)

Date Published: 2020/05/21

Resources:
https://help.ubuntu.com/community/DisklessUbuntuHowto
https://wiki.debian.org/PXEBootInstall

Environment

pfSense (DHCP Server)(192.168.1.1)
Ubuntu 20.04 (Data Host Server)(192.168.1.2)
Ubuntu 20.04 (XPE Client)(192.168.1.50)(pxe1)

DHCP IP Reservation already assigned for both Host and Client machines.

Server Setup

sudo apt install tftpd-hpa syslinux pxelinux nfs-kernel-server initramfs-tools -y

Configure TFTP

sudo mkdir /pxe
sudo mkdir /pxe/tftproot
sudo nano /etc/default/tftpd-hpa
File Content
TFTP_USERNAME="tftp" TFTP_DIRECTORY="/pxe/tftproot" TFTP_ADDRESS=":69" TFTP_OPTIONS="--secure"
Create TFTP file structure
sudo mkdir /pxe/tftproot/pxe1
sudo mkdir -p /pxe/tftproot/pxe1/pxelinux.cfg
sudo cp /usr/lib/PXELINUX/pxelinux.0 /pxe/tftproot/pxe1
sudo mkdir -p /pxe/tftproot/pxe1/boot
sudo cp -r /usr/lib/syslinux/modules/bios /pxe/tftproot/pxe1/boot/isolinux
Identify the vmlinuz version...
uname -r
Now edit /pxe/tftproot/pxe1/pxelinux.cfg/default
sudo nano /pxe/tftproot/pxe1/pxelinux.cfg/default
Content should be:
DEFAULT linux LABEL linux KERNEL vmlinuz-[version] APPEND root=/dev/nfs initrd=initrd.img-[version] nfsroot=192.168.1.2:/pxe/nfsroot/pxe1 ip=dhcp rw
Replace [version] with the results from 'uname -r'
Note: pxe1 can be replaced with identity of install.
Set folder permissions
sudo chmod -R 777 /pxe/tftproot

Setup NFS

sudo mkdir /pxe/nfsroot
sudo mkdir /pxe/nfsroot/pxe1
sudo nano /etc/exports
Content for /etc/exports
/pxe/nfsroot/pxe1 192.168.1.50(rw,no_root_squash,async,insecure,no_subtree_check) /pxe/tftproot/pxe1 192.168.1.50(rw,no_root_squash,async,insecure,no_subtree_check)
Apply Exports
sudo exportfs -rv

PXE Client Setup

First install Ubuntu and connect to the network. Then we will copy the OS to the Host server for future booting.
First lets prepare the kernel files needed for later.
sudo mkdir /pxefiles
sudo cp /boot/vmlinuz-`uname -r` /pxefiles
Now we will update /etc/initramfs-tools/initramfs.conf
sudo nano /etc/initramfs-tools/initramfs.conf
# # MODULES: [ most | netboot | dep | list ] # # most - Add all framebuffer, acpi, filesystem, and harddrive drivers. # # dep - Try and guess which modules to load. # # netboot - Add the base modules, network modules, but skip block devices. # # list - Only include modules from the 'additional modules' list # MODULES=netboot
sudo mkinitramfs -o /pxefiles/initrd.img-`uname -r`
Now to copy the files to the host server.
First install support for NFS:
sudo apt install nfs-common -y
Now to setup the mount and copy the OS.
sudo mount -t nfs -onolock 192.168.1.2:/pxe/nfsroot/pxe1 /mnt
sudo cp -axv /. /mnt/.
sudo cp -axv /dev/. /mnt/dev/.
Now to revert the client OS so it can still be booted from the hard drive if needed.
sudo nano /etc/initramfs-tools/initramfs.conf
# # MODULES: [ most | netboot | dep | list ] # # most - Add all framebuffer, acpi, filesystem, and harddrive drivers. # # dep - Try and guess which modules to load. # # netboot - Add the base modules, network modules, but skip block devices. # # list - Only include modules from the 'additional modules' list # MODULES=most

Now back to the Host Server

sudo cp -axv /pxe/nfsroot/pxe1/pxefiles/. /pxe/tftproot/pxe1
Now to comment out the local drives
sudo nano /pxe/nfsroot/pxe1/etc/fstab
Comment out /dev/disk... & /swap.img, then add /pxeboot for easy kernel updates:
# /etc/fstab: static file system information. # # Use 'blkid' to print the universally unique identifier for a # device; this may be used with UUID= as a more robust way to name devices # that works even if disks are added and removed. See fstab(5). # # / was on /dev/sda2 during curtin installation #/dev/disk/by-uuid/bd2f327a-7d4b-4072-9113-995acbc4b935 / ext4 defaults 0 0 #/swap.img none swap sw 0 0 192.168.1.2:/pxe/tftproot/pxe1 /pxeboot nfs _netdev,auto,rw,exec,hard,tcp,timeo=600 0 0
Now to start/restart the TFTP Service
sudo systemctl restart tftpd-hpa

Now to setup the DHCP Server (pfSense in my case)

Navigate to Services > DHCP Server
Header should be Services / DHCP / LAN
Scroll down to Other Options and locate Network Booting and click Display Advanced,
Check Enables network booting then enter the Host Server IP (192.168.1.2) into Next Server and click Save.

The PXE Client should already have a DHCP Static Mapping (192.168.1.50) to reserve the IP address. Edit that mapping.

Enter /pxe1/pxelinux.0 in the Netboot filename field.
Scroll down to TFTP Servers and click Display Advanced, then enter Host Server IP into the TFTP Server field.

After First Boot of PXE Client

Remove applications that are no longer needed (PXE Client Only, Before First Update)

Remove Grub
sudo apt purge grub-pc
Remove Cryptsetup
sudo apt remove cryptsetup
Remove Software Raid MDADM
sudo apt remove mdadm

Updating Kernel on Client

If you receive an Error about updating the kernel after sudo apt upgrade then execute
sudo mkinitramfs -o /pxeboot/initrd.img-`uname -r` && sudo cp --preserve=timestamps -v /boot/vmlinuz-* /pxeboot && sudo chmod -R 777 /pxeboot
Note the most recent version, Ex: vmlinux-x.x.x-generic
Now update the boot config
nano /pxeboot/pxelinux.cfg/default
DEFAULT linux LABEL linux KERNEL vmlinuz-[version] APPEND root=/dev/nfs initrd=initrd.img-[version] nfsroot=192.168.1.2:/pxe/nfsroot/pxe1 ip=dhcp rw
Lastly it is very important to set the permissions on the pxeboot folder.
Now Reboot
sudo reboot
You will notice all is now up-to-date.

Notes:

I had to reboot the Host Server for everything to work.

For a live system log:

tail -f /var/log/syslog

I had an issue with LXD failing during boot on the PXE Client, as I wasn't using it, I removed it.

sudo snap remove lxd

To setup additional installs, repeat these steps and replace pxe1 with a shortname for each other install in both tftproot and nfsroot. Be sure to update the IP Address as well.

You can also do the client setup once and copy it to a new folder:

sudo cp -axv /pxe/tftproot/pxe1/. /pxe/tftproot/pxe2
sudo cp -axv /pxe/nfsroot/pxe1/. /pxe/nfsroot/pxe2
Enter /pxe2/pxelinux.0 in the Netboot filename field.
sudo nano /etc/exports
/pxe/nfsroot/pxe1 192.168.1.50(rw,no_root_squash,async,insecure,no_subtree_check) /pxe/tftproot/pxe1 192.168.1.50(rw,no_root_squash,async,insecure,no_subtree_check) /pxe/nfsroot/pxe2 192.168.1.51(rw,no_root_squash,async,insecure,no_subtree_check) /pxe/tftproot/pxe2 192.168.1.51(rw,no_root_squash,async,insecure,no_subtree_check)
sudo exportfs -rv
sudo nano /pxe/tftproot/pxe2/pxelinux.cfg/default
DEFAULT linux LABEL linux KERNEL vmlinuz-[version] APPEND root=/dev/nfs initrd=initrd.img-[version] nfsroot=192.168.1.2:/pxe/nfsroot/pxe2 ip=dhcp rw

Hope this helps someone