UEFI + BIOS bootable live Debian stretch amd64 with persistence

22,262

Here is a way to create a Debian live USB drive with persistence. It will allow to install the missing packages which will from then on be available on every live boot using the persistence. Because we re-create the live ISO image filesystem contents on a read-write capable filesystem, we can change the bootloader configurations to enable persistence and set the keyboard layout on boot.

The steps described here were tested to work on Debian stretch and buster to create a Debian stretch live image.

There are a lot of steps involved, but it seems that this method is still quite efficient.

Disclaimer: You will lose the data on the target USB drive and if you mess up the commands below you might feel very sorry afterwards. I am not responsible for your actions.

Feeling lucky

If you feel particularly lucky today, you can try a bash script automating the process for you. Give it your ISO image path as first parameter and the USB drive block device name as the second. Note that this script is insanely dangerous and that you should not execute it without reading and understanding it first.

TL;DR

Get Debian live ISO image, then do the following:

umount /dev/sdX*
parted /dev/sdX --script mktable gpt
parted /dev/sdX --script mkpart EFI fat16 1MiB 10MiB
parted /dev/sdX --script mkpart live fat16 10MiB 3GiB
parted /dev/sdX --script mkpart persistence ext4 3GiB 100%
parted /dev/sdX --script set 1 msftdata on
parted /dev/sdX --script set 2 legacy_boot on
parted /dev/sdX --script set 2 msftdata on

mkfs.vfat -n EFI /dev/sdX1
mkfs.vfat -n LIVE /dev/sdX2
mkfs.ext4 -F -L persistence /dev/sdX3

mkdir /tmp/usb-efi /tmp/usb-live /tmp/usb-persistence /tmp/live-iso
mount /dev/sdX1 /tmp/usb-efi
mount /dev/sdX2 /tmp/usb-live
mount /dev/sdX3 /tmp/usb-persistence
mount -oro live.iso /tmp/live-iso

