Setting up Centos to netboot and mount a root file system over NFS proved to be a whole lot harder than I thought it was going to be. There are a gazillion pages on the net about setting up DHCP/PXE/TFTP, and a gazillion more about how to netboot random disribution installers, but I couldn't find a clear guide on how to actually run centos (or RHEL) diskless. Ubuntu works more or less out of the box diskless, I guess RHEL/Centos is a server OS, and servers have disks, or something.

Anyhoo, I wanted to netboot centos in order to use the Dell firmware repos to update the firmware on some Dell r410's. I only want to run Centos for a few minutes per server, and as I'm allergic to physical media, and didn't want to rely on something server specific (like a DRAC) netbooting seemed like the go. Here's what I ended up doing:

My DHCP/PXE/NFS server runs debian squeeze, largely standard. I used rinse (the logical equivalent to debootstrap in the RPM world) to make an initial centos tree. Happily, rinse is a standard package in squeeze, so is just an aptitude away:

sudo aptitude install rinse
cd /exports
sudo rinse  --directory=centos5.6 --distribution=centos-5 --add-pkg-list extra-rpms

The extra-rpms file is an optional list of extra packages you want installed, mine looks like:

# cat extra-rpms
python-libs
nano

python-libs seemed to be needed to make rinse work properly, nano because it's personally familiar.

Rinse will haul in packages from your nearest Centos mirror, at the end of the process your new directory should have about 350MB of stuff in it. Chroot into the new tree, and make a few mods:

sudo chroot centos5.6
cat > /etc/fstab
  192.168.1.30:/exports/centos5.6 /        nfs     rw,tcp,nolock  0 0
  tmpfs                           /dev/shm tmpfs   defaults       0 0
  devpts                          /dev/pts devpts  gid=5,mode=620 0 0
  sysfs                           /sys     sysfs   defaults       0 0
  proc                            /proc    proc    defaults       0 0
^D

Make sure you substitute the IP of your NFS server, and the path to your newly created centos tree. You can also set root passwords, hostname, add users, and other things that don't start daemons (any daemons you start will end up littering the server you're running the chroot on).

We then use yum to install the kernel package...

yum -y install kernel

... and generate a new initrd with support for NFS. Make sure you add/substitute any other ethernet modules you need for your hardware in the preload argument below. mkinitrd requires /etc/modprobe.conf to exist - it hangs if it doesn't:

touch /etc/modprobe.conf

/sbin/mkinitrd -v -f --omit-scsi-modules --omit-raid-modules \
--omit-lvm-modules --without-usb --without-multipath --without-dmraid \
--preload="tg3 e100 bnx2 e1000 nfs" --net-dev=eth0 --rootfs=nfs  \
/tmp/test.img 2.6.18-238.12.1.el5

Leave your chroot, and copy the kernel and new initrd into your pxe tftp tree. The initrd is not world readable by default, so make sure you chmod it so that the tftp server can get at it

exit
sudo cp /nfs/centos5/boot/vmlinuz-2.6.18-238.12.1.el5 /tftpboot/pxe/centos-5.6/vmlinuz
sudo cp /nfs/centos5/tmp/test.img /tftpboot/pxe/centos-5.6/initrd.img
sudo chmod 644 /tftpboot/pxe/centos-5.6/initrd.img

If you regenerate your initrd multiple times, you don't have to copy the kernel each time, only the initrd - you only need to copy the kernel if it gets upgraded.

Add something like this to your pxe config:

LABEL CentOS 5.6 BIOS updater
MENU LABEL CentOS 5.6 BIOS updater
kernel centos-5.6/vmlinuz
APPEND vga=normal initrd=centos-5.6/initrd.img ramdisk_size=10000 ip=dhcp

Net boot a PC into the new config, and make whatever changes you need. I tend to install ssh because the KVM in the dell DRACs is annoying

yum -y install openssh-server

To use the Dell firmware tools, you'll need a few dependancies:

yum -y install which compat-libstdc++-33 nano wget gpg perl    

then follow the instructions on http://linux.dell.com/repo/hardware/latest/

wget -q -O - http://linux.dell.com/repo/hardware/latest/bootstrap.cgi | bash
yum install dell_ft_install
yum install $(bootstrap_firmware)

And you're done - on any new machine that needs to be firmware updated, boot the nfsroot centos, then run whatever combination of these is appropriate:

yum update
yum install $(bootstrap_firmware)
inventory_firmware
update_firmware
update_firmware --yes