Linux os mitigation

It may seem too daunting to mitigate the currently installed linux install to new hardware, and on top that there is little awareness on how to do it. After me myself struggling a lot i decided to make a guide.

Basic preparation

  1. There is basically two approach to achieve it top to down and bottom up approach, personally i prefer top to down.

top to down approach

top to down approach is basically cloning you os to to new drive or Partition, Generally either you can use dd , clonezilla to do cloning at block level, or can use archiving copying tool like rsync. rysnc is my fav!, less likely to fail and robust, I have tried dd, but i had lot of problem, It works fine for disk to disk clone, but had to fight a lot to make it work for partition to partition.

  1. Basically what we will do is copy whole rootfs of installed os to new partition, chroot into it update the fstab and reinstall grub into new drive if parition is in new drive.
  • Get a live linux os boot it up this should have rsync installed,
  • create partition/ format new drive using fdisk or gparted.
  • Then identify the os partition using lsblk or fdisk, mount the partition
lsblk 
  • mount the partition ,
sudo mount /dev/sdx /mnt/
  • if it is btrfs subvol use -o subvol=subvolume flag, for example if your rootfs brtfs subvolume is @, then do
sudo mount /dev/sdx -o subvol=@ /mnt 
  • Also mount the target partition, i assume target is /mnt2/

Rsync clone

I found about this rsync command with commandline options in arch wiki,pretty wonderful guide also pretty neat option –info=progess2

rsync -aAXHv --info=progress2  --exclude={"/mnt/dev/*","/mnt/proc/*","/mnt/sys/*","/mnt/tmp/*","/mnt/run/*","/mnt/mnt/*","/mnt/media/*","/mnt/lost+found"} /mnt/ /mnt2 

let the copy be done.

prepare for chroot save this following script then run

Now we need to create a chroot enviroment to install grub and update fstab

  • Copy and save the following chroot script, it requires a target rootfs dir

bash script

#!/bin/bash

display_usage() {
    echo "Usage: $1 <target_directory>"
    exit ;
    
}

   [[ $# -eq 1  ]] ||  { display_usage;   }

    for i in dev sys proc; do
        sudo mount --bind "/$i" "${1}/$i" || { echo "Mount failed."; exit 1;  }
        done

        sudo chroot "$1" bash
  • Launch chroot.sh
bash ./chroot.sh <dev block> <mount dir >
  • in chroot enviroment now we need to update fstab
vi /etc/fstab

find UUID of partition using lsblk -f command or blkid

if it is btrfs then example syntax

UUID=fa5b0128-8a78-40ce-a7e2-cf3519e5363f         /               btrfs   defaults,subvol=@,compress=zstd   0       1

ext4

UUID=fa5b0128-8a78-40ce-a7e2-cf3519e5363f         /               ext4    defaults  0       1
  • now install and update your grub, if you have multiple os, mind to toggle the os detection flag in /etc/default/grub , change GRUB_DISABLE_OS_PROBER=true to GRUB_DISABLE_OS_PROBER=false
  • Install grub I assume your partition table is mbr
grub-install --target=i386-pc /dev/sdX

replace sdx with devfs block name

then finally update the grub

update-grub 

at last update kernel initramfs

update-initramfs -u 

you will have to again update initramfs if you plan to run os from different machine

Important info for btrfs user

Some time update-grub doesn’t create correct grub entry for btrfs subvolume, in that case you will have to create a custom grub entry manually

  • open /boot/grub/grub.cfg in editor, check if your entry looks something like this
menuentry 'Debian GNU/Linux' --class debian --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-fa5b0128-8a78-40ce-a7e2-cf3519e5363f' {
    load_video
    insmod gzio
    if [ x$grub_platform = xxen  ]; then insmod xzio; insmod lzopio; fi
    insmod part_msdos
    insmod btrfs
    set root='hd0,msdos3'
    if [ x$feature_platform_search_hint = xy  ]; then
     search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos3 --hint-efi=hd0,msdos3 --hint-baremetal=ahci0,msdos3  fa5b0128-8a78-40ce-a7e2-cf3519e5363f
    else
     search --no-floppy --fs-uuid --set=root fa5b0128-8a78-40ce-a7e2-cf3519e5363f
    fi
    echo    'Loading Linux 6.1.0-10-rt-amd64 ...'
    linux   /@/boot/vmlinuz-6.1.0-10-rt-amd64 root=UUID=fa5b0128-8a78-40ce-a7e2-cf3519e5363f ro rootflags=subvol=@ resume=UUID=53e68cd8-e29b-4871-b8ca-14225675a601 debug
    echo    'Loading initial ramdisk ...'
    initrd  /@/boot/initrd.img-6.1.0-10-rt-amd64

}

check at kernel and initramfs parameter and look for subvolume, for example in above code subvolume is @ so parameter looks like linux /@/boot/vmlinuz-6.1.0-10-rt-amd64 ro rootflags=subvol=@ also initramfs initrd /@/boot/initrd.img-6.1.0-10-rt-amd64, important here to not is look for rootflags , and correct dir like /@

  • Custom grub entry if grub entry is incorrect, create a custom entry by opening /etc/grub.d/40_custom copy a entry from original grub.cfg then change according to correct subvolume and root flags

then update grub

update-grub