Saturday, September 18, 2010

Linux PXE Boot

Over the next few posts I thought I would outline my version of diskless booting and imaging a Linux system (Kickstart specifically). To start with we'll be setting up PXELINUX and the required services, TFTP, NFS and DHCP.

TFTP Server
When PXE booting a client, Trivial File Transfer Protocol Daemon is responsible for passing the kernel binaries. Because it's directory structure forms the basis for the rest of our files, its a good idea to have it installed first. Once installed, enable the daemon by editing /etc/xinetd.d/tftp and changing disabled = yes to disabled = no, or you can run a sed script as shown below, then restart xinetd. This is also the file to edit if you want to place files in a different folder. The default is /tftpboot which I will be using through the rest of the example.
SuSE
# zypper install tftp
RedHat
# yum install tftp

# sed -e 's/disable.*=\ yes/disable\t\t\t= no/' /etc/xinetd.d/tftp > /etc/xinetd.d/tftp.temp
# mv /etc/xinetd.d/tftp.temp /etc/xinetd.d/tftp
# /etc/init.d/xinetd restart

PXELINUX
PXELINUX is a derivative project of SYSLINUX which allows you to boot Linux from a network server. I used to use Etherboot for this purpose but it requires a device specific image to be pushed to the card. This can create all kinds of headaches whereas PXELINUX is quite simple; one binary to all cards as long as they conform to the Intel PXE specification (Pre-Execution Environment). I don't know of a server today that doesn't have a PXE compliant NIC and in fact many desktop cards do as well.

Most distributions have a package for SYSLINUX which includes PXELINUX, or if you want to do things manually you can grab the binaries from here. This is perhaps already installed with a default directory structure which I also follow.
SuSE
# zypper install syslinux
RedHat
# yum install syslinux
There should be a directory under /tftpboot called linux-boot with a single file, pxelinux.0. If not you can create them as shown below.
# mkdir -p /tftpboot/linux-boot
# cp /usr/share/syslinux/pxelinux.0 /tftpboot/linux-boot

NFS Server
The NFS Server requirements are pretty basic and largely depends on what you want to do. For now we will setup two exports, one for diskless booting and another for Kickstart. They actually don't have to be on the same physical box, if you have a fancy NAS server you can host it there but for the purposes of this exercise we will host it under /tftpboot/boot-image and /tftpboot/kickstart. Edit /etc/exports as shown and startup your NFS server.
# mkdir -p /tftpboot/boot-image
# mkdir -p /tftpboot/kickstart
# vi /etc/exports
/tftpboot/boot-image *(rw,no_root_squash)
/tftpboot/kickstart *(rw,no_root_squash)
# /etc/init.d/nfsserver start

DHCP Server
Asside from the details of setting up PXELINUX itself, the DHCP server contains most of the configuration information. Listed below is a generic configuration that should give you a good starting point. I generally have a listing for each one of my servers as it provides me with some additional flexibility such as providing general DHCP services to other hosts on the same network.

The first option ddns-update-style turns off dynamic DNS. The second next-server is used to tell the client from which server it should retrieve it's initial boot as specified by the filename option. Otherwise things should be pretty straight forward.
ddns-ddns-update-style       none;
next-server             192.168.0.1;

subnet 192.168.0.0 netmask 255.255.255.0 {

}

group {
        option domain-name              "pxeboot.net";
        filename                        "linux-install/pxelinux.0";
        option routers                  ;
        option domain-name-servers      ;
        use-host-decl-names             on;
        host node01 {
                hardware ethernet       00:AE:56:9C:5D:81;
                fixed-address           192.168.0.10;
        }
        host node02 {
                hardware ethernet       00:50:56:99:4E:41;
                fixed-address           192.168.0.11;
        }
        host node03 {
                hardware ethernet       00:50:56:99:E0:68;
                fixed-address           192.168.0.12;
        }
}

Once this is completed you will probably have to edit the dhcpd configuration file, /etc/sysconfig/dhcpd, in order to tell it which interface to listen to. It's generally the first option (after the comments) and is called DHCPD_INTERFACE. Simply append on the appropriate interface and restart dhcpd with /etc/init.d/dhcpd restart. There is generally decent error information on the command line if you have any typos or missed anything.

