Skip to main content

HowTo: Hot migration of OS Linux (Debian 12) from one encrypted disk to another

This is a step-by-step HowTo article on performing a hot migration of a Linux operating system to another encrypted disk. It provides almost no explanations, focusing solely on the commands required to complete the task. Use it at your own risk. You could lose your data during the process, so ensure you have a backup of all critical data before proceeding. Part of the output has been removed to make this article shorter.

Environment checking

$ sudo apt list --installed lvm2 cryptsetup fdisk efibootmgr
Listing... Done
cryptsetup/stable,now 2:2.6.1-4~deb12u2 amd64 [installed]
efibootmgr/stable,now 17-2 amd64 [installed,automatic]
fdisk/stable,now 2.38.1-5+deb12u3 amd64 [installed]
lvm2/stable,now 2.03.16-2 amd64 [installed]

$ lsblk
NAME                         MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINTS
nvme0n1                      259:0    0 931.5G  0 disk  
nvme1n1                      259:4    0 238.5G  0 disk  
├─nvme1n1p1                  259:5    0   512M  0 part  /boot/efi
├─nvme1n1p2                  259:6    0   488M  0 part  /boot
└─nvme1n1p3                  259:7    0 237.5G  0 part  
  └─nvme1n1p3_crypt          254:0    0 237.5G  0 crypt 
    └─daemn--laptop--vg-root 254:1    0 236.5G  0 lvm   /
$ # nvme0n1 - the new empty device.
$ # nvme1n1 - the old device.

$ df -hT
Filesystem                         Type      Size  Used Avail Use% Mounted on
/dev/mapper/daemn--laptop--vg-root ext4      232G  175G   46G  80% /
/dev/nvme1n1p2                     ext2      456M  222M  210M  52% /boot
/dev/nvme1n1p1                     vfat      511M   77M  435M  15% /boot/efi
...

$ sudo cryptsetup status /dev/mapper/nvme1n1p3_crypt
/dev/mapper/nvme1n1p3_crypt is active and is in use.
  type:    LUKS2
  ...

Initializing a new disk

$ sudo fdisk /dev/nvme0n1

Command (m for help): g
Created a new GPT disklabel (GUID: C14B8CC0-4EBD-0543-A3B0-D82E5AB153F9).

Command (m for help): n
Partition number (1-128, default 1): 
First sector (2048-1953525134, default 2048): 
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-1953525134, default 1953523711): +512M

Created a new partition 1 of type 'Linux filesystem' and of size 512 MiB.

Command (m for help): t
Partition number (1-3, default 3): 1
Partition type or alias (type L to list all): 1

Changed type of partition 'Linux filesystem' to 'EFI System'.

Command (m for help): n
Partition number (2-128, default 2): 
First sector (1050624-1953525134, default 1050624): 
Last sector, +/-sectors or +/-size{K,M,G,T,P} (1050624-1953525134, default 1953523711): +512M

Created a new partition 2 of type 'Linux filesystem' and of size 512 MiB.

Command (m for help): n
Partition number (3-128, default 3): 
First sector (2099200-1953525134, default 2099200): 
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2099200-1953525134, default 1953523711): 

Created a new partition 3 of type 'Linux filesystem' and of size 930.5 GiB.

Command (m for help): p
Disk /dev/nvme0n1: 931.51 GiB, 1000204886016 bytes, 1953525168 sectors
Disk model: KINGSTON SFYRS1000G                     
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: C14B8CC0-4EBD-0543-A3B0-D82E5AB153F9

Device           Start        End    Sectors   Size Type
/dev/nvme0n1p1    2048    1050623    1048576   512M EFI System
/dev/nvme0n1p2 1050624    2099199    1048576   512M Linux filesystem
/dev/nvme0n1p3 2099200 1953523711 1951424512 930.5G Linux filesystem

Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.

$ sudo mkfs.vfat -F 32 /dev/nvme0n1p1 -n BOOT_EFI
mkfs.fat 4.2 (2021-01-31)

$ sudo mkfs.ext2 -L BOOT /dev/nvme0n1p2
mke2fs 1.47.0 (5-Feb-2023)
Discarding device blocks: done                            
Creating filesystem with 131072 4k blocks and 32768 inodes
Filesystem UUID: 2c2db8f5-fc84-4c0b-a060-0e9c1b1c0bee
Superblock backups stored on blocks: 
	32768, 98304

Allocating group tables: done                            
Writing inode tables: done                            
Writing superblocks and filesystem accounting information: done

$ sudo cryptsetup -y luksFormat /dev/nvme0n1p3

WARNING!
========
This will overwrite data on /dev/nvme0n1p3 irrevocably.

Are you sure? (Type 'yes' in capital letters): YES
Enter passphrase for /dev/nvme0n1p3: 
Verify passphrase: 

