I want to change a btrfs LUKS encrypted partition to ext4

I have a Fedora 38 workstation installation. It was updated to Fedora 42. That is, the sda3 partition is btrfs. I want to get rid of btrfs before it causes serious problems and use ext4. The partition is encrypted with LUKS. While preparing the necessary steps to do this, I’m stuck with an AI that claims I don’t need to reformat sda3 to ext4. This AI claims that sda3 will magically switch from btrfs to ext4. While it’s possible, I don’t see how, and I don’t want to go through all that work only to find that the partition has remained in btrfs even though its encrypted contents are now ext4.

I think this is missing somewhere, right?
sudo mkfs.ext4 /dev/sda3

Here are the instructions given by the AI:

  1. Open the LUKS container
    sudo cryptsetup luksOpen /dev/sda3 luks-root

  2. Retrieve the FS UUID (Btrfs)
    UUID_FS=$(blkid -s UUID -o value /dev/sda3)

  3. Back up the Btrfs to an external device
    sudo mkdir -p /mnt/btrfs_src && sudo mount /dev/mapper/luks-root /mnt/btrfs_src
    BACKUP=“/run/media/liveuser/USB/sda3_$(date +%F).tar.gz”
    sudo tar -czvf “$BACKUP” -C /mnt/btrfs_src .
    sudo umount /mnt/btrfs_src

  4. Delete the Btrfs
    sudo wipefs -a /dev/mapper/luks-root

  5. Create EXT4 while keeping the same UUID
    sudo mkfs.ext4 -U “$UUID_FS” /dev/mapper/luks-root

  6. Restore the backup to the new EXT4
    sudo mkdir -p /mnt/ext4 && sudo mount /dev/mapper/luks-root /mnt/ext4
    sudo tar -xzvf “$BACKUP” -C /mnt/ext4
    sudo umount /mnt/ext4

  7. Close the container and reboot
    sudo cryptsetup luksClose luks-root

I’ll try another AI later; I’ve used up my credits for now.

This isn’t a topic about btrfs vs ext4 reliability, please avoid discussing that. I know opinions vary greatly. The point is, I want to get rid of it.

This would make /dev/sda3 an unencrypted ext4 filesystem. Assuming that you want to retain the encryption, you need to create the filesystem in the LUKS volume, which step 5 in the LLM instructions does.

Your choice, free as in ‘freedom’.

Thanks for your reply. Strange. The idea would be to reencrypt the ext4 filesystem naturally. It goes like this, isn’t it? ext4 partition → luks container → data ?

What do you mean “reencrypt”?

Do you mean an in-place conversion of the filesystem? The LLM instructions do not accomplish that. That’s why step 3 is a backup, step 4 deletes it, step 5 creates a new ext4 filesystem, and step 6 restores the backup.

No, it’s partition on disk → LUKS → filesystem. You can see that in the order of steps: In step 1, you open the encrypted LUKS volume /dev/sda3, this allows the OS to see and mount the filesystem data structure in the mapped /dev/mapper/luks-root in step 3.

If you want to change an encrypted btrfs into an encrypted ext4 without creating a new encryption, you would open the encrypted device and then format the contained mapped partition.

I assume your encrypted device is sda3, and the contained btrfs file system that is currently used for Fedora is subsequently luks-root.

So you would do
sudo cryptsetup luksOpen /dev/sda3 luks-root
and then
sudo mkfs.ext4 /dev/mapper/luks-root

Keep in mind that this will completely remove all data of that partition, the subsequent ext4 will be empty, and nothing of the earlier btrfs can be recovered.

So if you Fedora operating system is on that btrfs, you cannot change btrfs to ext4 without setting up a new Fedora. Therefore, you cannot do this from within the Fedora that is installed on that partition.

In short, it might be easier to just setup a new Fedora and create an encrypted ext4 during installation.

LUKS takes the original storage and puts an encryption on top. It then creates an unencrypted storage that is mapped in /dev/mapper. You can use the latter in /dev/mapper like a normal partition, and put an ext4 or btrfs on top of it and then mount it subsequently. LUKS (more correctly, dm-crypt, not LUKS) will then encrypt what is put to the mapped device, and write/read to the original, such as /dev/sda3

My idea was

  1. backup the data

  2. wipe sda3 and mkfs.ext4 sda3

  3. create ext4 luks container in sda3

  4. restore data

Overkill ?

That does not make sense.

You would create a new ext4, and then delete it again. I think you mix dm-crypt/luks layers: hardware/ssd → dm-crypt/luks → file system → your data files or operating system files

First you need an encrypted device (create a new one or use an existing one), and then you create your partitions with ext4/btrfs within.

Also, keep in mind that LUKS is just the header, so the meta-data and its structure. What is doing the work is dm-crypt.

