Setup PXE Server Ubuntu
In this tutorial, I will guide you through the process of creating a PXE server on an Ubuntu Host. This guide also includes complete setup instructions for the PXE client and DHCP server. I will also guide you through an effective storage/deployment method so that you may quickly deploy identical PXE images.
Install Server Dependencies ∞
- Update & clean current packages, then install the packages that are required for this tutorial.
sudo apt-get update -y && sudo apt-get dist-upgrade -y && sudo apt-get install -y isc-dhcp-server tftpd-hpa syslinux \ syslinux nfs-kernel-server initramfs-tools \ debootstrap syslinux
Setup NFS root ∞
-
Create desired directory structure. In my configuration, the pxe directory is in the root and I store all of my pxe images in pxe-boot/images/*.
sudo mkdir -p /pxe-boot/{pxelinux.cfg,images/{base-cluster-image}}
-
Copy the PXE boot file to the PXE root.
sudo cp /usr/lib/syslinux/pxelinux.0 /pxe-boot
-
Share new directory via NFS
sudo nano /etc/exports
/pxe-boot 192.168.69.100(rw,no_root_squash,async,insecure) #< You will want to modify the IP
-
Sync exports
sudo exportfs -rv
-
Download base system via debootstrap to
pxe-boot/images/base-cluster-image
. Add desired packages to the include parameter. This will take a while..you can continue with the other sections in another screen session if you want to save time. You can also change the arch or distribution (quantal) to fit your desired setup.sudo debootstrap --variant=minbase --include=procps,screen,passwd,less,nano,bash,nfs-common \ --arch amd64 quantal /pxe-boot/images/base-cluster-image http://archive.ubuntu.com/ubuntu
-
Chroot to the image directory.
sudo chroot /pxe-boot/images/base-cluster-image/
-
Setup the hostname (replace
base-cluster-image
with your desired hostname)echo base-cluster-image > /etc/hostname
-
Setup the hosts file.
nano /etc/hosts
127.0.0.1 localhost 127.0.1.1 base-cluster-image #< (replace `base-cluster-image` with your desired hostname) # The following lines are desirable for IPv6 capable hosts ::1 ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters
-
Setup the fstab. It should look similar to the below (adding other mounts if necessary)
nano /etc/fstab
/proc /proc proc defaults 0 0 /sys /sys sysfs defaults 0 0 /dev/nfs / nfs defaults 1 1
-
Setup interfaces (client already discovered DHCP during boot process, so the interface needs to be set to manual).
nano /etc/network/interfaces`
# Loopback auto lo iface lo inet loopback # Don't discover DHCP iface eth0 inet manual
-
Add network adapter names to
/etc/initramfs-tools/modules
(such as ar8121, r8169, etc. – one per line) -
Mount
/proc
.mount /proc
-
Set the root password.
passwd Enter new UNIX password: Retype new UNIX password:
-
Generate/update locale settings.
locale-gen en_US.UTF-8 dpkg-reconfigure locales
-
Edit sources
nano /etc/apt/sources.list
and add:deb http://archive.ubuntu.com/ubuntu quantal main restricted universe multiverse deb http://archive.ubuntu.com/ubuntu quantal-updates main restricted universe multiverse deb http://archive.ubuntu.com/ubuntu quantal-security main restricted universe multiverse
- Update app cache
apt-get update
-
Install system kernel
apt-get install -y linux-headers-generic apt-get install -y linux-image-generic
-
Link kernel to a better spot and set permissions. This will allow you to upgrade kernels without changing configuration files.
ln -s /boot/vmlinuz-3.5.0-21-generic /vmlinuz #< Substitute for your kernel version ln -s /boot/initrd.img-3.5.0-21-generic /initrd.img #< Substitute for your kernel version chmod 777 -R /vmlinuz /initrd.img /boot/ #< /boot could probably be left out of this..
-
Edit initramfs.conf
nano /etc/initramfs-tools/initramfs.conf
and make the following options matchMODULES = netboot BOOT = nfs
-
Update initramfs with new params
update-initramfs -u
-
Install any source packages your image needs (or any you did not have in the debootstrap –include)
- Exit chroot
umount /proc exit
TFTP ∞
- Open the config file.
sudo nano /etc/default/tftpd-hpa
-
Make it look like the below (replace TFTP_DIRECTORY with PXE root)
# /etc/default/tftpd-hpa RUN_DAEMON="yes" OPTIONS="--secure" TFTP_ADDRESS="0.0.0.0:69" TFTP_USERNAME="tftp" TFTP_DIRECTORY="/pxe-boot/"
-
Create default boot config
DEFAULT images/base-cluster-image/vmlinuz APPEND boot=nfs root=/dev/nfs initrd=images/base-cluster-image/initrd.img nfsroot=192.168.69.100:/pxe-boot/images/base-cluster-image,rw ip=dhcp rw
-
Permissions
sudo chmod 777 /pxe-boot
-
Start tftp server
sudo /etc/init.d/tftpd-hpa start
- Verify server is listening
dlasley@server:/$ ss -apu | grep tftp UNCONN 0 0 *:tftp *:*
DHCPD ∞
Note that the below configurations are redundant, and should be chosen depending on your environment. Windows users would use the GUI.
Linux ∞
-
Edit config
sudo nano /etc/default/isc-dhcp-server
to listen on specific interfaces (space separate). Configure everything else to your likingINTERFACES="bond0"
-
Edit
dhcpd.conf
sudo nano /etc/dhcp/dhcpd.conf
. Mine is below (minus unrelated static clients), edit for your config (IPs, hostnames, MACs, etc.)ddns-update-style none; option subnet-mask 255.255.255.0; option broadcast-address 192.168.69.255; option routers 192.168.69.254; option domain-name-servers 192.168.69.110, 192.168.69.100, 192.168.69.254; option domain-name "dlasley.net"; default-lease-time 86400; max-lease-time 604800; #option time-offset -18000; authoritative; log-facility local7; allow booting; allow bootp; # Reserve >100 for static subnet 192.168.69.0 netmask 255.255.255.0 { range 192.168.69.1 192.168.69.99; get-lease-hostnames on; use-host-decl-names on; next-server 192.168.69.100; filename "/pxe-boot/pxelinux.0"; } host cluster_1 { hardware ethernet 00:21:97:32:D6:B5; fixed-address 192.168.69.103; #filename "/pxe-boot/pxelinux.0"; #< Can also define on a #next-server 192.168.69.104; # client-by-client basis }
-
Restart DHCP server
sudo service isc-dhcp-server restart
Ubiquiti EdgeRouter Lite ∞
- Login to router via ssh, enter configure more
configure
- Add
bootfile-server
to DHCP configedit service dhcp-server shared-network-name dlasley.net subnet 192.168.69.0/24 set bootfile-server 192.168.69.100
- Add
filename
options to DHCP config. Make sure to encapsulate the file path in"
set subnet-parameters "filename "/pxe-boot/pxelinux.0";"
- Commit and save
commit save
Storing/Deploying Images (Optional) ∞
-
Compress base image for storage
tar cvpjf base-cluster-image.tar.bz2 ./base-cluster-image rm -Rf ./base-cluster-image
-
Extract base image
tar xvpfj ./base-cluster-image.tar.bz2 -C ./
-
Rename folder
mv ./base-cluster-image ./cluster-0
-
Setup the hostname (replace
base-cluster-image
with your hostname)echo cluster-0 > ./cluster-0/etc/hostname
- Setup hosts file
nano /etc/hosts
(note 127.0.1.1 is now cluster-0 instead of base-cluster-image)127.0.0.1 localhost 127.0.1.1 cluster-0 # The following lines are desirable for IPv6 capable hosts ::1 ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters
Booting (On The Client) ∞
-
Setup BIOS to boot from NIC
-
Client should get net config from DHCP server, download pxe file from TFTP server, then begin booting
-
If permissions issues arise, it may be acls. Try:
sudo setfacl -bR /pxe-boot/
-
Add Swap Space (Optional) ∞
You can add swap space using either a network share, or an external device (flash drive)
Network Share ∞
This will create swap space on the network share
- On the booted client
sudo apt-get install dphys-swapfile #< Install, sets up swap at `/var/swap` that is 2x current RAM (or 2048MB per default config) sudo losetup /dev/loop0 /var/swap #< Set up and control loop devices (swap) sudo swapon /dev/loop0 #< Enable for paging and swapping
- Run top to verify that you have swap space.
KiB Swap: 2097148 total, 0 used, 2097148 free, 1462084 cached
-
Make the change permanent.
sudo nano /etc/fstab
/dev/loop0 none swap sw 0 0 #< Add this
External Device ∞
This will create swap space on an external device
- Umount the drive
sudo umount /media/mounted_swap
- Find the device with fdisk. For the purposes of this article, I will be using /dev/sdc1
sudo fdisk -l
- Write the swap file to the device
sudo mkswap /dev/sdc1
- Activate the swap device.
sudo swapon –p 32767 /dev/sdc1
- Run top to verify that you have swap space.
KiB Swap: 2097148 total, 0 used, 2097148 free, 1462084 cached
- Make the change permanent.
sudo nano /etc/fstab
/dev/sdc1 none swap sw 0 0 #< Add this
Credits ∞
- PXEInstallMultiDistro
- DisklessUbuntuHowTo
- PXEInstallServer
- OnNFSDrive
- PXE Linux
- Various manpages ;)
Hi,
Can this be used for windows client?
I mean the server is ubuntu and the clients are windows XP..
Thanks in advance :)
This tutorial is compatible with Linux clients only. I’m not exactly sure of a way to boot a Windows client via PXE without a Windows server.
Hi ,
I am doing diskless booting . i can’t able to mount the file system which we gave in default file in pxelinux.cfg folder.
Let me eloborate my question
I am having two computers . one acts like server and other acts like client. I am having linux kernel image in server. and i configured my dhcp.conf file in server as follows
# DHCP Server Configuration file.
# see /usr/share/doc/dhcp*/dhcpd.conf.sample
allow booting;
allow bootp;
use-host-decl-names on;
ddns-update-style interim;
ignore client-updates;
next-server 172.16.6.238;
subnet 172.16.6.0 netmask 255.255.255.0 {
option subnet-mask 255.255.255.0;
range dynamic-bootp 172.16.6.10 172.16.6.254;
default-lease-time 21600;
max-lease-time 43200;
option domain-name-servers 127.0.0.1;
option routers 172.16.6.1;
filename “pxelinux.0”;
}
host pxe_client {
hardware ethernet 7client mac address; #client mac address
fixed-address 172.16.6.237;
}
group {
next-server 172.16.6.238; # our Server
host tftpclient {
filename “pxelinux.0”;
}
}
my client is getting correct ip-address
It able to load the kernel which is present in server
problem is client can’t able to mount the filesystem while booting , where the filesystem is present in server . my kernel boot arguments are
default openwrt
label openwrt
kernel openwrt-x86-generic-vmlinuz
append boot=nfs root=/dev/nfs nfsroot=172.16.6.237:/nfsroot ip=dhcp rw
my client is not mounting the file system while booting
Please give me required suggestions
You are missing the initrd declaration in the kernel boot arguments. Initrd loads the root file system into memory during the Kernel boot process; not having this is likely causing the issue. Try adding the initrd declaration; and if that doesn’t work, what error message are you receiving from the client?
Hiya, im pretty much a newbie tro ubuntu, but tried setting up this server by following all the instructions,
i executed
Download base system via debootstrap to pxe-boot/images/base-cluster-image. Add desired packages to the include parameter. This will take a while..you can continue with the other sections in another screen session if you want to save time. You can also change the arch or distribution (quantal) to fit your desired setup.
sudo debootstrap –variant=minbase –include=procps,screen,passwd,less,nano,bash,nfs-common \
–arch amd64 quantal /pxe-boot/images/base-cluster-image http://archive.ubuntu.com/ubuntu
and then tried sudo chroot /pxe-boot/images/base-cluster-image/
but now i get the error
chroot: failed to run command `/bin/bash’: Exec format error
what am i doin wrong? plz help and thnx in advance
Hi, and thanks for reading my blog! There could be a few possibilities here, but the error basically means that your jail doesn’t have a shell or some other required library. My immediate thought is that the host server is 32-bit and the chroot is 64-bit. What is the output of `uname -a` on the server?
Hi, I’ve read your blog and it did great help for me. But I’ve met something weird, stuck me at the boot process.
It seems happened at the nfs mount, my whole screen filled with
Begin: Retrying nfs mount ... Begin: Running /scripts/nfs-premount ... done.
mount call failed - server replied: No such file or directory.
Begin: Retrying nfs mount ... Begin: Running /scripts/nfs-premount ... done.
mount call failed - server replied: No such file or directory.
Begin: Retrying nfs mount ... Begin: Running /scripts/nfs-premount ... done.
mount call failed - server replied: No such file or directory.
Begin: Retrying nfs mount ... Begin: Running /scripts/nfs-premount ... done.
mount call failed - server replied: No such file or directory.
Begin: Retrying nfs mount ... Begin: Running /scripts/nfs-premount ... done.
mount call failed - server replied: No such file or directory.
Begin: Retrying nfs mount ... Begin: Running /scripts/nfs-premount ... done.
mount call failed - server replied: No such file or directory.
Begin: Retrying nfs mount ... Begin: Running /scripts/nfs-premount ... done.
mount call failed - server replied: No such file or directory.
I’ve do some google but it doesn’t help, do you have any ideas about how to fix it?
A~ what a shame, according to my nfs server log, I’ve found that I typed in the wrong path in the configuration file. It works now. Thank you.
I’m happy to hear that you got it up and running. This is a tricky process, no doubt ;)
Dave – great tutorial, thanks for the writeup. I have an EdgeRouter Lite; is the Linux DHCP is necessary since I am using the ERL as my DHCP server? I guess I am confused with having two DHCP servers on the network and how to de-conflict, or am I missing something?
Nope – no need for two DHCPs, the ERL is perfectly fine. I should have specified that the DHCP section is an either/or – updating now!
Awesome, thanks!