Linux To Go

# Overview

This post shows how to clone an installed Linux to your USB disk so you can use it every where in every computer that supports UEFI/GPT.

# Preparation

  • An installed Linux to be cloned
  • A helper Linux (could be a LiveCD or a real system)
  • An external disk with GPT partition table

# Convension

  • /dev/sda is the disk containing the installed Linux that will be cloned later
  • /dev/sdb is the external disk
  • /mnt/sda is the mount point of /dev/sda
  • /mnt/sdb is the mount point of /dev/sdb

# Boot into your helper Linux

  • If you are using a LiveCD Linux, you make a bootable USB with that LiveCD image and then boot your computer from the USB.

  • If you are using a real system, make sure you are not booting into the one that will be cloned later.

  • The best choice is always using a Virtual Machine 😃

# Partition your external disk

You can use fdisk or parted or gparted or what ever you want to partition your disk. You should learn how to use these partition tools by Googling.

I will assume that you have the following partition after all successful operation. note that: the EFI partition is essential because we are using UEFI/GPT

Device Type Mount point Flag
/dev/sdb1 fat32 /boot/efi esp, boot
/dev/sdb2 ext4 /
/dev/sdb3 exfat
  • The /dev/sdb1 is the EFI partition.
  • The /dev/sdb2 is the Linux root partition.
  • The /dev/sdb3 is the data partition for containing non-system files (such as your shared documents and movies).

# Copying root filesystem files

Assume that we have the following structure of /dev/sda:

Device Type Mount point Flag
/dev/sda1 fat32 /boot/efi esp, boot
/dev/sda2 ext4 /
/dev/sda3 ext4 /home

Let's do the following steps:

  • Mount /dev/sda2 on /mnt/sda
  • Mount /dev/sda3 on /mnt/sda/home
  • Mount /dev/sdb2 on /mnt/sdb

There's no need to mount the efi partition in /dev/sda1 as we will re-install grub later which will re-generate all boot files.

Then copy all files under /mnt/sda to /mnt/sdb by

sudo cp -a /mnt/sda/* /mnt/sdb

Don't forget to add the -a option, that is, keep all files' attributes (ownership, timestamp, etc.)

I don't want to use a home partition so I just merged the root and home in /dev/sda. If you would like to use a home partition, you should create a separate home partition in /dev/sdb and mount it to /mnt/sdb/home before copying files.

# Installing grub

  • Mount /dev/sdb1 to /mnt/sdb/boot/efi

And let grub to perform the installation:

sudo grub-install --target x86_64-efi --removable --boot-directory=/mnt/sdb/boot --efi-directory=/mnt/sdb/boot/efi

Now we are preparaing to chroot into the root and generate grub config. But first we should mount 3 fundamental virtual filesystems:

sudo mount --bind /dev  /mnt/sdb/dev
sudo mount --bind /sys  /mnt/sdb/sys
sudo mount --bind /proc /mnt/sdb/proc

And next step is generating grub config file. Please note that we should disable the os-probe feature because a Linux To Go should never discover and boot into systems that installed on the host's disk.

chroot /mnt/sdb
chmod -x /etc/grub.d/30_os-prober
grub-mkconfig -o /boot/grub/grub.cfg

Do not use update-grub as it will modify UEFI boot items.

# Editing /etc/fstab

Currently the /etc/fstab is corrupted as it is copied from an old disk whose UUID does not match the one now.

You can use blkid to see the UUID of /dev/sdb1 and /dev/sdb2. And we should only mount / and /boot/efi when system starts, so let's edit /etc/fstab like this:

UUID=530190fb-9486-429b-8aea-ff80a27aaa4f /               ext4    errors=remount-ro 0       1
UUID=6E98-B9EE                            /boot/efi       vfat    defaults	0	2

Where the 530190fb-9486-429b-8aea-ff80a27aaa4f and 6E98-B9EE should be your blkid of /dev/sdb2 and /dev/sdb1.

# Clean up

It's time to unmount all things and have a reboot.

sudo umount -a /mnt/sda
sudo umount -a /mnt/sdb

Power off your machine and boot from your external disk. You should see your Linux logo or dmesg now on your screen.

# Frequently Asked Questions

If grub says

grub-install: error: /usr/lib/grub/x86_64-efi/modinfo.sh doesn't exist. Please specify --target or --directory

That's because your helper Linux is installed with BIOS/MBR. You can run the following command to install required files:

sudo apt install grub2-efi-modules