1 Like

Not overkill. You backup data, you do what you need to do, then you restore the data, that’s the universal way to do it.

However, I did remove steps 2 and 3. I don’t think you have a firm understanding of the interaction of dm-crypt (with cryptsetup) and filesystems and I strongly suggest you read some more documentation.

Yeah, as you can see, it’s not clear in my head. In short, the LLM was right ?

Edit: I probably shouldn’t have copied @josevillani’s quotes from @py0xc3’s post, that messed up whose post Discourse thinks I replied to. Sorry. :slight_smile:

I think you are mixing up dm-crypt (with LUKS, which makes dm-crypt/cryptsetup more usable) with something like EncFS.

In general, you put a filesystem onto a block device, e.g., you put an ext4 filesystem onto your /dev/sda3 partition. The filesystem provides the organization such that the operating system can actually store and – more importantly – retrieve data later. (Otherwise you could store all your data in /dev/null. :wink: ) EncFS allows you to store encrypted files in an otherwise unencrypted filesystem.

In contrast, dm-crypt provides an encryption layer on top of a block device and exposes a (mapped) block device of the plain text data. In your example:

  • /dev/sda3 is the block device on your disk, it contains cipher blocks,
  • dm-crypt provides an en/decryption layer on top of /dev/sda3 and exposes the plain text blocks as the block device /dev/mapper/luks-root,
  • and in the block device /dev/mapper/luks-root, you currently have a BTRFS filesystem, which you want to replace with an ext4 one.

As much as it pains me to write it, I didn’t spot any obvious mistakes. But always remember Donald Knuth: “Beware of bugs in the above code; I have only proved it correct, not tried it.”

Interesting. /dev/null lol. Thanks guys @l-c-g @py0xc3

Maybe I’ll do that in 8 days. I’m currently testing recent software upgrades. Kernel 6.16.4 particularly. And I also converted a bunch of snapshots back into filesystem

DIRECTORIES=(
“/var/cache”
“/var/crash”
“/var/log”
“/var/spool”
“/var/tmp”
“/var/www”
“/var/lib/AccountsService”
“/var/lib/gdm”
“/opt”
“/var/lib/machines”
)

Hold on, are you trying to convert your root filesystem? In that case, you probably need some more changes to your GRUB entries and your fstab.

It might be quicker to just reinstall if you feel this strongly about it.

Oh I’m well aware of that. I have done that many times. First time changing the filesystem type in the process though.

That would be the complete process, from a live USB:

  1. Mount the NTFS drive for backup:

    mkdir /mnt/backup
    mount -t ntfs-3g -o defaults,permissions,rw,uid=1000,gid=1000,dmask=022,fmask=022,windows_names,exec /dev/sdc1 /mnt/backup
    
  2. Open the LUKS container on the SSD:

    cryptsetup luksOpen /dev/sda3 myluks
    
  3. Mount the BTRFS subvolumes:

    mkdir /mnt/system
    mount -o subvol=root,compress=zstd:1 /dev/mapper/myluks /mnt/system
    mount -o subvol=home,compress=zstd:1 /dev/mapper/myluks /mnt/system/home
    mount -o subvol=home/shizuma/.mozilla,compress=zstd:1 /dev/mapper/myluks /mnt/system/home/shizuma/.mozilla
    
  4. Create a tar.gz backup of the system to the NTFS drive, preserving permissions and extended attributes:

    cd /mnt/system
    tar --acls --xattrs --exclude=./mnt --exclude=./proc --exclude=./sys --exclude=./dev --exclude=./run --exclude=./tmp -cpzf /mnt/backup/system_backup.tar.gz .
    
    • --acls and --xattrs ensure permissions and extended attributes are preserved.
    • Exclusions prevent copying virtual filesystems.
    • -z enables gzip compression (you can use -I zstd for zstd compression if preferred, e.g., tar --acls --xattrs --use-compress-program=zstd -cpf /mnt/backup/system_backup.tar.zst .).
    • This may take time depending on data size and compression. Monitor progress with pv if installed: tar ... | pv > /mnt/backup/system_backup.tar.gz.
  5. Verify the archive size and integrity:

    ls -lh /mnt/backup/system_backup.tar.gz
    tar -tzf /mnt/backup/system_backup.tar.gz > /dev/null
    

    (The second command checks for errors; it doesn’t extract but reads the archive.)

  6. Unmount everything:

    umount /mnt/system/home/shizuma/.mozilla
    umount /mnt/system/home
    umount /mnt/system
    cryptsetup luksClose myluks
    umount /mnt/backup
    

