Installing Kubuntu 14.04 on a USB Drive with Debootstrap#

We will install Ubuntu 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 Wajig (Package Management)):

wajig install debootstrap

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

sudo -i

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

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

Partitioning#

Create the following partitions:

device

mount point

size

/dev/sdc1

/boot

150M

/dev/sdc2

/

Rest

Remember to make /dev/sdc1 bootable!

Using parted:

 1parted $usb_drive p
 2parted $usb_drive << EOF
 3rm 1
 4mkpart primary ext4 0% 150M
 5mkpart primary ext4 150M 100%
 6align-check opt 1
 7align-check opt 2
 8set 1 boot on
 9EOF
10fdisk -l $usb_drive

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)
[[ -n $boot_uuid && -n $root_uuid ]] || echo 'Both must be set'

Mounting and Unmounting#

Create and run the Bash script mountall:

 1cat > mountall << EOF
 2mkdir -p $chroot_dir
 3mount /dev/disk/by-uuid/$root_uuid $chroot_dir
 4
 5mkdir -p $chroot_dir/boot
 6mount /dev/disk/by-uuid/$boot_uuid $chroot_dir/boot
 7
 8mkdir -p $chroot_dir/{dev,proc,run,sys}
 9mount -B /dev $chroot_dir/dev
10mount -B /dev/pts $chroot_dir/dev/pts
11mount -t proc proc $chroot_dir/proc  # for bash completion
12mount -B /run $chroot_dir/run
13mount -B /sys $chroot_dir/sys
14EOF
15
16chmod +x mountall
17./mountall

Create the Bash script umountall for later use:

 1cat > umountall << EOF
 2umount $chroot_dir/run
 3umount $chroot_dir/sys
 4umount $chroot_dir/dev/pts
 5umount $chroot_dir/dev
 6umount $chroot_dir/proc
 7
 8umount $chroot_dir/boot
 9umount $chroot_dir/
10EOF
11
12chmod +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=precise
target=$chroot_dir
mirror=http://de.archive.ubuntu.com/ubuntu/
target_arch=amd64

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

Note

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

New Hostname#

new_hostname=port
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#

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 root_uuid in the chroot environment:

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

Chrooting#

chroot $chroot_dir

Locale:

 1cat <<EOF > /etc/default/locale
 2LANG="en_US.UTF-8"
 3LANGUAGE=en_US:en
 4LC_NUMERIC="de_DE.UTF-8"
 5LC_TIME="de_DE.UTF-8"
 6LC_MONETARY="de_DE.UTF-8"
 7LC_PAPER="de_DE.UTF-8"
 8LC_NAME="de_DE.UTF-8"
 9LC_ADDRESS="de_DE.UTF-8"
10LC_TELEPHONE="de_DE.UTF-8"
11LC_MEASUREMENT="de_DE.UTF-8"
12LC_IDENTIFICATION="de_DE.UTF-8"
13EOF
14locale-gen en_US.UTF-8 de_DE.UTF-8
15dpkg-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

Making It Bootable#

MBR:

grub-install --root-directory=$chroot_dir --no-floppy --recheck $usb_drive

Unmount:

./umountall

That’s it! Exit the sudo -i:

exit

Troubleshooting#

GRUB#

See also http://www.gnu.org/software/grub/manual/grub.html#Troubleshooting.

15 : File not found#

  • Check if vmlinuz-<kernel-version> exists in /boot

  • Check kernel line. Should be kernel /vmlinuz-<kernel-version> root=UUID=<root_uuid> vga=791, because /boot has it’s own partition. If it is just a directory under /, it should read kernel /boot/vmlinuz-<kernel-version> root=UUID=<root_uuid> vga=791.

17 : Cannot mount selected partition#

Play with root (hd<disk-number>,<partition-number>. GRUB will show you 21 : Selected disk does not exist or 22 : No such partition when you try a disk/partition that does not exist.

Ramdisk Image#

thanks, skrewz [1]:

kernel_version=2.6.28-11-generic
cd /tmp && rm -Rf w; mkdir w && cd w && cp $chroot_dir/boot/initrd.img-$kernel_version i.cpio.gz && gunzip i.cpio.gz && cpio --extract --file=i.cpio && rm i.cpio
ls

Notes#

  • 2013-12-31 I had to use UUIDs only (in chroot fstab and from the outside). Else I would get the error:

    /usr/sbin/grub-probe: error: cannot find a GRUB drive for /dev/sdc1.  Check
    your device.map.
    Auto-detection of a filesystem of /dev/sdc1 failed.
    Try with --recheck.
    If the problem persists please report this together with the output of
    "/usr/sbin/grub-probe --device-map="/tmp/target/boot/grub/device.map"
    --target=fs -v /tmp/target/boot/grub" to <bug-grub@gnu.org>
    

Further Reading#