Moving only the Linux side of a dual-boot nvme2n1 → empty nvme0n1. Windows partitions (p1–p4) stay on the old drive untouched.
| Old (nvme2n1) | What | Size |
|---|---|---|
| p5 | LUKS → LVM (VG vg) |
1.22 TiB |
| p6 | EFI (fat32, label EFI-LINUX) | 100 MiB |
| p7 | /boot (ext4) | 500 MiB |
Target: nvme0n1 — 3.64 TiB, currently empty.
- Arch Linux live USB (latest ISO: https://archlinux.org/download/)
- Both NVMe drives installed in the machine
- Know your LVM layout — run
lvson your live system before starting
Run these on the live system and save the output (photo, write it down, whatever):
# LVM layout — need to know LV names and sizes
sudo lvs -o lv_name,vg_name,lv_size,lv_path
# Current fstab for reference
cat /etc/fstab
# Current crypttab
cat /etc/crypttab
# Check bootloader type
# systemd-boot:
bootctl status
# GRUB:
# grub-install --version
# Kernel cmdline (shows root= and cryptdevice= params)
cat /proc/cmdline
# Current UUIDs for reference
sudo blkid /dev/nvme2n1p5 /dev/nvme2n1p6 /dev/nvme2n1p7Write down or photograph ALL of this output. You'll need it.
- Write the Arch ISO to a USB stick
- Boot from it (F12 / boot menu)
- Connect to the internet (
iwctlfor wifi, or just plug in ethernet) - Install rsync if not present:
pacman -Sy rsync
Verify both drives are visible:
lsblk
# Should see nvme0n1 (3.64 TiB, empty) and nvme2n1 (1.82 TiB, with partitions)gdisk /dev/nvme0n1Create this layout:
| # | Size | Type code | Purpose |
|---|---|---|---|
| 1 | 512 MiB | EF00 | EFI System Partition |
| 2 | 1 GiB | 8300 | /boot |
| 3 | (rest) | 8309 | LUKS |
In gdisk:
o ← new GPT table (confirm)
n ← new partition
1 ← partition number
enter ← default first sector
+512M ← size
EF00 ← EFI type
n
2
enter
+1G
8300 ← Linux filesystem
n
3
enter
enter ← use all remaining space
8309 ← Linux LUKS
w ← write and exit
mkfs.fat -F32 -n EFI-LINUX /dev/nvme0n1p1
mkfs.ext4 -L boot /dev/nvme0n1p2# Create LUKS container (you'll set a new passphrase)
cryptsetup luksFormat /dev/nvme0n1p3
# Open it
cryptsetup open /dev/nvme0n1p3 cryptnew
# Create LVM physical volume
pvcreate /dev/mapper/cryptnew
# Create volume group — use the SAME name as your old VG
# (no conflict since old drive's VG isn't activated)
vgcreate vg /dev/mapper/cryptnewNow create your LVs. Adapt these to match your actual layout from Phase 0.
Example (adjust sizes — you have ~3.6 TiB to play with now):
# If you have swap + root:
lvcreate -L 32G vg -n swap
lvcreate -l 100%FREE vg -n root
# If you have swap + root + home:
# lvcreate -L 32G vg -n swap
# lvcreate -L 500G vg -n root
# lvcreate -l 100%FREE vg -n homeFormat the logical volumes:
mkfs.ext4 /dev/vg/root
mkswap /dev/vg/swap
# If you have a separate /home:
# mkfs.ext4 /dev/vg/homecryptsetup open /dev/nvme2n1p5 cryptoldImportant: If the old VG is also named vg, LVM will see duplicate VG names.
Rename the old one temporarily:
# Check what LVM found
vgscan
pvs
# If both VGs are named "vg", rename the OLD one:
# Find the old VG's UUID
vgdisplay
# Rename by UUID:
vgrename <old-vg-uuid> vgold
vgchange -ayIf the VG names are already different, just activate:
vgchange -ay# New drive
mount /dev/vg/root /mnt
mkdir -p /mnt/boot /mnt/efi
# If separate /home:
# mkdir -p /mnt/home
# mount /dev/vg/home /mnt/home
mount /dev/nvme0n1p2 /mnt/boot
mount /dev/nvme0n1p1 /mnt/efi
# Old drive
mkdir -p /mnt2
mount /dev/vgold/root /mnt2
mkdir -p /mnt2/boot /mnt2/efi
mount /dev/nvme2n1p7 /mnt2/boot
mount /dev/nvme2n1p6 /mnt2/efi
# If old had separate /home:
# mkdir -p /mnt2/home
# mount /dev/vgold/home /mnt2/home# Root filesystem
rsync -aAXHv --info=progress2 /mnt2/ /mnt/ \
--exclude={'/boot/*','/efi/*','/home/*'}
# Boot
rsync -aAXHv --info=progress2 /mnt2/boot/ /mnt/boot/
# EFI
rsync -aAXHv --info=progress2 /mnt2/efi/ /mnt/efi/
# Home (if separate LV)
# rsync -aAXHv --info=progress2 /mnt2/home/ /mnt/home/Note: The root rsync will take the longest — depends on how much data is on the 1.22 TiB LV. NVMe-to-NVMe should be fast. Expect ~10–30 min for a typical install.
blkid /dev/nvme0n1p1 /dev/nvme0n1p2 /dev/nvme0n1p3
blkid /dev/vg/root /dev/vg/swap
# If separate /home:
# blkid /dev/vg/homeWrite these down. You need:
- nvme0n1p1 UUID → fstab (EFI)
- nvme0n1p2 UUID → fstab (/boot)
- nvme0n1p3 UUID → crypttab (LUKS partition)
- vg/root UUID → fstab (/)
- vg/swap UUID → fstab (swap)
nano /mnt/etc/fstabReplace all old UUIDs with the new ones. It should look something like:
# <device> <mount> <type> <options> <dump> <pass>
UUID=<vg-root-uuid> / ext4 rw,relatime 0 1
UUID=<nvme0n1p2-uuid> /boot ext4 rw,relatime 0 2
UUID=<nvme0n1p1-uuid> /efi vfat rw,relatime,... 0 2
UUID=<vg-swap-uuid> none swap defaults 0 0
nano /mnt/etc/crypttabUpdate to point to the new LUKS partition:
cryptlvm UUID=<nvme0n1p3-uuid> none luks
Match the mapped name (
cryptlvmor whatever your old config used) — check what your kernel cmdline referenced.
umount -R /mnt2
# Make sure new drive is mounted correctly
# (should already be from Phase 5)
arch-chroot /mntbootctl installEdit the loader entry:
nano /efi/loader/entries/arch.conf
# (or wherever your entry file is — check /efi/loader/loader.conf for the default)It should reference the new LUKS partition. Example:
title Arch Linux
linux /vmlinuz-linux
initrd /intel-ucode.img
initrd /initramfs-linux.img
options cryptdevice=UUID=<nvme0n1p3-uuid>:cryptlvm root=/dev/vg/root rw
Use the LUKS partition UUID (the raw nvme0n1p3), not the LV UUID. Adjust
intel-ucode→amd-ucodeif on AMD. Matchcryptlvmto whatever mapped name your crypttab uses.
grub-install --target=x86_64-efi --efi-directory=/efi --bootloader-id=GRUB
grub-mkconfig -o /boot/grub/grub.cfgmkinitcpio -PThis is critical — it rebuilds initramfs with the new crypttab/fstab references.
exit # leave chroot
umount -R /mnt
reboot- Enter BIOS/UEFI firmware settings (usually F2 or Del)
- Set nvme0n1 as first boot device
- Boot — you should get the LUKS passphrase prompt
- Enter your (new) passphrase
- Should boot normally into your Arch install
Once booted and verified:
# Verify everything mounted correctly
lsblk
mount | grep nvme0n1
swapon --show
# If you renamed the old VG to vgold temporarily,
# it doesn't matter — the old drive isn't activated.
# Optional: reclaim the old Linux partitions on nvme2n1
# (p5, p6, p7) — can delete them in gdisk/GParted
# to free ~1.32 TiB on the old drive for Windows useCan't boot / drops to emergency shell:
- Boot the live USB again
- Mount the new root, chroot in
- Check
/etc/fstabUUIDs matchblkidoutput - Check
/etc/crypttabUUID matches the LUKS partition - Check bootloader entry has correct
cryptdevice=UUID - Run
mkinitcpio -Pagain
LUKS passphrase prompt doesn't appear:
- The initramfs doesn't have the encrypt hook
- In chroot: check
/etc/mkinitcpio.confhasencryptandlvm2in HOOKS - Typical order:
... block encrypt lvm2 filesystems ... - Regenerate:
mkinitcpio -P
VG name collision in live environment:
- Use
vgrenamewith the VG UUID (fromvgdisplay) to disambiguate - Or: only open ONE LUKS container at a time
If the data copied fine but GRUB won't boot, this is almost always one of three things:
cryptdevice=in GRUB config still has the old drive's UUIDgrub-installwas never re-run against the new EFI partitiongrub.cfgwas never regenerated with the new UUIDs
# 1. Open the new LUKS + activate LVM
cryptsetup open /dev/nvme0n1p3 cryptlvm
vgchange -ay
# 2. Mount the new system
mount /dev/vg/root /mnt
mount /dev/nvme0n1p2 /mnt/boot
mount /dev/nvme0n1p1 /mnt/efi # adjust if your ESP mounts at /boot/efi
# 3. Chroot in
arch-chroot /mnt
# 4. Get the new LUKS partition UUID
blkid /dev/nvme0n1p3
# Note the UUID= value (NOT PARTUUID)
# 5. Update /etc/default/grub with the new UUID
nano /etc/default/grubThe critical line — make sure it references the new LUKS partition:
GRUB_CMDLINE_LINUX="cryptdevice=UUID=<nvme0n1p3-uuid>:cryptlvm root=/dev/vg/root"
Also verify these modules are listed (needed for LUKS + LVM):
GRUB_PRELOAD_MODULES="part_gpt part_msdos cryptodisk luks lvm"
Then reinstall and regenerate everything:
# 6. Reinstall GRUB to the new EFI partition
grub-install --target=x86_64-efi --efi-directory=/efi --bootloader-id=GRUB
# 7. Regenerate grub.cfg (picks up the new cryptdevice UUID)
grub-mkconfig -o /boot/grub/grub.cfg
# 8. Verify mkinitcpio.conf has the right hooks
grep HOOKS /etc/mkinitcpio.conf
# Must contain: ... block encrypt lvm2 filesystems ...
# If missing encrypt or lvm2, add them and save
# 9. Rebuild initramfs
mkinitcpio -P
# 10. Also verify /etc/crypttab and /etc/fstab have new UUIDs
cat /etc/crypttab # should reference nvme0n1p3 UUID
cat /etc/fstab # should reference new partition/LV UUIDs
# 11. Exit and reboot
exit
umount -R /mnt
rebootIf you created the new LUKS container with cryptsetup luksFormat (defaults to LUKS2 on modern systems) and your /boot is inside the encrypted volume, GRUB cannot decrypt it — GRUB's LUKS2 support is limited.
This shouldn't affect you if /boot is on a separate unencrypted partition (nvme0n1p2), which is the layout in this guide. But if you're hitting error: disk 'lvmid/...' not found, check whether GRUB is trying to read from inside the LUKS container before it's unlocked.
Once booted successfully:
# Verify you're on the new drive
lsblk
mount | grep nvme0n1
cat /proc/cmdline # should show cryptdevice=UUID=<new-uuid>
# Verify LUKS is the new partition
sudo cryptsetup status cryptlvm- Arch Wiki: Migrate installation to new hardware
- Arch Wiki: Rsync — Full system backup
- Arch Wiki: dm-crypt/Encrypting an entire system
- Migrating LVM on LUKS to a larger SSD (Rawsec)
- Migrating ArchLinux from SSD to NVMe (saghul)
- Recovering GRUB with LUKS + LVM (USP)
- Arch Forums: GRUB + UEFI + LVM on LUKS fix