Step 2: Recreate the filesystem as EXT4

  1. Re-open the LUKS container:

    cryptsetup luksOpen /dev/sda3 myluks
    
  2. Create a new EXT4 filesystem with the same UUID:

    mkfs.ext4 -U 974a92ad-75ce-4957-9258-975411396cab -L / /dev/mapper/myluks
    
  3. Mount the new EXT4:

    mount /dev/mapper/myluks /mnt/system
    mkdir -p /mnt/system/home/shizuma/.mozilla
    

    Step 3: Restore data from tar.gz and configure

  4. Mount the NTFS backup:

    mount -t ntfs-3g -o defaults,permissions,rw,uid=1000,gid=1000,dmask=022,fmask=022,windows_names,exec /dev/sdc1 /mnt/backup
    
  5. Restore the data from the tar.gz archive:

    cd /mnt/system
    tar --acls --xattrs -xpzf /mnt/backup/system_backup.tar.gz
    

    (This extracts files, preserving permissions and attributes. Use -I zstd if you used zstd compression.)

  6. Edit /etc/fstab:

    nano /mnt/system/etc/fstab
    

    Replace with:

    UUID=974a92ad-75ce-4957-9258-975411396cab / ext4 defaults,x-systemd.device-timeout=0 0 1
    UUID=8424fe94-203a-4c47-88d6-969b7c50661f /boot ext4 defaults 1 2
    UUID=D6022A010229E6E9 /mnt/Jeux ntfs-3g defaults,permissions,rw,uid=1000,gid=1000,dmask=022,fmask=022,windows_names,exec 0 0
    
  7. Chroot to regenerate initramfs and GRUB:

    mkdir /mnt/system/{proc,mnt,sys,dev,run,tmp}
    mount /dev/sda2 /mnt/system/boot
    mount --bind /proc /mnt/system/proc
    mount --bind /sys /mnt/system/sys
    mount --bind /dev /mnt/system/dev
    mount --bind /run /mnt/system/run
    chroot /mnt/system
    dracut --regenerate-all --force
    grub2-mkconfig -o /boot/grub2/grub.cfg
    exit
    
  8. Unmount everything:

    umount /mnt/system/proc /mnt/system/sys /mnt/system/dev /mnt/system/run
    umount /mnt/system/boot /mnt/system
    cryptsetup luksClose myluks
    umount /mnt/backup
    

Step 4: Reboot and verify

  1. Remove the live USB and reboot into the SSD.
  2. Check mounts with lsblk and mount. Verify fstab with cat /etc/fstab.
  3. If issues, restore from the clone HDD: dd if=/dev/sdb of=/dev/sda bs=4M status=progress conv=fdatasync.
  4. Clean up the backup if unneeded: rm /mnt/backup/system_backup.tar.gz (after remounting).

I’m not keen reinstalling. In fact, never reformated any windows installation ever. Always upgraded all the way from WFWG 3.11. That would require weeks to recustomize my system the way it is now.

Or 5min with an Ansible playbook. :wink: (It took longer than 5min to write, though.)

Joking aside, if anything in this goes wrong, there is a significant chance you will have to reinstall.

Step 5 is quite obviously a reformat. The plaintext formatting of the dm-crypt block device passes through as a format in ciphertext to the /dev/sda3 block device.

Indeed you do not need to reset any of your LUKS keys to merely switch file systems. You’d do that for different reasons, like you think the DEK is somehow compromised. Reformating LUKS does mean changing the LUKS UUID so you’d have to go find where all that UUID is used and change it. (Off hand, /etc/crypttab, /etc/fstab, and the BLS drop-in snippets as the rd.luks hints.)

If you want to switch to argon2id PBKDF, which is the default now, you could just add another keyslot using that PBKDF with the same (or different, up to you) user passphrase, and then delete the old keyslot. Since this doesn’t change the DEK, it’s not a “reformat” of the LUKS partition.

Definitely backup first.

I want to get rid of btrfs before it causes serious problems

Btrfs isn’t going to cause you serious problems. Your underlying storage stack might cause you serious problems which Btrfs would complain about early and often compared to ext4, since that’s what it’s designed to do.

Never. I have a clone copy.

Then I am confused. Why would you spend the additional time to copy all the files into a TAR, risking that you forget a switch to preserve some metadata, instead of simply mounting the byte-identical clone and copying the files from there to your shiny new ext4?

1 Like

That is interesting. I cannot do that with 2 identical btrfs filesystems opened at the same time. Might be different whenever one is ext4. Good point. Deserves more thoughts. Thanks for the hint.

Revised Steps Using Clone HDD (Avoiding BTRFS UUID Conflict)