$ sudo cryptsetup open /dev/nvme0n1p3 data_crypt
Enter passphrase for /dev/nvme0n1p3: 

$ sudo cryptsetup status /dev/mapper/data_crypt
/dev/mapper/data_crypt is active.
  type:    LUKS2
...

Migrating root (/) partition

$ sudo pvcreate /dev/mapper/data_crypt
  Physical volume "/dev/mapper/data_crypt" successfully created.

$ sudo vgextend daemn-laptop-vg /dev/mapper/data_crypt
  Volume group "daemn-laptop-vg" successfully extended

$ sudo pvdisplay
  --- Physical volume ---
  PV Name               /dev/mapper/nvme1n1p3_crypt
  VG Name               daemn-laptop-vg
  PV Size               237.48 GiB / not usable 0   
...

  --- Physical volume ---
  PV Name               /dev/mapper/data_crypt
  VG Name               daemn-laptop-vg
  PV Size               <930.50 GiB / not usable 4.00 MiB
...

$ sudo pvmove /dev/mapper/nvme1n1p3_crypt /dev/mapper/data_crypt
  ...
  /dev/mapper/nvme1n1p3_crypt: Moved: 100.00%

$ sudo vgreduce daemn-laptop-vg /dev/mapper/nvme1n1p3_crypt
  Removed "/dev/mapper/nvme1n1p3_crypt" from volume group "daemn-laptop-vg"

$ sudo pvdisplay
  --- Physical volume ---
  PV Name               /dev/mapper/data_crypt
  VG Name               daemn-laptop-vg
  PV Size               <930.50 GiB / not usable 4.00 MiB
...

  "/dev/mapper/nvme1n1p3_crypt" is a new physical volume of "237.48 GiB"
  --- NEW Physical volume ---
  PV Name               /dev/mapper/nvme1n1p3_crypt
  VG Name               
  PV Size               237.48 GiB
...

$ sudo cryptsetup close /dev/mapper/nvme1n1p3_crypt

$ sudo lvextend -v -l +100%FREE /dev/mapper/daemn--laptop--vg-root
  Converted 100%FREE into at most 177656 physical extents.
  Extending logical volume daemn-laptop-vg/root to up to 930.49 GiB
...

$ sudo resize2fs /dev/mapper/daemn--laptop--vg-root
resize2fs 1.47.0 (5-Feb-2023)
Filesystem at /dev/mapper/daemn--laptop--vg-root is mounted on /; on-line resizing required
old_desc_blocks = 30, new_desc_blocks = 117
The filesystem on /dev/mapper/daemn--laptop--vg-root is now 243922944 (4k) blocks long.

$ df -h /
Filesystem                          Size  Used Avail Use% Mounted on
/dev/mapper/daemn--laptop--vg-root  915G  175G  701G  20% /

Migrating boot (/boot and /boot/efi) partitions

$ sudo blkid
/dev/mapper/daemn--laptop--vg-root: UUID="c4d4ae76-2726-4f2d-9ca8-610ba4a91cc9" BLOCK_SIZE="4096" TYPE="ext4"
/dev/nvme0n1p3: UUID="ae84a802-8d91-4a6d-bf34-e5e1691a2b3a" TYPE="crypto_LUKS" PARTUUID="3ab560c6-5cf8-e246-98de-08c28e4fb7ea"
/dev/nvme0n1p1: LABEL_FATBOOT="BOOT_EFI" LABEL="BOOT_EFI" UUID="CF9D-8F65" BLOCK_SIZE="512" TYPE="vfat" PARTUUID="9ab3ea38-eb44-4348-8250-a3993feaed05"
/dev/nvme0n1p2: LABEL="BOOT" UUID="2c2db8f5-fc84-4c0b-a060-0e9c1b1c0bee" BLOCK_SIZE="4096" TYPE="ext2" PARTUUID="45f7e4f1-0331-a440-8a8e-7f988692aeb2"
/dev/nvme1n1p2: UUID="3ed6aa53-feb3-4bfb-afdd-51df184f197e" BLOCK_SIZE="1024" TYPE="ext2" PARTUUID="96499402-27a6-4d5a-9ee9-be6bf06e56b2"
/dev/nvme1n1p3: UUID="b2c29a49-f256-4319-b12d-a113a134b507" TYPE="crypto_LUKS" PARTUUID="c91573b0-44b9-44b8-858b-a0dbb1bb10d4"
/dev/nvme1n1p1: UUID="EAEE-A070" BLOCK_SIZE="512" TYPE="vfat" PARTUUID="a60317df-b103-4cd8-90cc-97d113265273"
/dev/mapper/data_crypt: UUID="CUckb8-W1sA-d1Fm-G0LE-h2Q9-FHbN-C5YIwQ" TYPE="LVM2_member"

$ cat /etc/crypttab
# nvme1n1p3_crypt UUID=b2c29a49-f256-4319-b12d-a113a134b507 none luks,discard
data_crypt UUID=ae84a802-8d91-4a6d-bf34-e5e1691a2b3a none luks,discard

$ cat /etc/fstab
/dev/mapper/daemn--laptop--vg-root /               ext4    errors=remount-ro 0       1
# UUID=3ed6aa53-feb3-4bfb-afdd-51df184f197e /boot           ext2    defaults        0       2
UUID=2c2db8f5-fc84-4c0b-a060-0e9c1b1c0bee /boot           ext2    defaults        0       2
# UUID=EAEE-A070  /boot/efi       vfat    umask=0077      0       1
UUID=CF9D-8F65  /boot/efi       vfat    umask=0077      0       1

$ sudo rsync -a /boot/ /boot_backup/

$ sudo umount /boot/efi

$ sudo umount /boot

$ sudo systemctl daemon-reload

$ sudo mount /boot

$ sudo mkdir /boot/efi

$ sudo chmod 700 /boot/efi

$ sudo mount /boot/efi/

$ sudo rsync -a --exclude efi /boot_backup/ /boot/

$ sudo rsync -a /boot_backup/efi/ /boot/efi/

$ sudo efibootmgr -v
...
Boot0006* debian	HD(1,GPT,a60317df-b103-4cd8-90cc-97d113265273,0x800,0x100000)/File(\EFI\debian\shimx64.efi)

$ sudo efibootmgr -c -d /dev/nvme0n1 -p 1 -L "debian-1tb" -l '\EFI\debian\shimx64.efi'
...
Boot0006* debian
Boot0000* debian-1tb

$ sudo efibootmgr --bootnum 0006 --inactive
...
Boot0000* debian-1tb
Boot0006  debian

$ sudo update-initramfs -u -k all
update-initramfs: Generating /boot/initrd.img-6.1.0-29-amd64
update-initramfs: Generating /boot/initrd.img-6.1.0-27-amd64
update-initramfs: Generating /boot/initrd.img-6.1.0-25-amd64

$ sudo grub-install /dev/nvme0n1
Installing for x86_64-efi platform.
Installation finished. No error reported.

$ sudo update-grub
Generating grub configuration file ...
...

Result overview

$ lsblk
NAME                         MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINTS
nvme0n1                      259:0    0 931.5G  0 disk  
├─nvme0n1p1                  259:1    0   512M  0 part  /boot/efi
├─nvme0n1p2                  259:2    0   512M  0 part  /boot
└─nvme0n1p3                  259:3    0 930.5G  0 part  
  └─data_crypt               254:0    0 930.5G  0 crypt 
    └─daemn--laptop--vg-root 254:1    0 930.5G  0 lvm   /
nvme1n1                      259:4    0 238.5G  0 disk  
├─nvme1n1p1                  259:5    0   512M  0 part  
├─nvme1n1p2                  259:6    0   488M  0 part  
└─nvme1n1p3                  259:7    0 237.5G  0 part  

$ df -hT
Filesystem                         Type      Size  Used Avail Use% Mounted on
/dev/mapper/daemn--laptop--vg-root ext4      915G  175G  701G  20% /
/dev/nvme0n1p2                     ext2      504M  222M  257M  47% /boot
/dev/nvme0n1p1                     vfat      511M   77M  435M  15% /boot/efi
...

Comments

Popular posts from this blog

Optimizing Database Query Performance: Solving Text Search Challenges with Table Partitioning

In the development of the " antikollektor " project, which aims to provide a user-friendly interface for checking judicial databases, I encountered a major challenge related to how fast the database could respond to queries. Specifically, queries involving text searches across a large number of rows were taking an unacceptably long time to execute. In this article, I will share the steps taken to optimize database performance by implementing a table partitioning strategy, addressing the issues encountered and achieving significant improvements in query speed. The Issue: Slow Text Search Queries Users typically search for court cases by defendant name within a specified date range. The average request was taking approximately 5 seconds to execute. casesdbv2=# explain analyze select * from cases where date >= '2023-01-01' and date <= '2023-06-30' and defendant ilike '%ivanov%sergey%' order by date desc offset 30 limit 10; ...

How to create a Simple Captcha Resolver

"All aircraft designers once learned to make paper airplanes." Someone Smart This article shows my journey of developing a simple captcha resolver. By repeating the steps described, you will be able to get acquainted with the technologies and create your own recognizer for experimentation and study. Some specific development points have been omitted to simplify the material in the article. It should be noted that I am not an ML specialist and very superficially familiar with machine learning technologies. I developed this captcha recognizer out of curiosity, driven by an interest in understanding how the learning process works. So I would be very grateful for advice and comments from those who understand this. There are numerous parameters mentioned in the article that I don’t explain in detail. The goal of this approach is to make the article shorter and simpler while encouraging readers to experiment with the parameters themselves. I have used the simplest algorithms po...