0

I have an existing system with partitions but want to move them to a new device. The new device may be smaller and be connected to the system differently then the existing device. How do I move the partitions and file systems on them and keep a booting system?

0

With a standard set of tools drives can be copied along with the Linux OS. There are some considerations to take with distributions but for the most part this works on any distribution. In our example we will move from an HDD to an SSD that is also smaller than the HDD.

Gather information about the partitions and file systems.

Partition/block device layout:

lsblk -o NAME,VENDOR,SERIAL,FSTYPE,MODEL,SIZE,TYPE,MOUNTPOINT

Determine the partitions you will be working on and the receiving disk.

ls /dev/disk/by-id/

Based on the information from lsblk write down a set of /dev/disk paths to your exiting partitions and the receiving disk. Noting that VENDOR from lsblk is actually the busname.

/dev/disk/by-id/[busname]-[model]_[serial]-partX

For example:

/dev/disk/by-id/usb-hdd1000_1234-part1
/dev/disk/by-id/usb-hdd1000_1234-part2
/dev/disk/by-id/usb-hdd1000_1234-part3
/dev/disk/by-id/usb-hdd1000_1234-part4
/dev/disk/by-id/usb-hdd1000_1234-part5

And the source and receiving disk:

/dev/disk/by-id/usb-hdd1000_1234
/dev/disk/by-id/ata-ssd1000_1234

Confirm these are the devices you expect with ls -la:

ls -la /dev/disk/by-id/usb-hdd1000_1234
  /dev/disk/by-id/usb-hdd1000_1234 -> ../../sda
ls -la /dev/disk/by-id/ata-ssd1000_1234
  /dev/disk/by-id/ata-ssd1000_1234 -> ../../sdb

Decide on a desirable partition layout

For example

Device size: 256GiB
1 EFI     256MiB
2 Linux    20GiB
3 Windows  80GiB
4 Data    139.75GiB
5 Swap     16GiB

Refer to other questions for what sorts of partitions you need or should have for your specific system. However make sure all your partitions are aligned to 4K sectors especially if you are moving to an SSD. To do this adjust the size of each partition so that its divisible by 4KiB.

Create new partitions

We can use fdisk or parted among others. We'll just cover these and only GPT for now. Using the example partition layout:

fdisk /dev/disk/by-id/ata-ssd1000_1234

g For new GPT partition table

n For new partition

ENTER For default partition number.

ENTER For default start sector.

+256M For a 256MiB (M) ahead of the start sector (+).

t 1

1

For EFI System fs type.

Type codes include:

1 EFI System - Needed on EFI systems for booting
4 BIOS Boot - Used for executable data on BIOS mode GPT disks
11 Microsoft Basic Data - Used for most Windows data partitions including NTFS
20 Linux file system - Used for all Linux based file systems except swap. Other types exist for special volume types like RAID (29) and LVM (31).
19 Linux swap - for swap partitions

Repeat for the other partitions.

OR with parted:

parted
> select /dev/disk/by-id/ata-ssd1000_1234
> mktable gpt
> mkpart ESP fat32 1MiB 513MiB
> set 1 boot on
> mkpart primary ext4 513MiB 20737MiB
> mkpart primary ntfs 20737MiB 102657MiB
> mkpart primary ext4 102657MiB 245761MiB
> mkpart primary linux-swap 245761MiB 262145MiB

Determine if any file systems need resizing

If the receiving disk is smaller or some smaller partitions are desired then the existing file systems needs to be shrunk down.

File system utilization:

dh -h

Determine that the file system has enough free space to do this. If the file system is NTFS consider using Disk Management on Windows instead.

For example we'll resize the Linux partition which /dev/disk/by-id/usb-hdd1000_1234-part2

e2fsck -f /dev/disk/by-id/usb-hdd1000_1234-part2
resize2fs /dev/disk/by-id/usb-hdd1000_1234-part2 20G