Configuring PXELINUX
When PXELINUX is booted it will look in a sub-directory called pxelinux.cfg to find a configuration file for a specific host. Because this is a relative directory, ours will be called /tftpboot/linux-install/pxelinux.cfg. There is an order to the files its looking for which you can read all about here but given that this is a generic boot server, I am going to use the catch all default file.

In the example below I use numbers to control what to boot from rather than typing names. There is a display option display msgs/logicalshift.msg that shows the available boot choices (see below) and a corresponding label which does the actual work. My default is a generic installation, there is a prompt for the user to input a value and a 10 second timeout. You can find more about these options from the syslinux man pages.

Under each kernel I have two important options; the append option to tell the kernel to load an appropriate initrd, where to find its kickstart file and which device to use for the kickstart; in this case the interface that was booted from. And ipappend, used to tell PXELINUX that it should pass along IP information to the kernel given by the DHCP server.

In my configuration I specify a local boot option, a setup to run completely from an NFS server and two kickstart configurations; a generic install and one pre-configured to run Oracle. More on these to follow.

/tftpboot/linux-install/pxelinux.cfg/default
default 4
prompt 1
timeout 100
display msgs/logicalshift.msg

label 1
        localboot 0

label 2
        kernel CUSTOM/bzImage_x64-2.6.34
        append rw nfsroot=:/tftpboot/boot-image ip=dhcp

label 3
        kernel RHEL_5.4/vmlinuz
        append ksdevice=bootif initrd=RHEL_5.5/initrd.img ks=nfs::/tftpboot/KickStart/cfg/generic_5.5.ks
        ipappend 2

label 4
        kernel RHEL_5.4/vmlinuz
        append ksdevice=bootif initrd=RHEL_5.5/initrd.img ks=:/tftpboot/KickStart/cfg/oracle_5.5.ks
        ipappend 2


/tftpboot/linux-install/pxelinux.cfg/msgs/logicalshift.msg
This file doesn't provide any logic, it is just for display to give the user the available options. Escape characters are there to provide some colour, just for fun. I use an online ascii generator with a rounded font from here if you are interested in doing your own version.
^L

           ^O09Welcome to the ^O0cLogical Shift Installer^O07
^O0a
 _             _             _          _     _    ___       
| |           (_)           | |        | |   (_)  / __)  _   
| | ___   ____ _  ____ _____| |     ___| |__  _ _| |__ _| |_ 
| |/ _ \ / _  | |/ ___|____ | |    /___)  _ \| (_   __|_   _)
| | |_| ( (_| | ( (___/ ___ | |   |___ | | | | | | |    | |_ 
 \_)___/ \___ |_|\____)_____|\_)  (___/|_| |_|_| |_|     \__)
        (_____|                                              

                           
^O07

Enter number of the Operation System you wish to install:

1. Local (HDD) boot
2. Custom NFS root
3. Generic RHEL 5.5
4. RHEL 5.5 with Oracle Prerequisites (default)

Boot Kernel and KickStart File
One last step remains to give us some basic functionality, a Kernel and initial RAM disk to boot from and a kick start file to install from. I like to keep multiple kernel versions around so I have a directly relative to pxelinux.0 called RHEL_5.5.

In my pxe config file above I reference a directory for a RedHat 5.5. This is again a relative directory to pxelinux so it will be located under /tftpboot/linux-install as RHEL_5.5. You can get the kernel and initial RAM disk from the RedHat DVD; the steps are outlined below. The easiest way to create a kick start file is to perform a manual install, save the results and copy the file to the NFS location specified on the append line of your pxelinux.cfg/default file. From this base line you can customize your installation but I will cover that in a latter post.
# mkdir -p /tftpboot/linux-install/RHEL_5.5
# mount -o loop rhel_5.5.iso /mnt
# cp /mnt/images/pxeboot/vmlinuz /tftpboot/linux-install/RHEL_5.5/
# cp /mnt/images/pxeboot/initrd.img /tftpboot/linux-install/RHEL_5.5/
# umount /mnt