Create a Custom Debian Live Environment (CD or USB) with Grub Only
This article was last edited over 3 years ago. Information here may no longer be accurate. Please proceed with caution, and feel free to contact me.
Warning: I have stopped updating this article in favor of a similar, but updated, guide.
These are steps that I used on an Ubuntu 18.04 LTS (Bionic Beaver) 64-bit system to build an x86 Debian 9 (Stretch) live environment that I can boot from CD or USB.
These steps can be used to create a live environment that is BIOS bootable (MBR), UEFI bootable (GPT), or combination of both UEFI and BIOS bootable. Something unique about this guide is that Syslinux/Isolinux are not used. Only Grub boot equipment. This is done for consistency and to avoid mixing the two (Syslinux/Isolinux alone cannot accomplish everything covered in this article, but Grub can).
Here are some alternatives to my guide that may be better solutions for anyone reading this article: live-build, mkusb, UNetbootin, xixer, rufus, YUMI, Simple-cdd. You should also look at the Debian DebianCustomCD documentation as it will prove more informative than this article could ever be.
I wrote this guide more for educational purposes than anything. It is not necessarily the fastest guide or the best guide for your needs. I hope it is helpful all the same.
Warning: I have highlighted all the places you should be in the [chroot] environment. Be careful! Running some of these commands on your local environment instead of in the chroot can damage your system.
Prerequisites
Install applications we need to build the environment.
sudo apt-get install \
debootstrap \
squashfs-tools \
xorriso \
grub-pc-bin \
grub-efi-amd64-bin \
mtools
Create a directory where we will store all of the files we create throughout this guide.
mkdir -p $HOME/LIVE_BOOT
Bootstrap and Configure Debian
Set up the base Debian environment. I am using
stretch
for my distribution and i386
for
the architecture. Consult the list of
debian mirrors.
Please change the URL in this command if there is a mirror that is closer to you.
sudo debootstrap \
--arch=i386 \
--variant=minbase \
stretch \
$HOME/LIVE_BOOT/chroot \
http://ftp.us.debian.org/debian/
Chroot to the Debian environment we just bootstrapped.
sudo chroot $HOME/LIVE_BOOT/chroot
[chroot] Set a custom hostname for your Debian environment.
echo "debian-live" > /etc/hostname
[chroot] Figure out which Linux Kernel you want in the live environment.
apt-cache search linux-image
[chroot] I chose the
image linux-image-686
. I also believe
live-boot
is a necessity.
systemd-sys
(or an equivalent) is also necessary to
provide init.
apt-get update && \
apt-get install --no-install-recommends \
linux-image-686 \
live-boot \
systemd-sysv
[chroot] Install
programs of your choosing, and then run
apt-get clean
to save some space. I use
--no-install-recommends
to avoid superfluous
packages. You should decide what you need for your environment.
Read Debian’s ReduceDebian article for tips on reducing the size of your Debian environment if size is important and you want a minimal and compact installation. Please note that some live environments like Tiny Core Linux or Puppy Linux are specifically optimized for a tiny footprint. Although this article results in a relatively tiny live environment, generating an environment that is only a couple dozen MB large takes additional effort not covered in this article.
apt-get install --no-install-recommends \
network-manager net-tools wireless-tools wpagui \
curl openssh-client \
blackbox xserver-xorg-core xserver-xorg xinit xterm \
nano && \
apt-get clean
[chroot] Set the
root password. root
will be the only user in this
live environment by default, but you may add additional users as
needed.
passwd root
[chroot] Exit the chroot.
exit
Create directories that will contain files for our live environment files and scratch files.
mkdir -p $HOME/LIVE_BOOT/{scratch,image/live}
Compress the chroot environment into a Squash filesystem.
sudo mksquashfs \
$HOME/LIVE_BOOT/chroot \
$HOME/LIVE_BOOT/image/live/filesystem.squashfs \
-e boot
Copy the kernel and initramfs from inside the
chroot
to the live
directory.
cp $HOME/LIVE_BOOT/chroot/boot/vmlinuz-* \
$HOME/LIVE_BOOT/image/vmlinuz && \
cp $HOME/LIVE_BOOT/chroot/boot/initrd.img-* \
$HOME/LIVE_BOOT/image/initrd
Create a menu configuration file for grub. Please note that the
insmod all_video
line was needed in my testing to
deal with
a bug in UEFI booting
for one of my machines. Perhaps not everyone will need that line,
but I did.
This config instructs Grub to use the search
command
to infer which device contains our live environment. This seems
like the most portable solution considering the various ways we
may write our live environment to bootable media.
cat <<'EOF' >$HOME/LIVE_BOOT/scratch/grub.cfg
insmod all_video
search --set=root --file /DEBIAN_CUSTOM
set default="0"
set timeout=30
menuentry "Debian Live" {
linux /vmlinuz boot=live quiet nomodeset
initrd /initrd
}
EOF
Create a special file in image
named
DEBIAN_CUSTOM
. This file will be used to help
Grub
figure out which device contains our live
filesystem. This file name must be unique and must match the file
name in our grub.cfg
config.
touch $HOME/LIVE_BOOT/image/DEBIAN_CUSTOM
Your LIVE_BOOT
directory should now roughly look like
this.
LIVE_BOOT/chroot/*tons of chroot files*
LIVE_BOOT/scratch/grub.cfg
LIVE_BOOT/image/DEBIAN_CUSTOM
LIVE_BOOT/image/initrd
LIVE_BOOT/image/vmlinuz
LIVE_BOOT/image/live/filesystem.squashfs
Create a bootable medium
Please note that there are two separate sets of instructions below for creating a bootable medium for the live environment. One process is titled Create Bootable ISO/CD and the other, separate process, is titled Create Bootable USB.
-
The Create Bootable ISO/CD instructions will
result in an
.iso
image file containing our live environment. - The Create Bootable USB instructions will result in our live environment being installed directly to a USB device.
The .iso
file we create with the
Create Bootable ISO/CD instructions can be burned
to a CD-ROM (optical media), or written to a USB device with
dd
. The functionality that allows this
“dd-able” behavior from our .iso
file
does not come for free. The process is a bit complex, but
that resultant behavior is common in many modern live environments
such as the Ubuntu installation .iso
file.
Please note that writing an .iso
file to a USB
device is not the same as installing the live environment
directly to a USB device. Read more in my
Notes which details my discoveries.
Create Bootable ISO/CD
Install the live environment to an .iso
file which
can be burned to optical media.
As stated above, the .iso
file generated by these
steps can be written to a USB device with
something like dd
.
I have separated the instructions for creating a BIOS bootable,
UEFI bootable, or combination BIOS + UEFI bootable
.iso
in order to illustrate the separate processes.
Click either “BIOS”, “UEFI”, or
“BIOS + UEFI” and follow the instructions that are
appropriate for your needs.
BIOS Support Only
Create a grub BIOS image.
grub-mkstandalone \
--format=i386-pc \
--output=$HOME/LIVE_BOOT/scratch/core.img \
--install-modules="linux normal iso9660 biosdisk memdisk search tar ls" \
--modules="linux normal iso9660 biosdisk search" \
--locales="" \
--fonts="" \
"boot/grub/grub.cfg=$HOME/LIVE_BOOT/scratch/grub.cfg"
Use cat
to combine a bootable Grub
cdboot.img
bootloader with our boot image.
cat \
/usr/lib/grub/i386-pc/cdboot.img \
$HOME/LIVE_BOOT/scratch/core.img \
> $HOME/LIVE_BOOT/scratch/bios.img
Generate the ISO file.
xorriso \
-as mkisofs \
-iso-level 3 \
-full-iso9660-filenames \
-volid "DEBIAN_CUSTOM" \
--grub2-boot-info \
--grub2-mbr /usr/lib/grub/i386-pc/boot_hybrid.img \
-eltorito-boot \
boot/grub/bios.img \
-no-emul-boot \
-boot-load-size 4 \
-boot-info-table \
--eltorito-catalog boot/grub/boot.cat \
-output "${HOME}/LIVE_BOOT/debian-custom.iso" \
-graft-points \
"${HOME}/LIVE_BOOT/image" \
/boot/grub/bios.img=$HOME/LIVE_BOOT/scratch/bios.img
Now burn the ISO to a CD and you should be ready to boot from it using a BIOS system.
UEFI Support Only
Create a grub UEFI image.
grub-mkstandalone \
--format=x86_64-efi \
--output=$HOME/LIVE_BOOT/scratch/bootx64.efi \
--locales="" \
--fonts="" \
"boot/grub/grub.cfg=$HOME/LIVE_BOOT/scratch/grub.cfg"
Create a FAT16 UEFI boot disk image containing the EFI bootloader.
Note the use of the mmd
and
mcopy
commands to copy our UEFI boot loader named
bootx64.efi
.
(cd $HOME/LIVE_BOOT/scratch && \
dd if=/dev/zero of=efiboot.img bs=1M count=10 && \
mkfs.vfat efiboot.img && \
mmd -i efiboot.img efi efi/boot && \
mcopy -i efiboot.img ./bootx64.efi ::efi/boot/
)
Generate the ISO file.
xorriso \
-as mkisofs \
-iso-level 3 \
-full-iso9660-filenames \
-volid "DEBIAN_CUSTOM" \
-eltorito-alt-boot \
-e EFI/efiboot.img \
-no-emul-boot \
-append_partition 2 0xef ${HOME}/LIVE_BOOT/scratch/efiboot.img \
-output "${HOME}/LIVE_BOOT/debian-custom.iso" \
-graft-points \
"${HOME}/LIVE_BOOT/image" \
/EFI/efiboot.img=$HOME/LIVE_BOOT/scratch/efiboot.img
Now burn the ISO to a CD and you should be ready to boot from it using a UEFI system.
BIOS + UEFI Support
Create a grub UEFI image.
grub-mkstandalone \
--format=x86_64-efi \
--output=$HOME/LIVE_BOOT/scratch/bootx64.efi \
--locales="" \
--fonts="" \
"boot/grub/grub.cfg=$HOME/LIVE_BOOT/scratch/grub.cfg"
Create a FAT16 UEFI boot disk image containing the EFI bootloader.
Note the use of the mmd
and
mcopy
commands to copy our UEFI boot loader named
bootx64.efi
.
(cd $HOME/LIVE_BOOT/scratch && \
dd if=/dev/zero of=efiboot.img bs=1M count=10 && \
mkfs.vfat efiboot.img && \
mmd -i efiboot.img efi efi/boot && \
mcopy -i efiboot.img ./bootx64.efi ::efi/boot/
)
Create a grub BIOS image.
grub-mkstandalone \
--format=i386-pc \
--output=$HOME/LIVE_BOOT/scratch/core.img \
--install-modules="linux normal iso9660 biosdisk memdisk search tar ls" \
--modules="linux normal iso9660 biosdisk search" \
--locales="" \
--fonts="" \
"boot/grub/grub.cfg=$HOME/LIVE_BOOT/scratch/grub.cfg"
Use cat
to combine a bootable Grub
cdboot.img
bootloader with our boot image.
cat \
/usr/lib/grub/i386-pc/cdboot.img \
$HOME/LIVE_BOOT/scratch/core.img \
> $HOME/LIVE_BOOT/scratch/bios.img
Generate the ISO file.
xorriso \
-as mkisofs \
-iso-level 3 \
-full-iso9660-filenames \
-volid "DEBIAN_CUSTOM" \
-eltorito-boot \
boot/grub/bios.img \
-no-emul-boot \
-boot-load-size 4 \
-boot-info-table \
--eltorito-catalog boot/grub/boot.cat \
--grub2-boot-info \
--grub2-mbr /usr/lib/grub/i386-pc/boot_hybrid.img \
-eltorito-alt-boot \
-e EFI/efiboot.img \
-no-emul-boot \
-append_partition 2 0xef ${HOME}/LIVE_BOOT/scratch/efiboot.img \
-output "${HOME}/LIVE_BOOT/debian-custom.iso" \
-graft-points \
"${HOME}/LIVE_BOOT/image" \
/boot/grub/bios.img=$HOME/LIVE_BOOT/scratch/bios.img \
/EFI/efiboot.img=$HOME/LIVE_BOOT/scratch/efiboot.img
Now burn the ISO to a CD and you should be ready to boot from it using either a UEFI or a BIOS system.
Create Bootable USB
Install the live environment to a USB device.
As stated above, installing a live environment to a USB device is
not the same as writing an .iso
file
to a USB device. The end result is the same for the most part in
both those scenarios, but there are subtle differences worth
understanding, and there are valid reasons someone may want to
install a live environment directly to a USB device rather than
writing an .iso
file to a USB device.
I have separated the instructions for creating a BIOS bootable, UEFI bootable, or combination BIOS + UEFI bootable USB device in order to illustrate the separate processes. Click either “BIOS”, “UEFI”, or “BIOS + UEFI” and follow the instructions that are appropriate for your needs.
BIOS Support Only
I am assuming you have an umounted blank USB
drive at /dev/sdz. To allow easily swapping in a
real block device, I am using a variable named
$disk
in these commands.
Export the disk
variable.
export disk=/dev/sdz
Create a mount point for the USB drive.
sudo mkdir -p /mnt/usb
Partition the USB drive using parted
. This command
creates 1 partition in a traditional MBR layout.
sudo parted --script $disk \
mklabel msdos \
mkpart primary fat32 1MiB 100%
Format the partition.
sudo mkfs.vfat -F32 ${disk}1
Mount the partition.
sudo mount ${disk}1 /mnt/usb
Install Grub for i386-pc booting.
sudo grub-install \
--target=i386-pc \
--boot-directory=/mnt/usb/boot \
--recheck \
$disk
Create a live
directory on the USB device.
sudo mkdir -p /mnt/usb/{boot/grub,live}
Copy the Debian live environment files we previously generated to the USB disk.
sudo cp -r $HOME/LIVE_BOOT/image/* /mnt/usb/
Copy the grub.cfg
boot configuration to the USB
device.
sudo cp \
$HOME/LIVE_BOOT/scratch/grub.cfg \
/mnt/usb/boot/grub/grub.cfg
Now unmount the disk and you should be ready to boot from it on a BIOS system.
sudo umount /mnt/usb
UEFI Support Only
I am assuming you have an umounted blank USB
drive at /dev/sdz. To allow easily swapping in a
real block device, I am using a variable named
$disk
in these commands.
Export the disk
variable.
export disk=/dev/sdz
Create some mount points for the USB drive.
sudo mkdir -p /mnt/{usb,efi}
Partition the USB drive using parted
. This command
creates 2 partitions in a GPT (Guid Partition Table) layout. One
partition for UEFI, and one for our Debian OS and other live data.
sudo parted --script $disk \
mklabel gpt \
mkpart ESP fat32 1MiB 200MiB \
name 1 EFI \
set 1 esp on \
mkpart primary fat32 200MiB 100% \
name 2 LINUX \
set 2 msftdata on
Format the UEFI and data partitions.
sudo mkfs.vfat -F32 ${disk}1 && \
sudo mkfs.vfat -F32 ${disk}2
Mount the partitions.
sudo mount ${disk}1 /mnt/efi && \
sudo mount ${disk}2 /mnt/usb
Install Grub for x86_64 UEFI booting.
sudo grub-install \
--target=x86_64-efi \
--efi-directory=/mnt/efi \
--boot-directory=/mnt/usb/boot \
--removable \
--recheck
Create a live
directory on the USB device.
sudo mkdir -p /mnt/usb/{boot/grub,live}
Copy the Debian live environment files we previously generated to the USB disk.
sudo cp -r $HOME/LIVE_BOOT/image/* /mnt/usb/
Copy the grub.cfg
boot configuration to the USB
device.
sudo cp \
$HOME/LIVE_BOOT/scratch/grub.cfg \
/mnt/usb/boot/grub/grub.cfg
Now unmount the disk and you should be ready to boot from it on a UEFI system.
sudo umount /mnt/{usb,efi}
BIOS + UEFI Support
I am assuming you have an umounted blank USB
drive at /dev/sdz. To allow easily swapping in a
real block device, I am using a variable named
$disk
in these commands.
Export the disk
variable.
export disk=/dev/sdz
Create some mount points for the USB drive.
sudo mkdir -p /mnt/{usb,efi}
Partition the USB drive using parted
. This command
creates 3 partitions in a GPT (Guid Partition Table) layout. One
partition for the BIOS boot record, one for UEFI, and one for our
Debian OS and other live data.
sudo parted --script $disk \
mklabel gpt \
mkpart primary fat32 2048s 4095s \
name 1 BIOS \
set 1 bios_grub on \
mkpart ESP fat32 4096s 413695s \
name 2 EFI \
set 2 esp on \
mkpart primary fat32 413696s 100% \
name 3 LINUX \
set 3 msftdata on
Generate a hybrid MBR for the USB device. Note, this is
non-standard and so may not work on all systems. The
only
guides
I’ve
found on hybrid MBRs show that it must be done with
gdisk
. gdisk
supports commands
not in
sgdisk
, so this command is not easily scriptable. The
documentation for gdisk
warn that this procedure is
non-standard, flaky, and unsupported, but this does generally seem to do what is expected.
It allows for both BIOS and UEFI booting from the same USB device.
sudo gdisk $disk << EOF
r # recovery and transformation options
h # make hybrid MBR
1 2 3 # partition numbers for hybrid MBR
N # do not place EFI GPT (0xEE) partition first in MBR
EF # MBR hex code
N # do not set bootable flag
EF # MBR hex code
N # do not set bootable flag
83 # MBR hex code
Y # set the bootable flag
x # extra functionality menu
h # recompute CHS values in protective/hybrid MBR
w # write table to disk and exit
Y # confirm changes
EOF
Format the UEFI and data partitions.
sudo mkfs.vfat -F32 ${disk}2 && \
sudo mkfs.vfat -F32 ${disk}3
Mount the partitions.
sudo mount ${disk}2 /mnt/efi && \
sudo mount ${disk}3 /mnt/usb
Install Grub for x86_64 UEFI booting.
sudo grub-install \
--target=x86_64-efi \
--efi-directory=/mnt/efi \
--boot-directory=/mnt/usb/boot \
--removable \
--recheck
Install Grub for i386-pc booting.
sudo grub-install \
--target=i386-pc \
--boot-directory=/mnt/usb/boot \
--recheck \
$disk
Create a live
directory on the USB device.
sudo mkdir -p /mnt/usb/{boot/grub,live}
Copy the Debian live environment files we previously generated to the USB disk.
sudo cp -r $HOME/LIVE_BOOT/image/* /mnt/usb/
Copy the grub.cfg
boot configuration to the USB
device.
sudo cp \
$HOME/LIVE_BOOT/scratch/grub.cfg \
/mnt/usb/boot/grub/grub.cfg
Now unmount the disk and you should be ready to boot from it on either a BIOS or UEFI system.
sudo umount /mnt/{usb,efi}
Citations
- sgdisk(8) - Linux man page
- Hybrid UEFI GPT + BIOS GPT/MBR boot
- “No suitable mode found” error
- Where is the memtest option on the Ubuntu 64-bit live CD?
- Remastering the Install ISO
- Install GRUB2 in (U)EFI systems
- 6.4 Embedding a configuration file into GRUB
- Standalone Grub2 EFI installation - grub.cfg placement?
- actual usage of ‘grub-mkimage –config= ‘
- GRUB2 How To (4): memdisk and loopback device
- How does the grub efi loader find the correct grub.cfg and boot directory?
- How to Rescue a Non-booting GRUB 2 on Linux
- Using a CD
- Boot Linux with extlinux from EFI & GPT
- GRUB2 Modules
- grub-install.c
- Grub2/Troubleshooting
- Set up PreLoader
- Using PreLoader
- build.sh
- Archiso
- The simple menu system
- UEFI
- Make UEFI bootable live CD
- What is the proper way to use ISOLINUX with UEFI?
- Booting from removable media
- UEFI systems
- Managing EFI Boot Loaders for Linux: EFI Boot Loader Installation
- Examples
- Grub2 El-Torito CD
- Create ISO image with GRUB2
- DebianLive MultibootISO
- 11 GRUB image files
- stage2_eltorito missing
- 3.4 Making a GRUB bootable CD-ROM
- why is grub2 ignoring kernel options when boot from el torito on CD?
- Boot UEFI does not work from CD/DVD
- UEFI problem after upgrading to VMWS player 12
- make-efi
- UEFI + BIOS bootable live Debian stretch amd64 with persistence
- [syslinux] Isohybrid wiki page and UEFI