Installing Xubuntu 20.04 on a USB Drive with Debootstrap

We will install Xubuntu on a USB drive without leaving our current Ubuntu installation.

Your Skills

  • You can partition a hard drive and

  • you can install packages and

  • you like the command line.

Prerequisites

Get debootstrap (see also wajig):

wajig install debootstrap

Get admin rights to eliminate the need of typing sudo before every command:

sudo -i

Find your USB drive

lsblk --fs

My USB drive is /dev/sda and I create the chroot directory at $chroot_dir::

usb_drive=/dev/sda
chroot_dir=/tmp/target
mkdir -p $chroot_dir

Partitioning

Create the following partitions:

device

mount point

size

/dev/sda1

/boot

1G

/dev/sda2

/

Rest

Choosing a partition editor

I recommend gparted.

sudo apt-get install -y gparted

Remember to make /dev/sda1 bootable!

Remember both partitions:

boot_device=${usb_drive}1
root_device=${usb_drive}2
ls $boot_device $root_device

Formatting

mkfs.ext4 -L boot $boot_device
mkfs.ext4 -L root $root_device

Tune2fs

You could disable file system checks if you wanted to:

tune2fs -c 0 -i 0 $boot_device
tune2fs -c 0 -i 0 $root_device

Check Partitions and get UUIDs

parted $usb_drive p
boot_uuid=$(blkid -o value -s UUID $boot_device)
root_uuid=$(blkid -o value -s UUID $root_device)
echo $boot_uuid $root_uuid

Mounting and Unmounting

Create and run the Bash script mountall:

cat > mountall << EOF
mkdir -p $chroot_dir
mount /dev/disk/by-uuid/$root_uuid $chroot_dir

mkdir -p $chroot_dir/boot
mount /dev/disk/by-uuid/$boot_uuid $chroot_dir/boot

mkdir -p $chroot_dir/{dev,proc,run,sys}
mount -B /dev $chroot_dir/dev
mount -B /dev/pts $chroot_dir/dev/pts
mount -t proc proc $chroot_dir/proc  # for bash completion
mount -B /run $chroot_dir/run
mount -B /sys $chroot_dir/sys
EOF

chmod +x mountall
./mountall

Create the Bash script umountall for later use:

cat > umountall << EOF
umount $chroot_dir/run
umount $chroot_dir/sys
umount $chroot_dir/dev/pts
umount $chroot_dir/dev
umount $chroot_dir/proc

umount $chroot_dir/boot
umount $chroot_dir/
EOF

chmod +x umountall

Check that everything is mounted:

mount | grep $usb_drive

Debootstrap

Choose a fast mirror and a target architecture to increase debootstrap’s download speed and install the base system::

release=focal
target=$chroot_dir
mirror=http://de.archive.ubuntu.com/ubuntu/
target_arch=amd64

debootstrap --arch $target_arch $release $target $mirror

Bemerkung

It is important to choose the right architecture in the next step. You probably want amd64 or arm. For a full list of supported architectures see http://archive.ubuntu.com/ubuntu/dists/focal/Release

New Hostname

new_hostname=x
cat > $chroot_dir/etc/hostname << EOF
$new_hostname
EOF
cat > $chroot_dir/etc/hosts <<EOF
127.0.0.1       localhost
127.0.0.1       $new_hostname
EOF

Fstab

Write fstab (the indentation will be proper after uuid substitution):

cat > $chroot_dir/etc/fstab <<EOF
# device                                   mount  type  options            freq  passno
UUID=$root_uuid  /      ext4  errors=remount-ro  0     1
UUID=$boot_uuid  /boot  ext4  errors=remount-ro  0     1
EOF

Root UUID

We’ll need to access root_uuid in the chroot environment:

mkdir -p $chroot_dir/tmp
echo $root_uuid > $chroot_dir/tmp/root_uuid

Chrooting

chroot $chroot_dir

Locale:

cat <<EOF > /etc/default/locale
LANG="en_US.UTF-8"
LANGUAGE=en_US:en
LC_NUMERIC="de_DE.UTF-8"
LC_TIME="de_DE.UTF-8"
LC_MONETARY="de_DE.UTF-8"
LC_PAPER="de_DE.UTF-8"
LC_NAME="de_DE.UTF-8"
LC_ADDRESS="de_DE.UTF-8"
LC_TELEPHONE="de_DE.UTF-8"
LC_MEASUREMENT="de_DE.UTF-8"
LC_IDENTIFICATION="de_DE.UTF-8"
EOF
locale-gen en_US.UTF-8 de_DE.UTF-8
dpkg-reconfigure locales

Set the time zone and update the system::

cp /usr/share/zoneinfo/Europe/Berlin /etc/localtime

# add universe repository for wajig and python-optcomplete
echo `cat /etc/apt/sources.list` universe > /etc/apt/sources.list

apt-get update
apt-get dist-upgrade

Install the kernel, GRUB 2, completion tools and the terminal mouse server::

apt-get install -y initramfs-tools grub-pc

apt-get install -y linux-image-generic \
    vim bash-completion wajig python-optcomplete gpm

Enable root login::

passwd

Configuring the Boot Loader

You can edit /etc/default/grub if you want, but the defaults work. Afterwards::

update-grub

Exit the chroot::

exit

Troubleshooting

Warning: The driver descriptor says the physical block size is 2048 bytes, but Linux says it is 512 bytes.

dd if=/dev/zero of=$usb_drive bs=2048 count=32 && sync

Error: /dev/sda: unrecognised disk label

parted $usb_drive
mklabel msdos