Creating a multi-OS bootable USB drive

Contents

Make the drive bootable

These instructions were written using Syslinux 4.05 as a base. They further assume the partition you’re booting is formmated as FAT.

  1. Ensure the syslinux package is installed on the system (TIP: for now use the one on sparrow, as it’s much more up to date than the one on penguin)
  2. Mount the USB drive’s partition over a handy mount point such as /mnt/tmp or /mnt
  3. Allocate a directory on the drive called /boot
  4. Copy the following files from /usr/share/syslinux to /boot:
    • libcom32.c32
    • libmenu.c32
    • libutil.c32
    • menu.c32
    • vesamenu.c32
  5. Issue the following command to set up the Master Boot Record on the device, where x is the USB drive’s block file:
      X='sdx'
      [ -b /dev/$X ] && cat /usr/share/syslinux/mbr.bin >/dev/$X
  6. Issue the following command to toggle the bootable flag on the partition (the command below assumes 1; alter as needed):
      sfdisk --activate /dev/$X 1
  7. (FAT file systems) Issue the following command, where 1 is partition 1 (alter as needed):
      syslinux --install -d /boot -m /dev/${X}1
  8. (ext2/3/4 and NTFS filesystems): Ensure the USB’s file system is mounted. Issue the following command:
      extlinux --install /path/to/USB_drive_mount_point/boot

Set up a basic menu file

In the /boot directory, create a file called syslinux.cfg:

PROMPT 0
TIMEOUT 90
UI vesamenu.c32
MENU BACKGROUND #FF000000
MENU TITLE Multi-linux USB Flash Drive

MENU SPEARATOR

LABEL memtest
    MENU LABEL Memory tester - Memtest86| 4.10
    KERNEL memtest
    APPEND foo

(Note that memtest is not yet on the drive; it will get added later.)

Create another file named menu-rtn.cfg. This is used by OS-specific sub-menus to return to the top level menu.

LABEL return
    MENU LABEL Return to main menu
    KERNEL vesamenu.c32
    APPEND syslinux.cfg

General procedure to add a new OS to the drive

