There are many tutorials on the internet that tell you how to setup a PXE Boot server with PXELINUX. There are however other options to replace PXELINUX like GRUB2 and iPXE. In this tutorial, I'm going to teach you how to setup a PXE Boot Environment with GRUB2, and later add menu entries to boot many popular OSes.
Notice: I'm not going to repeat the part where you setup the DHCP and TFTP server. Such section in other tutorials still applies to this scenario.
think the GRUB2 image as the same as PXELINUX's pxelinux.0 file. Your DHCP server must point to it, and it must be available on your TFTP server. Instead of shoving a blob down your throat and telling you that it just works, I'm going to walk you through the process of making one yourself by using an readily available linux installation.
You will need one of the following to build a GRUB2 boot image:
- A working linux distribution that has the grub package installed. You don't need to use GRUB2 to boot the linux system.
- use WSL on Windows to have a linux subsystem.
- other distributions that has the grub package.
- If you really wanna go the long way, download GRUB2's source code from GNU, and compile it yourself.
The program we need is grub-mkimage. It is more flexible than grub-mknetdir, and I'm using it to explain the details.
angle brackets indicates names that you can replace yourself.
grub-mkimage -O <target> -o <output file name> -p <prefix directory> <list of modules separated by space>
Explanation:
- The
<target>
part chooses which boot system you want the image for. You have many choices including BIOS, UEFI32 and UEFI64. - Choose whatever you want of the
<output file name>
. - the
<prefix directory>
is the directory relative to your TFTP root to put yourgrub.cfg
file. For example, if we set it to/grub
and our TFTP root is/srv/tftp
, then yourgrub.cfg
file must be at/srv/tftp/grub/grub.cfg
. - modules are not included by default. You can add them at
<list of modules separated by space>
.
-
First, run the following command to build the image:
grub-mkimage -O i386-pc-pxe -o <output file name> -p /grub tftp pxe normal ls echo minicmd halt reboot http linux bsd zfs
<target>
must bei386-pc-pxe
for BIOS images.tftp
pxe
andnormal
are REQUIRED modules for BIOS boot.- other useful modules include:
ls
,echo
,minicmd
: provides basic commands for debug.halt
,reboot
: so that you can easily reboot your system from GRUB2.http
: MUST have if you want to download kernel/ram disks from http servers instead of tftp servers.linux
: REQUIRED to boot linux systems.bsd
: REQUIRED to boot BSD-derived systems, for example OpenBSD, NetBSD and FreeBSD.zfs
: OpenBSD and NetBSD's installation kernel need this module to load. Otherwise, it will produce aninvalid a.out header
error.
-
Second, upload the created image to your TFTP server. Again, I'm not shoving a fixed method down your throat. There are many to choose from, including
scp
andrsync
, go check their respective manual.
This is the more involving part. Usually one does not write grub.cfg themselves, but a grub file to be used by grub-mkconfig
autogeneration utility. However, we don't have that luxury here. We need to do it by ourselves. The syntax is kinda documented on their website, but it's a giant page. People who need this guide won't have time to read it lol. So I'm going to do some small explanations here. The completed grub.cfg file is in this gist too, so you can just grab it if you need.
This section is the global settings. Usually we set global variables like root
default
and timeout
here.
set default=0
set timeout=60
set root=(http,$net_default_server:8080)
The first two are self-explanatory. The third line needs a little explanation:
root
is a special variable. It will be appended to all paths you specified later.- In GRUB2, the syntax to denote a device is
(device, partition)
. For example, the 5th partition on the first disk is(hd0,5)
. - With the
http
module included at build, grub can create an http partition named(http, <server address>:<http port>)
. you can use any ip addresses or host names (www.example.com
). I have not tested ipv6 addresses yet. You can also use any port, not limited to the default80
port. Here, I use the port8080
because my HTTP server is setup so. - With the
tftp
module, grub can also create an tftp partition named(tftp, <server ip address>)
. Now the server address must be IP, and no port is allowed. - I'm using the variable
$net_default_server
. It is the IP address of your DHCP server. I have my HTTP server on my router, thus they share the same IP and I can dynamically configure it without hardcoding any address. You can have a domain name bound to your HTTP server so you don't have to hardcode IP addresses either. Ways to do that is beyond the scope of this tutorial. - Thus, the third line says that I want to set the
root
variable to point to the root folder of my HTTP server. Any later path reference will be on the HTTP server, so I can put my kernels and ramdisks on my http server, and download them on the fly when booting. Most tutorials out there tells you to put your kernels and ramdisks on the TFTP server. I'm not doing that. What I've tested is that HTTP is a little faster and a little more reliable in downloading larger files. You can also usenfs
andnbd
as your file storage instead of HTTP. Just search those terms online.