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?
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.
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/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:
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
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:
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 (+).
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:
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
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
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.
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.
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.
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
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.
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