Step 1: Prepare the SSD (reformat to EXT4)

  1. Verify device names for the SSD (/dev/sda) and clone HDD (/dev/sdb):

    lsblk
    blkid
    

    Confirm /dev/sdb3 has the same LUKS UUID (luks-0140d69f-4781-4439-9339-94a101794e2e) as /dev/sda3. If the HDD device name differs, adjust commands accordingly.

  2. Open the LUKS container on the SSD:

    cryptsetup luksOpen /dev/sda3 myluks
    
  3. Create a new EXT4 filesystem on the SSD’s LUKS device, preserving the UUID:

    mkfs.ext4 -U 974a92ad-75ce-4957-9258-975411396cab -L / /dev/mapper/myluks
    

    (This overwrites the BTRFS on /dev/sda3, ensuring no UUID conflict when we mount /dev/sdb3’s BTRFS later.)

  4. Mount the new EXT4 filesystem:

    mkdir /mnt/system
    mount /dev/mapper/myluks /mnt/system
    mkdir -p /mnt/system/home/shizuma/.mozilla
    
  5. Close the LUKS container on the SSD (not strictly necessary but ensures cleanliness):

    umount /mnt/system
    cryptsetup luksClose myluks
    

Step 2: Mount the clone and copy files

  1. Open the LUKS container on the clone HDD:

    cryptsetup luksOpen /dev/sdb3 myluks_clone
    
  2. Mount the BTRFS subvolumes from the clone:

    mkdir /mnt/clone
    mount -o subvol=root,compress=zstd:1 /dev/mapper/myluks_clone /mnt/clone
    mkdir -p /mnt/clone/home/shizuma/.mozilla
    mount -o subvol=home,compress=zstd:1 /dev/mapper/myluks_clone /mnt/clone/home
    mount -o subvol=home/shizuma/.mozilla,compress=zstd:1 /dev/mapper/myluks_clone /mnt/clone/home/shizuma/.mozilla
    
  3. Re-open and remount the SSD’s LUKS container with the new EXT4:

    cryptsetup luksOpen /dev/sda3 myluks
    mount /dev/mapper/myluks /mnt/system
    mkdir -p /mnt/system/home/shizuma/.mozilla
    
  4. Copy files from the clone to the new EXT4 using rsync:

    rsync -aAXv --exclude=/mnt --exclude=/proc --exclude=/sys --exclude=/dev --exclude=/run --exclude=/tmp /mnt/clone/ /mnt/system/
    
    • -a preserves permissions, timestamps, ownership; -A preserves ACLs; -X preserves extended attributes; -v shows progress.
    • Excludes virtual filesystems.
    • For hundreds of thousands of files, this may take time (HDD to SSD). If interrupted, re-run to resume.

    Alternative with cp (simpler but less resumable):

    cp -a --no-preserve=xattr /mnt/clone/* /mnt/clone/.* /mnt/system/
    
    • -a preserves permissions and structure; --no-preserve=xattr skips extended attributes if unneeded (BTRFS xattrs may not apply to EXT4). rsync is preferred for reliability.
  5. Verify the copy:

    ls -la /mnt/system
    du -sh /mnt/system
    

Step 3: Configure the system

  1. Edit /etc/fstab on the new EXT4 to reflect the filesystem change:

    nano /mnt/system/etc/fstab
    

    Replace with:

    UUID=974a92ad-75ce-4957-9258-975411396cab / ext4 defaults,x-systemd.device-timeout=0 0 1
    UUID=8424fe94-203a-4c47-88d6-969b7c50661f /boot ext4 defaults 1 2
    UUID=D6022A010229E6E9 /mnt/Jeux ntfs-3g defaults,permissions,rw,uid=1000,gid=1000,dmask=022,fmask=022,windows_names,exec 0 0
    
  2. Chroot to regenerate initramfs and GRUB:

    mkdir /mnt/system/{proc,mnt,sys,dev,run,tmp}
    mount /dev/sda2 /mnt/system/boot
    mount --bind /proc /mnt/system/proc
    mount --bind /sys /mnt/system/sys
    mount --bind /dev /mnt/system/dev
    mount --bind /run /mnt/system/run
    chroot /mnt/system
    dracut --regenerate-all --force
    grub2-mkconfig -o /boot/grub2/grub.cfg
    exit
    
  3. Unmount everything:

    umount /mnt/system/proc /mnt/system/sys /mnt/system/dev /mnt/system/run
    umount /mnt/system/boot
    umount /mnt/system
    cryptsetup luksClose myluks
    umount /mnt/clone/home/shizuma/.mozilla
    umount /mnt/clone/home
    umount /mnt/clone
    cryptsetup luksClose myluks_clone
    

Step 4: Reboot and verify

  1. Remove the live USB and reboot into the SSD.

  2. Check mounts with lsblk and mount. Verify fstab with cat /etc/fstab.

  3. If the system fails to boot, restore from the clone HDD:

    dd if=/dev/sdb of=/dev/sda bs=4M status=progress conv=fdatasync
    

Thanks a lot. I wasn’t sure of that.