1. Overview

As Linux users, we might want to clone or move our Linux installation from one device to another as it enables us to use an already configured setup on new hardware. It also means that we can bypass the hassle of configuring a new system from scratch.

In this tutorial, we’ll discuss the step-by-step process that we can follow to clone a Linux installation from one machine to another.

We’ll provide a unique name for each of the devices that we’ll be using in this process:

  • SOURCE: current device
  • DESTINATION: device that we’re cloning to

Since this is a multi-step process, let’s summarize it first.

2. Process Summary

The process that we’re going to follow includes a number of important steps that need to be carried out in order:

  1. bind mount the root filesystem (/) to /mnt/src on SOURCE
  2. create a .tar archive of the filesystem at /mnt/src and copy it to a storage drive
  3. install and boot into a new distro on DESTINATION
  4. create a destination (/dev/sdb1) and an EFI (/dev/sdb2) partition on DESTINATION
  5. mount new partitions (/dev/sdb1 -> /dest, /dev/sdb2 -> /efi)
  6. extract the filesystem from the archive on the storage drive (/media) to /dest
  7. making the extracted filesystem (/dest) bootable and booting into it
  8. performing post-clone configurations

Now, let’s start the process.

3. Bind Mounting the SOURCE Root Filesystem

The first step in the process is to bind mount the root filesystem (/) on SOURCE. The bind mount operation remounts a mounted filesystem to a different mount point. After the operation, the filesystem at the new mount point will be automatically updated whenever the filesystem on the initial mount point is updated.

In this case, we’re going to remount the root filesystem (/) to another mount point /mnt/src. This enables us to clone the filesystem on /mnt/src without touching /.

So, let’s perform the bind mount operation:

$ sudo mount --bind / /mnt/src

The –bind option tells the mount command to perform a bind mount operation instead of a regular mount operation. Thus, this mount command bind mounts the filesystem on / to /mnt/src.

4. Creating a .tar Archive of the SOURCE Root Filesystem

The next step is to create a .tar archive to store the root filesystem. Before proceeding, let’s note two things:

  • the tar command that we’ll use to create the archive doesn’t preserve all file metadata, but it does preserve the ownership and file permissions (special, read, write, and execute)
  • there needs to be enough space on the system for the archive creation to succeed

Let’s now create the root filesystem archive:

$ sudo tar -c /mnt/src > root.tar

The -c option, short for –create, creates a .tar archive of the /mnt/src directory. Then, the shell redirection operator (>) sets root.tar as the name of the archive.

Once the archive is created, we copy it to a storage drive, e.g., USB storage. This helps us extract the filesystem from the archive to DESTINATION.

5. Installing and Booting OS on DESTINATION

To have an environment on DESTINATION, we’ll prepare a medium on SOURCE and install the same OS on DESTINATION.

5.1. Prepare Installation Medium on SOURCE

So, let’s download the latest LTS (Long-Term Support) version of the distribution that we used on SOURCE. In this case, we use Ubuntu, so we’ll navigate to Ubuntu’s official downloads page and download the latest Ubuntu LTS release from there. After downloading, we’ll note its storage location for future reference.

Next, we attach a mounted storage drive to the machine and write a command in the terminal:

$ sudo fdisk -l

The fdisk command with the -l option, short for –list, lists all the existing partitions in the system. We’ll use this list to note the path of the newly attached storage drive.

Then, we use the dd command to copy the downloaded release to the storage drive:

$ sudo dd if=/home/user/ubuntu-22.04.3.iso of=/media

Here, the if field specifies the path of the downloaded release, i.e., /home/user/ubuntu-22.04.3.iso and the of field specifies the path of the storage drive, i.e., /media.

5.2. Install OS and Boot on DESTINATION

After copying, we restart the machine and install Ubuntu on a drive separate from the system drive. This enables us to copy the filesystem to a new drive without touching the root drive. Once the installation is complete, we boot into the freshly installed distro on DESTINATION.

Now, we’re ready to use DESTINATION for the cloning operation.

6. Creating New Partitions on DESTINATION

First, we determine if DESTINATION is an MBR or an EFI machine by listing the contents of the /sys/firmware directory:

$ cd /sys/firmware
$ ls
acpi  devicetree  dmi  efi  memmap

Since efi is listed in the terminal, DESTINATION is an EFI machine.

If it’s not listed, then the machine is usually an MBR machine.

6.1. Creating a Destination Partition

On DESTINATION, we create a new destination partition on the drive where we installed the newly downloaded OS (/dev/sdb).

So, let’s create a partition on /dev/sdb:

$ parted /dev/sdb
(parted) mklabel gpt
(parted) mkpart primary 0 10TB

Evidently, the partition creation process consists of three steps:

  1. parted initiates partition creation on /dev/sdb
  2. mklabel creates a GPT partition table
  3. mkpart makes a new primary partition with a starting value of 0 and an ending value of 10TB

On MBR machines, we’ll use msdos instead of gpt to create an MS-DOS partition table:

$ mklabel msdos

After completing the above steps, a new partition /dev/sdb1 should now be available.

