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:
- bind mount the root filesystem (/) to /mnt/src on SOURCE
- create a .tar archive of the filesystem at /mnt/src and copy it to a storage drive
- install and boot into a new distro on DESTINATION
- create a destination (/dev/sdb1) and an EFI (/dev/sdb2) partition on DESTINATION
- mount new partitions (/dev/sdb1 -> /dest, /dev/sdb2 -> /efi)
- extract the filesystem from the archive on the storage drive (/media) to /dest
- making the extracted filesystem (/dest) bootable and booting into it
- 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:
- parted initiates partition creation on /dev/sdb
- mklabel creates a GPT partition table
- 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.