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.
- 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)
- Mount the USB drive’s partition over a handy mount point such as
/mnt/tmp
or/mnt
- Allocate a directory on the drive called
/boot
- Copy the following files from
/usr/share/syslinux
to/boot
:libcom32.c32
libmenu.c32
libutil.c32
menu.c32
vesamenu.c32
- 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
- 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
- (FAT file systems) Issue the following command, where 1 is partition 1
(alter as needed):
syslinux --install -d /boot -m /dev/${X}1
- (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.)
-
Set the variable
DIST_DN
to a name that describes the distribution you’re setting up:
DIST_DN='Humboldt-Linux-16'
-
Mount the USB drive’s partition over a handy mount point such as
/mnt/tmp
or/mnt
-
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
-
In the root directory of the USB drive, create a directory for the OS files:
mkdir $DIST_DN
-
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
-
There is likely a
boot
orisolinux
directory under the OS-specific directory in the USB drive’s root that you created in step 4. -
Go into the distribution’s boot directory, probably one of: |
$DIST_DN/
boot
|$DIST_DN/
boot/syslinux
|$DIST_DN/
isolinux
-
This part is tricky. It’s necessary to update the
syslinux.cfg
,extlinux.cfg
, orisolinux.cfg
(orisolinux.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
theKERNEL
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 theBOOT_RP
(boot relative path.)- Prepend the kernel name with the
BOOT_RP
(the command below accomplishes this by adding the desired text after theKERNEL
command):
:%s,\(KERNEL \|kernel \),\1
BOOT_RP
/,
- Do the same for the
initrd
parameter:
:%s,\(initrd=\),\1
BOOT_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 fromlivecd-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>
toroot=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 theAPPEND
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 fromlivecd-iso-to-disk
):- (Sorry, this is not yet fully documented)
- You may also wish to remove
quiet
from theAPPEND
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 thestage2
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
andPackages
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 thesqaushfs.img
file:
[stage2]
mainimage = Humboldt_Linux_16/squashfs.img
- You may also wish to remove
quiet
from theAPPEND
line(s)
Knoppix: If you’re setting up a Knoppix distribution, and
DIST_DN
is notKNOPPIX
, you need to addknoppix_dir=
value_of_DIST_DN
to theAPPEND
line(s) - Prepend the kernel name with the
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.)