6.2. Creating a Partition for EFI Data Storage (Only EFI Machines)

Since DESTINATION is an EFI machine, we also have to create a new EFI partition on /dev/sdb, which we’ll bind mount to the cloned filesystem’s /boot directory. It will store all the EFI-related data on both /dev/sdb and the filesystem.

This step is essential to making the filesystem bootable, which we’ll perform later in the process.

To create the future EFI partition, we follow the same steps as in the previous section. The only difference is that the partition has an ending value of 1TB:

$ parted /dev/sdb
(parted) mkpart primary 0 1TB

After running the above command, a partition /dev/sdb2 should now be available on /dev/sdb that we’ll later use for EFI data storage.

7. Mounting the Partitions

The next step is to mount the newly created partitions to different mount points on the system.

First, let’s note their paths:

$ sudo fdisk -l

Second, let’s create two directories named /dest and /efi in the root directory (/):

$ mkdir /dest
$ mkdir /efi

Then, let’s use the mount command to mount the destination partition (/dev/sdb1) to /dest and the EFI partition (/dev/sdb2) to /efi:

$ sudo mount /dev/sdb1 /dest
$ sudo mount /dev/sdb2 /efi

Since the partitions are now mounted, we’ll refer to /dest as the destination partition and /efi as the EFI partition.

8. Extracting the Filesystem From the .tar Archive

At this point, we can extract the filesystem from the .tar archive created earlier on SOURCE to DESTINATION. To do this, we first attach and mount the storage drive containing the archive to DESTINATION and use the fdisk command to note its path:

$ sudo mount /dev/sdb3 /media

Above, the mount command mounts the attached storage drive (/dev/sdb3) to /media.

Next, we’ll use the tar command to extract the filesystem from the archive to the destination partition (/dest):

$ cd /dest
$ sudo tar -x -f /media/root.tar

The -f option, short for –file, specifies the target archive, i.e., root.tar, which we mentioned using its path. Then, the -x option, short for –extract, makes tar extract the filesystem from the specified archive to the current directory (/dest).

We then bind mount some directories from / to /dest to make the filesystem act like an actual Linux installation:

$ sudo mount --bind /dev /dest/dev
$ sudo mount --bind /dev/pts /dest/dev/pts
$ sudo mount --bind /proc /dest/proc
$ sudo mount --bind /sys /dest/sys
$ sudo mount --bind /run /dest/run

Since DESTINATION is an EFI machine, we also bind mount /efi to /dest/boot/efi:

$ cd dest
$ mkdir boot/efi
$ sudo mount --bind /efi /dest/boot/efi

Let’s proceed to the next step.

9. Making the Filesystem Bootable

The last step is to make the filesystem (/dest) bootable. Before that, we use the chroot command to make it the current root of the system:

$ sudo chroot /dest

Then, we install GRUB as the bootloader in the root directory (/), which makes the filesystem (/dest) bootable. To do this, we first have to install the GRUB utility:

$ sudo apt install grub-efi

On an MBR machine, we just have to replace grub-efi with grub-pc to install the utility:

$ sudo apt install grub-pc

After the installation, we use the grub-install command to install GRUB as the bootloader on / and make /dest bootable. However, we have to provide the device name (/dev/sdb) of the root directory (/) instead of its path:

$ sudo grub-install /dev/sdb

Now, we simply restart the machine to boot into the freshly cloned Linux installation on DESTINATION.

10. Performing Post-Clone Configurations

After booting into the cloned installation, we have to make some configurations that ensure that the installation is working smoothly on DESTINATION.

Let’s discuss them one by one.

10.1. New Drivers

Since we cloned the filesystem, a lot of new drivers that are incorporated into DESTINATION may not be installed on the new system.

In this case, we can simply navigate to Software & Updates -> Additional Drivers and install the new drivers from there.

10.2. Key Regeneration

When we move an installation from one device to another, we can copy the same key from the old device to the new device. However, we’ll have to generate a new key on the new device in case the key on the old one gets compromised or is still in use.

To avoid this problem, we can have a separate key on each device. To generate a new key on DESTINATION, we first navigate to the /.ssh directory in the filesystem:

$ cd /home/user/.ssh

Then, we remove the id_rsa and id_rsa.pub keys located in the directory:

$ rm id_rsa id_rsa.pub

Finally, we can generate a new key on DESTINATION.

10.3. Hardware Differences

There can be hardware differences between the old and the new devices. The point to note here is that the applications that are located in the filesystem on DESTINATION run smoothly if the hardware on the new device is supported.

If an application doesn’t work as intended, we can do two things:

  • install one of its hardware-supported versions on DESTINATION
  • navigate to Software & Updates -> Additional Drivers and update the hardware drivers from there

So, we’re pretty much done configuring the installation on DESTINATION. Now, we can start using the freshly cloned installation on the new device.

11. Conclusion

In this article, we had a detailed discussion on how to clone or move a Linux installation from one device to another.

We talked about the step-by-step process for cloning the installation from SOURCE to DESTINATION and went through the post-clone configurations that we have to make to keep the cloned installation running smoothly on DESTINATION.

Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.