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 readkernel /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#
Articles can be found on pendrivelinux or through Google; there are even some “official” tools.
https://help.ubuntu.com/community/FeistyEncryptedRootWithInstaller/#Chroot%20and%20configure