cp -ar /tmp/live-iso/* /tmp/usb-live

echo "/ union" > /tmp/usb-persistence/persistence.conf

grub-install --no-uefi-secure-boot --removable --target=x86_64-efi --boot-directory=/tmp/usb-live/boot/ --efi-directory=/tmp/usb-efi /dev/sdX

dd bs=440 count=1 conv=notrunc if=/usr/lib/syslinux/mbr/gptmbr.bin of=/dev/sdX
syslinux --install /dev/sdX2

mv /tmp/usb-live/isolinux /tmp/usb-live/syslinux
mv /tmp/usb-live/syslinux/isolinux.bin /tmp/usb-live/syslinux/syslinux.bin
mv /tmp/usb-live/syslinux/isolinux.cfg /tmp/usb-live/syslinux/syslinux.cfg

sed --in-place 's#isolinux/splash#syslinux/splash#' /tmp/usb-live/boot/grub/grub.cfg

sed --in-place '0,/boot=live/{s/\(boot=live .*\)$/\1 persistence/}' /tmp/usb-live/boot/grub/grub.cfg /tmp/usb-live/syslinux/menu.cfg

sed --in-place '0,/boot=live/{s/\(boot=live .*\)$/\1 keyboard-layouts=de locales=en_US.UTF-8,de_DE.UTF-8/}' /tmp/usb-live/boot/grub/grub.cfg /tmp/usb-live/syslinux/menu.cfg

umount /tmp/usb-efi /tmp/usb-live /tmp/usb-persistence /tmp/live-iso
rmdir /tmp/usb-efi /tmp/usb-live /tmp/usb-persistence /tmp/live-iso

In Detail and with some explanation

You will need to execute most of the following commands with elevated privileges, i.e., using sudo on most GNU/Linux systems.

Download

Download a Debian live ISO image with the window manager of your choice:

https://cdimage.debian.org/debian-cd/current-live/amd64/iso-hybrid/

We'll refer to the downloaded ISO image simply as "live.iso".

Determine target drive

Find the device that is your USB drive using lsblk. We'll call that /dev/sdX.

Unmount

Unmount existing partitions on your drive using umount /dev/sdX*

Create partitions

We need an EFI boot partition for UEFI PCs to boot from the USB drive. Then we need a sufficiently large partition to hold the original live ISO filesystem image contents. That partition must have the legacy_boot flag set. Then we add the persistence partition, using up all the remaining space of the USB drive. You can do that with any GPT capable partitioning tool (mind the legacy_boot flag). Here is an example using parted:

parted /dev/sdX --script mktable gpt
parted /dev/sdX --script mkpart EFI fat16 1MiB 10MiB
parted /dev/sdX --script mkpart live fat16 10MiB 3GiB
parted /dev/sdX --script mkpart persistence ext4 3GiB 100%
parted /dev/sdX --script set 1 msftdata on
parted /dev/sdX --script set 2 legacy_boot on
parted /dev/sdX --script set 2 msftdata on

This creates a GPT partition table and a protective MBR partition table.

Create Filesystems

We want FAT on the EFI and live partition and we want ext4 on the persistence parition and we require the label persistence for the persistence feature to work.

mkfs.vfat -n EFI /dev/sdX1
mkfs.vfat -n LIVE /dev/sdX2
mkfs.ext4 -F -L persistence /dev/sdX3

Mounting the resources

We'll need to mount the source ISO and target partitions at temporary mount points.

mkdir /tmp/usb-efi /tmp/usb-live /tmp/usb-persistence /tmp/live-iso
mount /dev/sdX1 /tmp/usb-efi
mount /dev/sdX2 /tmp/usb-live
mount /dev/sdX3 /tmp/usb-persistence
mount -oro live.iso /tmp/live-iso

Install live system

Copy the live ISO filesystem content to the LIVE partition.

cp -ar /tmp/live-iso/* /tmp/usb-live

persistence.conf

Prepare the persistence filesystem with the required configuration file. The persistence feature will not work without this file.

echo "/ union" > /tmp/usb-persistence/persistence.conf

Grub for UEFI support

Install grub2 for UEFI booting support (this requires the grub-efi-amd64-bin package on Debian). We force grub-install to not use UEFI secure boot, which apparently does not work with the --removable option.

grub-install --no-uefi-secure-boot --removable --target=x86_64-efi --boot-directory=/tmp/usb-live/boot/ --efi-directory=/tmp/usb-efi /dev/sdX

Syslinux for legacy BIOS support

Install syslinux gptmbr.bin bootloader to the drive (download syslinux or install package syslinux-common). Then install syslinux to the live partition.

dd bs=440 count=1 conv=notrunc if=/usr/lib/syslinux/mbr/gptmbr.bin of=/dev/sdX
syslinux --install /dev/sdX2

Isolinux fixup

Reuse the isolinux config of the original live ISO to work with syslinux.

mv /tmp/usb-live/isolinux /tmp/usb-live/syslinux
mv /tmp/usb-live/syslinux/isolinux.bin /tmp/usb-live/syslinux/syslinux.bin
mv /tmp/usb-live/syslinux/isolinux.cfg /tmp/usb-live/syslinux/syslinux.cfg

Kernel parameters

Now that we copied the live system files to an actual read-write filesystem, we can manipulate the grub and syslinux config.

Add the persistence kernel parameter to menu.cfg and grub.cfg. In both files, add the keyword persistence at the end of the respective first line with boot=live in it.

sed --in-place '0,/boot=live/{s/\(boot=live .*\)$/\1 persistence/}' /tmp/usb-live/boot/grub/grub.cfg /tmp/usb-live/syslinux/menu.cfg

Set the keyboard-layout kernel parameter. In both files, add the keywords at the end of the respective first line with boot=live in it.

sed --in-place '0,/boot=live/{s/\(boot=live .*\)$/\1 keyboard-layouts=de locales=en_US.UTF-8,de_DE.UTF-8/}' /tmp/usb-live/boot/grub/grub.cfg /tmp/usb-live/syslinux/menu.cfg

Grub splash

Fix the grub splash image (optional; we moved it into another directory).

sed --in-place 's#isolinux/splash#syslinux/splash#' /tmp/usb-live/boot/grub/grub.cfg

Unmounting and Cleanup

umount /tmp/usb-efi /tmp/usb-live /tmp/usb-persistence /tmp/live-iso
rmdir /tmp/usb-efi /tmp/usb-live /tmp/usb-persistence /tmp/live-iso

Why this should work for both UEFI and BIOS

When starting in UEFI mode, the PC will scan the FAT partitions we defined in the GPT partition table. The first FAT partition carries the UEFI grub bootloader, which is found because it is located in the path specified by UEFI for removable drives (the --removable switch to grub-install did this). No UEFI boot entry is necessary for that to work, we only need to make the PC try to boot from the USB drive. That grub is configured to take it from there (load the grub.cfg, show the menu, etc.).

When starting in BIOS mode and selecting to boot from the USB drive, the PC will execute the gptmbr.bin bootloader code we have written to the protective MBR of the USB drive. That bootloader looks for the GPT partition marked with the legacy_boot flag and chainload syslinux from that partition. Syslinux then takes over (load menu.cfg, show the menu, etc.).

Encrypted Persistence

Instead of using plain ext4 on the persistence partition, one could first encrypt the persistence partition with LUKS (using cryptsetup), then format that with ext4 (using the proper label). However, as the documentation says, the live system must include the cryptsetup package. Otherwise, the encrypted partition cannot be decrypted by the live system. This means one has to build a custom live ISO first. That is, however, out of the scope of this answer.

History

The --no-uefi-secure-boot option was previously not part of the call to grub-install. The stick worked fine for me, but that stopped with Debian buster, even though secure boot is still disabled on my machine.

Share:
22,262

Related videos on Youtube

schlimmchen
Author by

schlimmchen

Updated on September 18, 2022

Comments

  • schlimmchen
    schlimmchen over 1 year

    All of the information I currently find on this matter is insufficient for my taste. It is either outdated, misleading or even wrong, seems overly complicated or not covering this specific question.

    Goals:

    • bootable USB drive (both UEFI and legacy BIOS supported)
    • (based on) live Debian 9 (stretch)
    • persistence (by default and for both UEFI and legacy BIOS)
    • German keyboard layout per default
    • fit for troubleshooting other GNU/Linux systems

    Reasons:

    • having to setup the keyboard layout on every use is a real headache
    • cryptsetup and efibootmgr are missing in the default Debian live images
    • gnome-terminal has this annoying white background per default

    No solutions:

    • (re)building custom debian live image (it seems tedious, although I did not try it yet)
    • unetbootin (asks for an unknown password when starting up on debian stretch and I think it does not support UEFI anyways)
    • some foreign automated process where I don't see what is happening

    Debian live and install images are isohybrid and can be conveniently written to block devices using dd. And they do work from USB drives like that, which is very nice! However, there will be no persistence and no way to start with a non-english keyboard layout per default without editing the grub and isolinux config, which is included in the very read-only ISO9660 filesystem of the live ISO image. So even after writing the live ISO to a USB drive, these parameters still cannot be changed.

  • Petr Havlicek
    Petr Havlicek over 6 years
    I've just created an account here to thank you for this. Excellent manual. Small suggestion - it would be nice to have the persistence partition encrypted.
  • schlimmchen
    schlimmchen over 6 years
    @PetrHavlicek True. I think that is easy enough to do, but I spent my spare time since creating this Q&A with other issues, so I still have to revisit this idea (and thanks for your appreciation :).
  • mikuszefski
    mikuszefski over 6 years
    Works great! Some extra explanation would be nice, though. (sure you can look it all up on the man pages, but e.g. mktable, while the same as mklable, is not really documented as such, etc.)
  • ceving
    ceving over 6 years
    Is it possible to have just a file on the FAT formatted USB stick, which contains the persistence volume? It should be possible by loop mounting the file. But how to tell Debians initrd to take a file instead of a partition?
  • schlimmchen
    schlimmchen over 6 years
    See debian-live.alioth.debian.org/live-manual/stable/manual/html‌​/… for that. In short: Create an image (sparse) file in the root of any filesystem, name that file 'persistence' and format it, e.g., with ext4.
  • user42070
    user42070 almost 6 years
    Great work. Although I have an issue on several Macbook. If I use the above on a 32 GB key drive it will work fine. If I use instead a 64 Gb drive then the boot will stop on a 'busybox' with the message "unable to find a medium containing a live file sytem". Any ideas why ? Is there a workaround to work on a 64 Gib ( should I try to use less than 32 GB maybe) ? The 64GB key drive works well on a standard desktop PC so it seems to be very specific to apple machines... any help would be appreciate
  • Lorem Ipsum
    Lorem Ipsum over 5 years
    It seems there were some problems with debian-live. The new manual is available here: live-team.pages.debian.net/live-manual
  • sudodus
    sudodus almost 5 years
    +1, Great work, @schlimmchen :-) You may want to compare your method with that of mkusb. See the following links, mkusb and mkusb/persistent and mkusb/install-to-debian.
  • Andrew
    Andrew over 4 years
    what would be the equivalent flag for msftdata in gpart ? FreeBSD user here. freebsd.org/cgi/man.cgi?gpart(8)
  • Admin
    Admin almost 2 years
    At this point, on Debian Bookworm, you'll need to sudo apt-get install syslinux syslinux-common. Just the latter does not get you the syslinux command. Great write-up!