This procedure assumes you’re adding a bootable Linux operating system from an ISO image. For the purposes of this text, we’re installing Humboldt Linux version 16 (Humboldt is a species of penguin; 16 is in memory of sixteen members of the Humboldt Broncos hockey team who were killed when a tractor-trailer collided with their bus in April 2018.)

  1. Set the variable DIST_DN to a name that describes the distribution you’re setting up:
      DIST_DN='Humboldt-Linux-16'

  2. Mount the USB drive’s partition over a handy mount point such as /mnt/tmp or /mnt

  3. Mount the ISO image:
      mkdir /r/iso
      mount -o loop,ro /var/local/ISO/Humboldt-Linux-16.2018-04-06.x86_64.iso /r/iso

  4. In the root directory of the USB drive, create a directory for the OS files:
      mkdir $DIST_DN

  5. Copy the contents of the ISO to the directory:
      DIR=/r/iso; TAR_SIZE=$(ls -lR $DIR | estimate-tar-size); echo $TAR_SIZE
      cd $DIR; tar cf - . | pv -s$TAR_SIZE | tar xf - -C /path/to/$DIST_DN

  6. There is likely a boot or isolinux directory under the OS-specific directory in the USB drive’s root that you created in step 4.

  7. Go into the distribution’s boot directory, probably one of: | $DIST_DN/boot | $DIST_DN/boot/syslinux | $DIST_DN/isolinux

  8. This part is tricky. It’s necessary to update the syslinux.cfg, extlinux.cfg, or isolinux.cfg (or isolinux.conf) file to indicate the correct path the the kernel and initrd files. But the path is relative to the /boot directory in the root of the USB drive and not to the directory you’re currently in. For example:

    USB_DRIVE/
    ├─ .treeinfo(Needed for CentOS installs)
    ├─ boot/
    │  ├─ isolinux.bin
    │  ├─ libcom32.c32
    │  ├─ libmenu32.c32
    │  ├─ libutil32.c32
    │  ├─ menu.c32
    │  ├─ menurtn.cfg
    │  ├─ syslinux.cfg
    │  └─ vesamenu.c32
    ├─ CentOS
    │  └─ (...)
    ├─ Humboldt-Linux-16/
    │  ├─ EFI/
    │  │  └─ (...)
    │  ├─ isolinux/You are here
    │  │  ├─ initrd.img
    │  │  ├─ isolinux.bin
    │  │  ├─ isolinux.conf
    │  │  ├─ memtest
    │  │  ├─ vesamenu.c32
    │  │  └─ vmlinuz
    │  ├─ modules/
    │  │  └─ (...)
    │  └─ (other files and directories)
    ├─ Knoppix-8.1/
    │  └─ (...)
    ├─ Packages/(Needed for CentOS installs)
    │  └─ (...)
    ├─ repodata/(Needed for CentOS installs)
    │  └─ (...)
    (other files and directories)`
    

    You would expect, for example, in Humboldt-Linux-16/isolinux/isolinux.conf the KERNEL line would be simply:

    KERNEL vmlinuz
    

    But the USB drive will start in boot/, and that’s where the directory tree is anchored. So the path to the kernel is relative to that:

    KERNEL ../Humboldt-Linux-16/isolinux/vmlinuz
    

    The next two points refer to the ../Humboldt-Linux-16/isolinux part as the BOOT_RP (boot relative path.)

    • Prepend the kernel name with the BOOT_RP (the command below accomplishes this by adding the desired text after the KERNEL command):
        :%s,\(KERNEL \|kernel \),\1BOOT_RP/,
    • Do the same for the initrd parameter:
        :%s,\(initrd=\),\1BOOT_RP/,

    Following are tweaks that need to be made for various distributions.

    Fedora Linux Spin (USB drive): If you’re setting up a Fedora spin, you need to make some additional changes to the APPEND line (gleaned from livecd-iso-to-disk):

    • Issue this command: lsblk -l -oNAME,UUID,FSTYPE,MOUNTPOINT -xNAME | less
    • Note the UUID of the partition where you created DIST_DN
    • Change root=live:CDLABEL=<whatever>
      to root=live:UUID=UUID live_dir=DIST_DN/LiveOS
      (you may have to change this on multiple lines)
      (As of Fedora 28, root=live:LABEL=filesystem_label_of_USB_partition also works)
    • You may also wish to remove quiet from the APPEND lines

    Fedora Linux Spin (tftoboot): If you’re setting up a Fedora spin, you need to make some additional changes to the APPEND line (gleaned from livecd-iso-to-disk):

    • (Sorry, this is not yet fully documented)
    • You may also wish to remove quiet from the APPEND lines

    RHEL/CentOS installation: If you’re setting up a Red Hat Enterprise Linux or CentOS installation device (as of CentOS 7):

    • Update the APPEND line to show the following:
        inst.stage2=hd:LABEL=filesystem_label_of_USB_partition
      (the path to the stage2 image file will be put into a .treeinfo file in a later step)
    • If you’re setting up a USB flash drive with a network install image, you’ll probably want to add the folllowing to the APPEND line:
        inst.repo=nfs:nfsvers=4:penguin:/mnt/iso
    • If you’re setting up an external disc drive with an “Everything” image, the instrepo and Packages directories must go into the root of the drive. The installer is rather simple-minded about this. Even though it can accept an NFS server name and a path:
        inst.repo=nfs:nfsvers=4:nfs.ourcompany.com:/mnt/CentOS-ISO
      and from there figure out if it has a repository or needs to mount an ISO image file, for local media it looks only in the root. The following does not work:
        inst.repo=hd:LABEL=USB_FAT:/CentOS-7.5-Everything
    • Copy the .treeinfo file from the ISO image into the root of the USB flash drive, and update the [stage2]/mainimage parameter to show the path to the sqaushfs.img file:
        [stage2]
        mainimage = Humboldt_Linux_16/squashfs.img
    • You may also wish to remove quiet from the APPEND line(s)

    Knoppix: If you’re setting up a Knoppix distribution, and DIST_DN is not KNOPPIX, you need to add knoppix_dir=value_of_DIST_DN to the APPEND line(s)

Update the top-level syslinux.cfg menu

Add lines similar to the following to the top-level syslinux.cfg menu.

The following lines boot the kernel directly; note the

LABEL humboldt
    MENU LABEL Humboldt Linux 16 (KDE)
    MENU DEFAULT
    KERNEL <value-of-BOOT_RP>/vmlinuz
    APPEND <value-of-BOOT_RP>/initrd.xz

The following lines allow you to use the distribution’s menu:

LABEL humboldt_m
    MENU LABEL Humboldt Linux 16 - menu
    COM32 vesamenu.c32
    APPEND <value-of-BOOT_RP>/isolinux.conf menu-rtn.cfg

For Proxmox 5.1 VE (debian based; note that this didn’t work in practice):

LABEL proxmox_i
    MENU LABEL Proxmox VE 5.1 release 3 Install
    KERNEL Proxmox-VE_5.1-3/linux26
    APPEND initrd=Proxmox-VE_5.1-3/initrd.img ro ramdisk_size=16777216 rw quiet splash=silent

LABEL proxmox_dbg
    MENU LABEL Proxmox VE 5.1 release 3 Install (debug)
    KERNEL Proxmox-VE_5.1-3/linux26
    APPEND initrd=Proxmox-VE_5.1-3/initrd.img ro ramdisk_size=16777216 rw quiet splash=verbose proxdebug

(The above didn’t work: Linux started, but the installer couldn’t locate the installation media.)