Making Debian CD image bootable via PXE

July 27, 2017      

Okay, this is somewhat of a hack, and certainly not recommended if your Debian CD is very large. Our scenario was a 150MB ISO in our build pipeline that we needed to PXE-boot and automatically install onto servers for automated testing. The ISO is already configured to autoinstall via a preseed configuration, so I will skip that part of the tutorial.

For PXE, we PXE boot iPXE and chainload a kernel+initrd, mostly because we have an web application that dynamically writes iPXE boot scripts depending on different states of the hardware. More on this system might come later.

 

Anyways then, to start off we have an image, lets call it debian.iso, fresh from our build pipeline. On it contains the neccesary files to install a debian system with your custom software as a package.

Now, if you try to PXE boot the ISO via a memdisk or such, you will run in to the “No CDROM found issue”, due to the installer not actually looking for memdisks. With our image being 150MB in total (and can’t enable internet on the installer because of missing drivers etc), we looked into embedding the whole ISO inside the installer initramfs file.

Hack away

Start by unpacking the iso. We don’t like loopback devices so losetup is out of question. 7z works fine for extraction in our case.

7z x debian.iso

Obviously run that in a folder inside /tmp/. The installer kernel/initrd was found in iso/install.386/ on our CD. Location may vary but should be one of the install folders.

We continue with unpacking the initrd file (if not run as root, it will complain about dev/console and dev/null).

zcat initrd.gz | cpio -i

To figure out how fool the installer, we dug through the depths of the debian-installer. A lot of the code can be found in initrd/var/lib/dpkg/info/*.postinst files, as well as initrd/usr/lib/base-installer*.
We found the code for CDROM detection/mounting, and found that it is pretty simple to spoof the CDROM being mounted.

In our version (Wheezy based), the install CDROM would be mounted to /cdrom, and a check was made before to see if /cdrom/.disk/info existed, in which case the installation would think the CDROM is already mounted and proceed.

Start the abuse

So, our first step was to copy the .disk directory from the extracted iso to initrd/cdrom/.disk.
We also copied the dists/ and pool/ folder as they are obviously needed for package installation.

We then packed the initrd with the following command:

find . | cpio -o -H newc | gzip > ../initrd-iso.gz

Fired it off in our test environment and BOOM, we got through almost the whole installation. But when the installer chroot:s to the installation target to install kernel and other packages, it was unable to find any kernels.

Sifting through /var/log/syslog in the installation (accessible through tty4 or via consoles on tty2/tty3 on normal debian installs) gave us the error that a bind mount from /cdrom to /target/media/cdrom had failed. We currently don’t know why this fails (exact command is mount -o bind /cdrom /target/media/cdrom) but it might have to do something with BusyBox:s implementation of mount.

More abuse

Anyways, to get past this we hacked up a quick script that just copied the contents of /cdrom to /target/media/cdrom and placed it as a base-installer routine.

Contents of initrd/usr/lib/base-installer.d/99copy-cdrom:

#!/bin/sh
set -e
. /usr/share/debconf/confmodule

cp -r /cdrom /target/media/cdrom

At the same time we also add a script to remove the cdrom when we are done, 150MB of already installed packages is somewhat of a waste.

Contents of initrd/usr/lib/finish-install.d/11delete-cdrom (a number higher than 20 will cause it not to be ran apparently):

#!/bin/sh
set -e
. /usr/share/debconf/confmodule

rm -rf /target/media/cdrom/*

chmod +x both files and pack the initrd again with

find . | cpio -o -H newc | gzip > ../initrd-iso.gz

and PXE boot the new kernel/initrd.

Behold, the installation runs the whole way and reboots when finished (as long as your preseed is correctly set).

 

Hope you enjoyed this quick hack and that it may help in some way.