Debian – How to write a grub.cfg menuentry for Debian Netinst (8.2 as of writing) to boot via USB

bootdebiandebian-installergrublinux

I keep several Linux distros on a USB stick and manage them by simply writing grub.cfg entries for each distro. The other distros I keep on the stick boot and run just fine, but I (and others, it seems) started having problems with Debian Jessie (8.x). Debian Netinst will boot to the debian-installer curses interface, but then tries to search for the correct debian iso file, even when the iso path is given in the kernel line in grub.cfg.

I've been partially successful trying to boot "debian-8.2.0-amd64-i386-netinst.iso" from a USB stick. I first setup my USB stick using the USB multiboot instructions found on the ArchWiki.

Here's a simplified file and folder structure of the USB stick, followed by the relevant grub.cfg entries.

USBROOT/
    ----boot/
        ----grub/
            ----grub.cfg
            ----(other grub paraphernalia)

        ----iso/
            ----debian/
                ----debian-8.2.0-amd64-i386-netinst.iso
                ----initrd.gz (special initrd)

While there is an initramfs within the iso, it won't allow debian to boot properly for reasons I don't really understand; it is explained briefly in the two links I've given so far.

Now my grub.cfg entries. I know this is an i386/amd64 multiarch iso, but I will just focus on the 64 bit part for simplicity. If we can figure out the 64 bit part, I should be able to easily make another entry for i386:

probe -u $root --set=rootuuid
set imgdevpath="/dev/disk/by-uuid/$rootuuid"

menuentry 'Debian 8.2 Multiarch' {
    set isoname='debian-8.2.0-amd64-i386-netinst.iso'
    set isopath='/boot/iso/debian'
    set isofile=${isopath}/${isoname}
    set initrdfile=${isopath}/initrd.gz
    loopback loop $isofile
    linux (loop)/install.amd/vmlinuz iso-scan/ask_second_pass=true iso-scan/filename=${imgdevpath}/${isofile} config quiet
    initrd ${initrdfile}/initrd.gz
}

As an aside: changing the initrd line to

initrd ${initrdfile}

makes grub (I think) throw an error. Grub pauses for a few moments, then Debian tries to boot and immediately has a kernel panic–as expected, because it can't find an initramfs. However, this doesn't happen when I fully write out the path as shown in the block code example. Why would it throw an error when I specify the path with set variables, and not when just writing out the full path by hand? But my main question is:

What kernel boot parameters must I supply so that no search is performed and the iso is located at the path I specify. The installer does eventually find the correct iso by searching, but why did it have to search?

I am almost certain it has everything to do with the linux line:

linux (loop)/install.amd/vmlinuz iso-scan/ask_second_pass=true iso-scan/filename=${imgdevpath}/${isofile} config quiet

I've tried at least 20 variations on the theme, such as changing:

iso-scan/filename=${isofile}
findiso=${imgdevpath}/${isofile}
findiso=${isofile}

EDIT: I fixed the initrd problem: I had single quotes when defining $initrdfile. The findiso/iso-scan/whatever problem still remains.

Best Answer

Since you are booting netinst you could skip the ISO entirely and boot the kernel+initrd directly from your USB filesystem. This is a netboot d-i, it will just load the rest of the components from a debian repo.

About the iso search, the process goes something like this:

  • grub loads the ISO and reads the kernel and initrd into memory (in your case the initrd was already extracted to the USB drive)
  • grub hands control over to the kernel
  • the kernel hands control over to the initrd's init script
  • the init script hands control over to the debian-installer
  • the iso-scan d-i module mounts all available drives looking for the iso-scan/filename provided
  • once the ISO is found and loopback-mounted the debian-installer continues with the process

(see also section 6.3.1.4 on the install docs for more details)

When you give a path like /dev/disk/by-uuid/UUID/debian/debian8.iso it doesn't make much sense, since /dev/disk/by-uuid/UUID is a block device and not a mounted filesystem where files can reside.

If you want iso-scan to narrow the search down, besides using iso-scan/filename you can also preseed the values* shared/ask_device=manual and shared/enter_device=/dev/disk/UUID (just add them to your kernel line)

This should be your grub.cfg then:

set imgdevpath="/dev/disk/by-uuid/UUID"

menuentry 'Debian 8.2 Multiarch' {
    set isofile='/boot/iso/debian/debian-8.2.0-amd64-i386-netinst.iso'
    loopback loop $isofile
    linux (loop)/install.amd/vmlinuz iso-scan/filename=$isofile shared/ask_device=manual shared/enter_device=$imgdevpath no-prompt no-eject
    initrd (loop)/install.amd/initrd.gz
}

Note that I haven't really tested this, I'm copy-pasting from a similar setup of mine for an older debian release.

I recommend you start with this and only if it doesn't work try the other initrd. Also make sure it works "manually" before readding the probe for the UUID.

* These are the ones I referred to as "hint" before. Guess I remembered hint from ubuntu or some other distro

Related Question