How to install a Debian Linux to USB stick from another (already running) Debian system.
Traditionally, “Live USB” is made using a “Hybrid” approach, where a
Live CD image (an
.iso file) is written to a USB drive.
And when such Live USB system boots, you get a simulated CD drive.
And I don’t quite like this “hybrid” technique, because it involves CD emulation, which seems a bit necro to me. Not to say that the CD image is hard to modify (especially from inside the running Live CD system).
What I like to do instead, is to install a first-class citizen Debian system directly onto USB drive (no CD emulation) as if it was an ordinary HDD/SSD installation. Like what is done by Debian Installer, but with no need for any installer CD.
debootstrap is the tool designed for that purpose.
It allows to install a Debian sytem from already running Debian system.
And actually, this is how Debian Installer CD works:
it boots a Debian Linux system from CD, and runs
debootstrap to install another
system on HDD. And if you have an already running Debian system,
then you don’t need a special installer. You can just call
So all you need to do that is a USB stick plugged in, and a running Debian system (Ubuntu, Mint, and other Debian-based distors are suitable).
And yes, before you start, you need to install the
debootstrap package on your host system:
~$ sudo apt-get install debootstrap
1. Prepare the device
Check the device and erase existing data
badblocks is a tool
that searches devices for bad blocks.
When I’m getting a new device into use, I usually run such check, because
otherwise, it may be an unpleasant surprise to discover a defect later,
after you put some files in there.
-w flag, it will perform a read-write test that erases all
existing data. So make sure you don’t have any important files on the
~$ sudo badblocks -s -w -t 0 /dev/sdX
-sshows the progress percentage in the console
-wmeans to perform a read-write test (default is a read-only test)
-t 0means to make the single write pass using zeros (default is to do 4 different passes)
/dev/sdX is a path to the USB stick device. In my case it is
and on your machine it may be different of course. Use
dmesg to figure
it out. And be careful, as you may erase a wrong device.
Create new partition table
Erasing the whole device means that there is no partition table
anymore. That is, if you had
/dev/sdc1 - it is gone, and now there is
/dev/sdc without any partitions. And you need to create one.
The one-liner spell below creates the single partition that occupies the whole device:
~$ echo ";" | sudo sfdisk /dev/sdX
Format the new partition
Now you need to format the new partition to create a file system in there:
~$ sudo mkfs.ext2 -L liveusb_root /dev/sdX1
-L liveusb_rootis the label (will be needed later for configuration)
I have chosen
ext2 file system because it is a native system for
Linux, and it has no journaling, so it performs less writes to my slow
USB Flash drive. If you’re installing to HDD or SSD, you probably want
ext4, or any other FS you believe is good.
Mount partition as a directory
OK, now you have an empty ready-to-use partition. You need to mount it as a directory, because later you will put in some files.
~$ sudo mkdir /mnt/liveusb ~$ sudo mount /dev/sdX1 /mnt/liveusb
debootstrap is the main tool here: it installs a Debian system from
already running Debian system.
This is how you run it:
~$ sudo debootstrap --arch=amd64 stable /mnt/liveusb
stretchis the release name. You can see the list of available release scripts in
That will create a root file system inside
(with all those
with a bunch of core
.deb packages installed.
Essentially, this is a small Debian system installed to a sub-directory.
It is not yet bootable: the bootloader and the Linux kernel itself is missing,
but it contains all necessary executable files to run a
And you soon will utilize this shell to finish the installation.
But before you can switch to the new shell, you need to copy some basic configuration from your host system.
~$ sudo cp /etc/resolv.conf /mnt/liveusb/etc/resolv.conf ~$ sudo cp /etc/locale.gen /mnt/liveusb/etc/locale.gen ~$ sudo cp /etc/default/locale /mnt/liveusb/etc/default/locale
Mount special file systems
And one more thing that will be needed later is the special virtual
/sys. They are not required to
run a shell, but some
debconf scripts (triggered when you do
install) will fail if they are missing.
So here how do you mount them:
~$ sudo mount --bind --make-rslave /dev /mnt/liveusb/dev ~$ sudo mount --bind --make-rslave /proc /mnt/liveusb/proc ~$ sudo mount --bind --make-rslave /sys /mnt/liveusb/sys
Finally, you’re ready to switch to the installed system:
~$ sudo chroot /mnt/liveusb /bin/bash
you may notice your shell prompt changed:
Now you’re insdie the target system.
It may seem strange if you didn’t work with
chroot before, but that
is right: you don’t need to reboot. If you have another Linux system
installed into some sub-directory, you can easily run a shell in there.
/mnt/liveusb is your root directory
/, and all subsequent
commands will be executed inside this isolated root environment.
3. Install packages
Now, when you’re inside your newly installed system, you can execute
any commands, including
apt install. And this is how you’re going to
But before you can install packages, you have to tune APT repository list:
cat <<EOF > /etc/apt/sources.list deb http://deb.debian.org/debian/ stable main contrib non-free deb http://deb.debian.org/debian/ stable-updates main contrib non-free deb http://deb.debian.org/debian-security stable/updates main EOF
If you want a different release, then you may want to use:
And another thing is to install localization data. This is not strictly required to operate, but it helps to avoid a bunch of noisy warning messages that printed when you install packages with missing locale data.
apt update apt upgrade apt install tzdata locales apt install localepurge
localepurge is a little trick that helps to save disk space
(useful for USB sticks).
Finally, you can use
apt to install some packages.
Here is a list of packages that I include to the base system. Mostly these are administration tools, device drivers, networking packages, and other “basic” packages useful for any installation:
apt install \ aide anacron bzip2 ca-certificates cifs-utils cryptsetup curl debootstrap \ dnsutils dosfstools e2fsprogs e2fsck-static elinks file firmware-atheros \ firmware-iwlwifi firmware-linux firmware-linux-nonfree firmware-realtek \ hdparm mcelog procinfo sysstat chkrootkit cmospwd foremost screen tmux \ secure-delete bash ecryptfs-utils ifupdown iproute2 iptables iputils-ping \ isc-dhcp-client iw kbd less linux-image-amd64 lm-sensors lshw lynx man mdadm \ lvm2 lsof htop iotop mc modemmanager nano ncurses-term net-tools netcat nmap \ ntfs-3g openssh-client openssl p7zip-full p7zip-rar pciutils pm-utils ppp \ pppconfig pppoeconf psmisc resolvconf rng-tools rsync sdparm smbclient socat \ sshfs sudo tcpdump telnet testdisk traceroute unzip usb-modeswitch usbutils \ vim wicd-curses wireless-regdb wireless-tools wpasupplicant wvdial
Configure the Bootloader
Now you have a nice Debian system with a bunch of base packages installed. But… it is not bootable yet.
In order to make the device bootable, you have to install a bootloader, Grub in my case.
But, before you install, you need to write the
(needed for configuration script executed automatically right after
cat <<EOF > /etc/fstab LABEL=liveusb_root / ext2 noatime 0 1 EOF
And now you can install the bootloader itself:
apt-get install grub2
After the installation, the configuration script will offer you a menu, where you have to choose the device to install the bootloader.
You should select your USB Stick device there (sic: the whole device, not a partition).
This is needed to actually write the bootloader code to special area on the device, which is triggered when computer boots.
Be careful to choose the right device. Otherwise, you will get a surprise after you reboot your host system.
Install desktop environment
Now, if you’re not comfortable with just bootable shell, you can also install a Desktop Environment, maybe some web browser, and any other extra packages you need:
apt-get install lxde
In my case, I don’t have enough free space on my USB Stick (it is an old device), so I skipped this step, and left my installation with only base set of CLI tools. That should be good enough for a rescue system.
You’re almost done. But before you exit, you need to leave some configuration to make the system usable after reboot.
First, some very basic networking configuration:
cat <<EOF > /etc/network/interfaces.d/lo auto lo iface lo inet loopback EOF echo liveusb > /etc/hostname sed -i 's/localhost/localhost liveusb/' /etc/hosts
And second, you need to create a user account. Otherwise, you will not be able to log in.
adduser username usermod -G sudo,netdev username
Exit from chroot
Before exit, you can clean up
.deb files download from the internet.
They are not needed after installation, so deleting them allows to win some free space on USB stick:
rm -rvf /var/cache/apt/archives/*.deb
Finally, you can exit from your
chroot environment to your host system:
After this point, you’re on your host system again.
You’re almost done. Before ejecting the USB device, you need to un-mount all the file systems:
~$ fuser --verbose --kill /mnt/liveusb/ ~$ sudo umount --recursive /mnt/liveusb/
fuser --killcommand is needed to stop background processes that are sometimes spawned during package installation.
Once you un-mounted the device, you can re-boot and test it. You should have a full-weighted first-class-citizen Debian Linux system that boots and works directly from the USB Flash device (as if it were an HDD).
The nice thing about it is that the system is writable (in contrast to hybrid Live CD/USB systems). You can install new packages and update the configuration on the fly, straight from the running system (as you normally do on a desktop system).
And the bonus nice thing is that now you leraned this
chroot techniques, and now you can make a lot:
- infest your friend’s USB sticks using
- use such USB sticks to infest more machiens with Debian
- in case you break something, you can boot from such USB stick and then use
chrootto switch to the broken system, and maybe even fix it
There is a lot of useful uses.
This whole technique can only work if your host architecture matches the target architecture.
If you have an
amd64 host, and for example you want to bootstrap an
armel system, then you’re in trouble.
This is possible (using multistrap),
but the process is commplicated, and it is really easier to download
a prepared virtual machine image (ir an
.iso file) in this case.
BIOS vs UEFI
This guide assumes you have a motherboard that supports BIOS bootloader mechanism. Yes, it is a bit old, but it is simple, and it is still the lowest common denominator. Majority of motherboards (I’ve seen to this day) do support BIOS mode booting, at least as a compatibility option.
If you want to use UEFI (which I do recommend honestly),
then the process will be slightly more complicated: you will need to allocate a special system partition,
grub-efi, and configure it differently, and so on.
I’ve omitted this option for simplicitly, because the text is already long.
The described technique involves running
apt install on a USB Flash drive.
If the device is slow, the instllation process may take hours.
To speed it up, I prefer to do this whole process in a temporary directory on my main SSD, and then copy it to USB stick at the very last moment.
But this scenario is more complicated: you have to enter/exit
multiple times, and mount-unmount file systems, and maybe some extra
Grub bootloader manipulations, and so on. So I omitted it for
simplicity, but you can try it.