The [How to Build a Netboot Server, Part 1][1] article provided a minimal [iPXE][2] boot script for your netboot image. Many users probably have a local operating system that they want to use in addition to the netboot image. But switching bootloaders using the typical workstation’s BIOS can be cumbersome. This part of the series shows how to set up some more complex iPXE configurations. These allow the end user to easily choose which operating system they want to boot. They also let the system administrator manage the boot menus from a central server.
### An interactive iPXE boot menu
The commands below redefine the netboot image’s boot.cfg as an interactive iPXE boot menu with a 5 second countdown timer:
```
$ MY_FVER=29
$ MY_KRNL=$(ls -c /fc$MY_FVER/lib/modules | head -n 1)
* **menu** defines the actual menu that will be shown on the screen.
* **failed** notifies the user that something went wrong and drops the user to a shell so they can troubleshot the problem.
* **shell** provides an interactive command prompt. You can reach it either by pressing the **Esc** key while at the boot menu or if the “boot” command returns with a failure code.
* **lcl** contains a single command that tells iPXE to exit and return control back to the BIOS. Whatever you want to boot by default (e.g. the workstation’s local hard drive) **must** be listed as the next boot item right after iPXE in your workstation’s BIOS.
* **f29** contains the same netboot code used earlier but with the final exit replaced with goto failed.
Copy the updated boot.cfg from your $HOME/esp/linux directory out to the ESPs of all your client systems. If all goes well, you should see results similar to the image below:
![][3]
### A server hosted boot menu
Another feature you can add to the netboot server is the ability to manage all the client boot menus from one central location. This feature can be especially useful when rolling out a new version of the OS. It lets you perform a sort of [atomic transaction][4] to switch all clients over to the new OS after you’ve copied the new kernel and initramfs out to the ESPs of all the clients.
Install Mojolicious:
```
$ sudo -i
# dnf install -y perl-Mojolicious
```
Define the “bootmenu” app:
```
# mkdir /opt/bootmenu
# cat << END > /opt/bootmenu/bootmenu.pl
#!/usr/bin/env perl
use Mojolicious::Lite;
use Mojolicious::Plugins;
plugin 'Config';
get '/menu';
app->start;
END
# chmod 755 /opt/bootmenu/bootmenu.pl
```
Define the configuration file for the bootmenu app:
```
# cat << END > /opt/bootmenu/bootmenu.conf
{
hypnotoad => {
listen => ['http://*:80'],
pid_file => '/run/bootmenu/bootmenu.pid',
}
}
END
```
This is an extremely simple Mojolicious application that listens on port 80 and only answers to /menu requests. If you want a quick introduction to what Mojolicious can do, run man Mojolicious::Guides::Growing to view the manual. Use the **Q** key to quit the manual.
Move boot.cfg over to our netboot app as a template named menu.html.ep:
After you’ve copied the updated bootloader to all your clients, you can make future updates to the boot menu simply by editing /opt/bootmenu/templates/menu.html.ep and running:
```
$ sudo systemctl restart bootmenu.service
```
### Making further changes
If the boot menu server is working properly, you’ll longer need the the boot.cfg file on your client systems.
For example, re-add the Fedora 28 image to the boot menu:
```
$ sudo -i
# MY_FVER=28
# MY_KRNL=$(ls -c /fc$MY_FVER/lib/modules | head -n 1)