If you're not sure of the exact size just fudge the size to something obviously smaller than the expected new partition size. The file system can be expanded to the exact size later.

resize2fs /dev/disk/by-id/usb-hdd1000_1234-part2 19G

OR Get within about 500MiB 19 GiB = 19456MiB + 500MiB = 19956 MiB

resize2fs /dev/disk/by-id/usb-hdd1000_1234-part2 19956M

Clone file systems to new partitions

Clone file systems by copying allocated space only:

You will probably want to do this in single user mode or a live cd.

partclone.fat32 -b -s /dev/disk/by-id/usb-hdd1000_1234-part1 -o /dev/disk/by-id/ata-ssd1000_1234-part1
partclone.ext4 -b -s /dev/disk/by-id/usb-hdd1000_1234-part2 -o /dev/disk/by-id/ata-ssd1000_1234-part2
partclone.ntfs -b -s /dev/disk/by-id/usb-hdd1000_1234-part3 -o /dev/disk/by-id/ata-ssd1000_1234-part3
partclone.ext4 -b -s /dev/disk/by-id/usb-hdd1000_1234-part4 -o /dev/disk/by-id/ata-ssd1000_1234-part4

Remake the swap

mkswap /dev/disk/by-id/usb-hdd1000_1234-part5

Because we shrunk the size of the file system on /dev/disk/by-id/usb-hdd1000_1234-part2 which is now copied to /dev/disk/by-id/ata-ssd1000_1234-part2 it may need to be enlarged. If sizes were copied exactly this isn't necessary.

resize2fs /dev/disk/by-id/ata-ssd1000_1234-part2

Make system bootable with the new disk

Now that the file systems and partitions are moved the UEFI, the bootloader and Linux need to be made aware of the new partitions. Another approach is to reuse UUIDs or partition ordering but this approach will likely need tweaking and fixing anyway so lets just update as needed.

Linux:

Depending on your distribution swap partitions will be automatically detected and used or they might need to be included in fstab.

Update fstab for the partitions needed to boot. This will include partitions for

/
/boot
/boot/efi
/home

In our example we only have / and the /boot/efi to update.

Use the UUIDs output from lsblk in fstab.

edit /etc/fstab

First for EFI System

lsblk -no UUID /dev/disk/by-id/ata-ssd1000_1234-part1

Use output to change the line in fstab with /boot/efi where UUID= should be changed to the UUID output from lsblk

Do the same for the Linux file system. lsblk -no UUID /dev/disk/by-id/ata-ssd1000_1234-part2

UEFI:

Alternatively you may want to just start with a formatted EFI System Partition which would also require Windows to have its bootloader fixed. Otherwise skip this step.

mkfs.vfat -F32 /dev/disk/by-id/ata-ssd1000_1234-part1

You can manually add entries to UEFI using efibootmgr but we will use the functionality built into GRUB.

GRUB:

We will only cover GRUB bootloader for now.

mount /dev/disk/by-id/ata-ssd1000_1234-part2 /mnt
mount /dev/disk/by-id/ata-ssd1000_1234-part1 /mnt/boot/efi

grub-install --target=x86_64-efi --boot-directory=/mnt/boot --efi-directory==/mnt/boot/efi --bootloader-id="NewLinux"
grub-mkconfig -o /mnt/boot/grub/grub.cfg

Set the bootloader-id parameter to the entry you want to appear in your UEFI. You want this to be different from your current setup.

Note that grub-mkconfig uses your running systems scripts to generate the entries. If you're using your existing disk this will include entries for itself and then os-prober will include the other disk. You will have to select this as it will not be default when booting. If you're using a live cd then both installs will be detected by os-prober. Once in the new system rerun grub-mkconfig for the entries to be generated by the new system.

Finally unmount the file systems and reboot

umount /mnt/*
reboot

Make sure to select the new disk in grub from osprober entries and then regenerate after booting into the new disk.

grub-mkconfig -o /boot/grub/grub.cfg

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.