Create a debian bootable live USB
Updated 2019-06-25: use Debian Stretch explicitly (already implied by kernel version); suggest testing with qemu.
We can install a full Linux distribution in a USB drive, and use it to boot a system. That is called a "live USB," and it can be used for recovery, as a portable environment, etc.
In this article we explain how to install a Debian GNU/Linux OS in a USB drive as if it was a hard disk. We will use Debian's own debootstrap to populate the root partition and syslinux as a bootloader (it is simpler than the standard grub).
Obs: to ease copy-and-pasting, we show the commands without prompt, and
prepend >
to the output of commands on most examples.
1 Partitioning
After inserting the USB drive, it will appear as a block device under /dev, usually sd[a-z]. Take a note on the device name. We will use /dev/sdc through the examples.
Create two partitions on our USB drive: one with 256MB for the /boot that will hold the syslinux bootloader and the Linux kernel; and another with all the rest of the space, that will hold the root filesystem.
There are many utilities you can use to partition the USB drive: parted, fdisk, etc.
For example, using fdisk, run it on /dev/sdc:
fdisk /dev/sdc > Welcome to fdisk (util-linux 2.25.2). > Changes will remain in memory only, until you decide to write them. > Be careful before using the write command.
You are left at fdisk's command prompt. Create the boot partition:
Command (m for help): n > Partition type > p primary (0 primary, 0 extended, 4 free) > e extended (container for logical partitions) > Select (default p): p > Partition number (1-4, default 1): 1 > First sector (2048-31350782, default 2048): > Last sector, +sectors or +size{K,M,G,T,P} (2048-31350782, default 31350782): +256M > > Created a new partition 1 of type 'Linux' and of size 256 MiB.
Set its type to FAT16:
Command (m for help): t > Selected partition 1 > Hex code (type L to list all codes): 6 > If you have created or modified any DOS 6.x partitions, please see the fdisk documentation for additional information. > Changed type of partition 'Linux' to 'FAT16'.
Mark it as active:
Command (m for help): a > The bootable flag on partition 1 is enabled now.
Create the root partition:
Command (m for help): n > Partition type > p primary (1 primary, 0 extended, 3 free) > e extended (container for logical partitions) > Select (default p): p > Partition number (2-4, default 2): 2 > First sector (526336-31350782, default 526336): > Last sector, +sectors or +size{K,M,G,T,P} (526336-31350782, default 31350782): > > Created a new partition 2 of type 'Linux' and of size 14.7 GiB.
Check that they were created:
Command (m for help): p > Disk /dev/sdc: 15 GiB, 16051600896 bytes, 31350783 sectors > Units: sectors of 1 * 512 = 512 bytes > Sector size (logical/physical): 512 bytes / 512 bytes > I/O size (minimum/optimal): 512 bytes / 512 bytes > Disklabel type: dos > Disk identifier: 0x13090bb3 > > Device Boot Start End Sectors Size Id Type > /dev/sdc1 * 2048 526335 524288 256M 6 FAT16 > /dev/sdc2 526336 31350782 30824447 14.7G 83 Linux
Save and exit:
Command (m for help): w > The partition table has been altered. > Calling ioctl() to re-read partition table. > Syncing disks.
We now have a /dev/sdc1 that will be our /boot, and /dev/sdc2 that will be our root file system. Observe that the boot partition has a MS-DOS type - that is required syslinux.
(the instructions above are heavily based on using-syslinux-to-boot-debootstraped)
2 Installing the bootloader
Create a FAT16 filesystem on the boot device:
mkdosfs -n LINUXBOOT /dev/sdc1 > mkfs.fat 3.0.27 (2014-11-12)
Install syslinux on it:
syslinux /dev/sdc1
3 Installing the base system in the root partition
Create the filesystem:
mkfs.ext4 /dev/sdc2 > mke2fs 1.42.12 (29-Aug-2014) > Creating filesystem with 3853055 4k blocks and 964768 inodes > Filesystem UUID: 68d66fd5-97f2-46ed-aee6-dad6f228a172 > Superblock backups stored on blocks: > 32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208 > > Allocating group tables: done > Writing inode tables: done > Creating journal (32768 blocks): done > Writing superblocks and filesystem accounting information: done
You can use any filesystem here, as long as it is supported by your future kernel.
Mount both partitions and use debootstrap to install the base files on it:
mkdir -p usbroot mount -t auto /dev/sdc2 usbroot mkdir -p usbroot/boot mount -t auto /dev/sdc1 usbroot/boot debootstrap stretch usbroot http://ftp.debian.org/debian > I: Retrieving Release.gpg > I: Checking Release signature > I: Valid Release signature (key id 75DDC3C4A499F1A18CB5F3C8CBF8D6FD518E17E1) > I: Retrieving Packages > I: Validating Packages > I: Resolving dependencies of required packages... > I: Resolving dependencies of base packages... > I: Found additional required dependencies: acl adduser dmsetup insserv libaudit1 libaudit-common libbz2-1.0 libcap2 libcap2-bin libcryptsetup4 libdb5.3 libdebconfclient0 libdevmapper1.02.1 libgcrypt20 libgpg-error0 libkmod2 libncursesw5 libprocps3 libsemanage1 libsemanage-common libslang2 libsystemd0 libudev1 libustr-1.0-1 procps systemd systemd-sysv udev > I: Found additional base dependencies: libdns-export100 libffi6 libgmp10 libgnutls-deb0-28 libgnutls-openssl27 libhogweed2 libicu52 libidn11 libirs-export91 libisccfg-export90 libisc-export95 libmnl0 libnetfilter-acct1 libnettle4 libnfnetlink0 libp11-kit0 libpsl0 libtasn1-6 > I: Checking component main on http://ftp.debian.org/debian... > I: Retrieving acl 2.2.52-2 > (...) > I: Configuring libc-bin... > I: Configuring systemd... > I: Base system installed successfully.
4 On-root configuration
We will have to chroot into our root filesystem to configure it further.
Mount the boot device and the default ones inside the root mount point:
mount -t devtmpfs dev usbroot/dev mount -t devpts devpts usbroot/dev/pts mount -t proc proc usbroot/proc mount -t sysfs sysfs usbroot/sys
chroot into root:
chroot usbroot /bin/bash
Set the root user password:
passwd > Enter new UNIX password: > Retype new UNIX password: > passwd: password updated successfully
Install the Linux kernel and other important packages:
apt-get install --no-install-recommends -y linux-image-amd64 syslinux busybox-static > Reading package lists... Done > Building dependency tree... Done > The following extra packages will be installed: > initramfs-tools klibc-utils libklibc libuuid-perl linux-base linux-image-4.9.0-9-amd64 > Suggested packages: > bash-completion linux-doc-3.16 debian-kernel-handbook grub-pc grub-efi extlinux > Recommended packages: > busybox busybox-initramfs busybox-static firmware-linux-free irqbalance > The following NEW packages will be installed: > initramfs-tools klibc-utils libklibc libuuid-perl linux-base linux-image-4.9.0-9-amd64 linux-image-amd64 > 0 upgraded, 7 newly installed, 0 to remove and 0 not upgraded. > Need to get 34.1 MB of archives. > After this operation, 164 MB of additional disk space will be used. > (...) > Setting up linux-image-amd64 (3.16+63) ... > Processing triggers for initramfs-tools (0.120) ... > ln: failed to create hard link '/boot/initrd.img-4.9.0-9-amd64.dpkg-bak' => '/boot/initrd.img-4.9.0-9-amd64': Operation not permitted > update-initramfs: Generating /boot/initrd.img-4.9.0-9-amd64
We now have to set up our mount points in the /etc/fstab of the USB drive, but if we simply use /dev/sdc* as the devices, we will have trouble mounting it on other systems with a different number of hard drives. To have stable mount points, we use the UUID - universal unique identifiers - of the filesystems. Use blkid to find out the values of your identifiers:
blkid > (...) > /dev/sdc1: SEC_TYPE="msdos" UUID="2420-26B1" TYPE="vfat" PARTUUID="13090bb3-01" > /dev/sdc2: UUID="68d66fd5-97f2-46ed-aee6-dad6f228a172" TYPE="ext4" PARTUUID="13090bb3-02"
In this example, the UUID of the boot filesystem is 2420-26B1
, and the
UUID of the root filesystem is 68d66fd5-97f2-46ed-aee6-dad6f228a172
. Use
them to populate /etc/fstab:
echo 'UUID=68d66fd5-97f2-46ed-aee6-dad6f228a172 / ext4 defaults,noatime 0 0' > etc/fstab echo 'UUID=2420-26B1 /boot vfat defaults 0 0' >> etc/fstab
Figure out the name of the kernel and initrd installed on the boot partition:
ls boot/vmlinuz* boot/initrd* > boot/initrd.img-4.9.0-9-amd64 boot/vmlinuz-4.9.0-9-amd64
And use them with the UUIDs to create the boot/syslinux.cfg
file, with
the following contents:
default linux timeout 1 prompt 1 label linux kernel vmlinuz-4.9.0-9-amd64 append initrd=initrd.img-4.9.0-9-amd64 root=UUID=68d66fd5-97f2-46ed-aee6-dad6f228a172 ro
Finally, write syslinux's master boot record on the USB drive:
cat /usr/lib/SYSLINUX/mbr.bin > /dev/sdc
5 Closing up
We are now ready to leave the chroot and umount all devices:
exit umount usbroot/dev/pts umount usbroot/dev umount usbroot/proc umount usbroot/sys umount usbroot/boot umount usbroot
We can test our system using qemu:
qemu-system-x86_64 -m 512 -hda /dev/sdc
We should be able to login as root, with the password we set above.
If everything is working as expected, we can now remove the USB drive and use it to boot any computer.
References
This article is, in fact, basically a rehash of the following references with the UUID part added.
- http://allskyee.blogspot.com.br/2014/01/using-syslinux-to-boot-debootstraped.html
- http://quietsche-entchen.de/cgi-bin/wiki.cgi/ariane/BootableUsbStick
I've also created a gist that's easy to change, with the commands in this article.