These are steps that I used on an Ubuntu 16.04.2 LTS (Xenial Xerus) 64-bit system to build a custom x86 Debian 9 (Stretch) live environment that I can boot from a USB drive.

These steps are a bit unique from other guides I've written on this topic. The key difference is that these steps allow you to create a USB drive with a hybrid boot record.

The benefit of a hybrid boot partition table configuration is that the MBR and GPT records can be used to boot on both an EFI and a BIOS system.

That means that this USB disk can be used on both Apple Macs and Windows/generic PCs!

Hybrid boot records come with some warnings. They are not officially supported and may not work on all systems. However, they are commonly used and worked perfectly fine in my testing.

Please also note that Debian 8 (Jessie) and older will not work as a valid target OS with these steps. Try as I did, I could not get Apple touchpad (clickpad) support working unless I used Debian 9. I'm sure it is possible, but you are better off using a more modern OS to save yourself the hassle if you plan to support Macs.

Configure Debian

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 cause issues.

  1. Install applications we need to build the environment.

    sudo apt-get install \
        debootstrap syslinux isolinux squashfs-tools \
        genisoimage memtest86+ rsync gdisk \
        grub2-common grub-efi-amd64
    
  2. Set up the base Debian environment. I am using Stretch for my distribution and i386 for the architecture. Please change your mirror if you are not in the U.S. or know of a mirror close to you.

    # Create a directory for the live environment.
    mkdir $HOME/live_boot
    
    sudo debootstrap \
        --arch=i386 \
        --variant=minbase \
        stretch $HOME/live_boot/chroot http://ftp.us.debian.org/debian/
    
  3. Chroot to our Debian environment.

    sudo chroot $HOME/live_boot/chroot
    
  4. chroot

    Set a custom hostname for your Debian environment.

    echo "debian-live" > /etc/hostname
    
  5. chroot

    Figure out which Linux Kernel you want in your live environment.

    apt-cache search linux-image
    
  6. chroot

    I chose the image linux-image-586. 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 --yes --force-yes \
        linux-image-586 live-boot systemd-sysv
    
  7. 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.

    apt-get install --no-install-recommends --yes --force-yes \
        network-manager net-tools wireless-tools wpagui \
        tcpdump wget openssh-client \
        blackbox xserver-xorg-core xserver-xorg x11-xserver-utils \
        xinit xterm \
        pciutils usbutils gparted ntfs-3g hfsprogs rsync dosfstools \
        syslinux partclone nano pv \
        rtorrent iceweasel chntpw && \
    apt-get clean
    
  8. chroot

    Set the root password (my only user will be root in the live environment)

    passwd root
    
  9. chroot

    exit
    
  10. Make directories that will be copied to our bootable medium.

    mkdir -p $HOME/live_boot/image/
    
  11. Compress the chroot environment into a Squash filesystem.

    sudo mksquashfs \
        $HOME/live_boot/chroot \
        $HOME/live_boot/image/filesystem.squashfs \
        -noappend \
        -e boot
    
  12. Copy our kernel and initramfs outside the chroot.

    cp $HOME/live_boot/chroot/boot/vmlinuz-4.9.0-2-686 \
        $HOME/live_boot/image/vmlinuz1 && \
    cp $HOME/live_boot/chroot/boot/initrd.img-4.9.0-2-686 \
        $HOME/live_boot/image/initrd1
    

USB

I am assuming that the USB drive you plan to use is at /dev/sdf. You must replace any instance of /dev/sdf in these steps with the with the location of your USB device or you may accidentally lose data.

  1. Ensure none of your USB drive partitions are mounted.

    sudo umount /dev/sdf*
    
  2. Wipe partition information from your USB drive.

    sudo wipefs -a /dev/sdf
    

    If you want to ensure your drive is totally wiped, you can do something like this to delete all data (including partition tables). This is a bit brute force and time consuming.

    sudo dd if=/dev/zero of=/dev/sdf
    
  3. Create some mount points that we will need.

    sudo mkdir -p /mnt/{usb,efi}
    
  4. Partition the USB drive using sgdisk. This command creates 3 partitions. One for the BIOS boot record, one for EFI, and one for our OS/data.

    sudo sgdisk \
        --new=1:2048:4095 \
            --typecode=1:ef02 \
            --change-name=1:"BIOS" \
            /dev/sdf \
        --new=2:4096:413695 \
            --typecode=2:ef00 \
            --change-name=2:"EFI" \
            /dev/sdf \
        --new=3:413696:`sgdisk -E /dev/sdf` \
            --typecode=3:8300 \
            --change-name=3:"LINUX" \
            /dev/sdf
    
  5. Set up the hybrid partition records. I used this Arch Linux article as a guide.

    Unfortunately, sgdisk cannot be used to script this operation, because, "If the active/bootable flag should be set, you must do so in another program..."

    sudo gdisk /dev/sdf << EOF
    r
    h
    1 2 3
    N
    EF
    N
    EF
    N
    83
    Y
    x
    h
    w
    Y
    EOF
    
  6. Format the partitions.

    sudo mkfs.vfat -F32 -n EFI /dev/sdf2
    
    sudo mkfs.vfat -F32 -n LINUX /dev/sdf3
    
  7. Mount the partitions.

    sudo mount /dev/sdf2 /mnt/efi
    
    sudo mount /dev/sdf3 /mnt/usb
    
  8. Install the boot records.

    sudo grub-install \
        --target=x86_64-efi \
        --efi-directory=/mnt/efi \
        --boot-directory=/mnt/usb/boot \
        --removable \
        --recheck
    
    sudo grub-install \
        --target=i386-pc \
        --boot-directory=/mnt/usb/boot \
        --recheck \
        /dev/sdf
    
  9. Copy the Debian live environment we created to the USB disk.

    sudo rsync -rv $HOME/live_boot/image/ /mnt/usb/live/
    
  10. Delete the existing grub.cfg entry if there is one.

    sudo rm -f /mnt/usb/boot/grub/grub.cfg
    
  11. Create a new grub.cfg entry.

    sudo nano /mnt/usb/boot/grub/grub.cfg
    

    It should look like this.

    set default="0"
    set timeout=10
    
    menuentry "Debian Live x86" {
        linux /live/vmlinuz1 boot=live
        initrd /live/initrd1
    }
    
  12. Now unmount the disk and you should be ready to boot from it and go.

    sudo umount /dev/sdf*
    

Helpful documents: