Commands are ran from a liveUSB
If the disk is LUKS-encrypted, unlock it and image the decrypted device-mapper node. Encrypted data is random and won't compress; the decrypted stream (zeroed free space) compresses well over the network.
Find the LUKS partition:
lsblk -f
Unlock it (prompts for passphrase):
sudo cryptsetup luksOpen /dev/nvme0n1p2 decrypted
Then use /dev/mapper/decrypted as the source (if=) in the dd commands
below instead of /dev/nvme0n1.
Notes:
- This images only the LUKS container — no partition table or EFI/boot partition. If LVM is layered inside LUKS, the image is an LVM PV.
- To make the VM boot, strip crypto references afterwards: remove the
/etc/crypttabentry, regenerate the initramfs without the encrypt hook, and fix/etc/fstab/bootloader to point at the plaintext device.
Compress over the network and extract on target. Faster: pigz -1 (all
cores, speed over ratio), an AES-NI SSH cipher, and mbuffer to keep the
gigabit pipe full (apt install mbuffer; drop it if unavailable).
sudo dd if=/dev/nvme0n1 bs=256M status=progress | pigz -1 -c | mbuffer -q -m 1G | ssh -c aes128-gcm@openssh.com [user]@[host] "gunzip -c > /mnt/disks/dev-nvme0n1.img"
Keeps the archive compressed on the remote. For a smaller stored file
raise the pigz level (e.g. -6) at the cost of speed.
sudo dd if=/dev/nvme0n1 bs=256M status=progress | pigz -1 -c | mbuffer -q -m 1G | ssh -c aes128-gcm@openssh.com [user]@[host] "cat > /mnt/disks/dev-nvme0n1.img.gz"
$ qemu-img convert -f raw -O qcow2 /mnt/disks/dev-nvme0n1.img /mnt/disks/dev-nvme0n1.qcow2