Fresh EndeavourOS installation on existing BTRFS within a LUKS2 volume

Hello dear EndeavourOS community,

I hope you can help me with a problem I’m having.

I have the following setup:

  • /dev/sda1 (ESP)
  • /dev/sda2 (LUKS2 volume containing BTRFS)
  • /dev/sda3 (LUKS2 volume as an encrypted swap partition)

This was originally installed using an EOS ISO and the Calamaris installer, with systemd-boot as the bootloader.

I want to be able to perform a fresh installation of EndeavourOS without losing my data. To prepare for this, I have already secured my @ and @home subvolumes by renaming them to @_old and @home_old. I have also removed the @cache subvolume so that the installer can simply create a new one. I don’t use the @log subvolume at all (I previously disabled it by removing the setting in /etc/calamaris/modules/mount.conf), and I plan to do the same for the new installation. My plan is to reformat /dev/sda1 and let the installer reinstall the bootloader there.

Now for the main question: How can I reinstall EndeavourOS onto an existing BTRFS filesystem within a LUKS2 volume so that new @, @home, and @cache subvolumes are created? This would allow me to keep my old @home_old subvolume temporarily to migrate data or potentially swap it back entirely. Since I need to keep the content of the LUKS2 volumes, I want to continue using them.

I considered (to trick the installer) doing an unencrypted installation in the Luks2 Volume and then manually adapting the old fstab, crypttab, and LUKS keyfile from the @_old Subvolumen. However, the Calamaris installer doesn’t seem to handle opened LUKS2 volumes correctly; it doesn’t offer the /dev/mapper/ devices as installation targets (even in manual partitioning) and instead tries to overwrite the LUKS2 partitions entirely.

Is there a way to install into an already mounted system, or is there another workaround for this?

Thanks in advance!

I’ll let @dalto provide you an answer to these questions since he is an expert on this. I use btrfs with grub because i can boot from snapshots.

systemd-boot does not natively parse or dynamically discover filesystem snapshots like GRUB does. Because systemd-boot reads static Boot Loader Specification (.conf) files directly from the ESP (EFI System Partition), it has no built-in awareness of Btrfs/ZFS subvolume histories

I also don’t use luks and wouldn’t be able to provide you with the correct answers to this.

Hello @ricklinux,

Thank you for your response.

Yes, GRUB is very capable and is a great bootloader. I consciously chose systemd-boot because of its small footprint and because it is part of the systemd suite. I don’t need the ability to boot into snapshots, and I am fine with using a live medium to make any necessary corrections or adjustments.

Also, a quick note for @dalto, just to avoid unnecessary explanations and to save him some time:

I have backups of everything, so basically nothing can be permanently broken. I am also comfortable making the necessary adjustments to fstab, crypttab, boot parameters, initramfs, etc., and I understand how these components relate to one another.

I simply need a way to install EndeavourOS onto an existing BTRFS filesystem in a LUKS2 Volume to avoid the unnecessary effort of copying data from one drive to another. It wouldn’t matter if the installer performed an unencrypted installation; I could handle the subsequent adjustments myself to make it compatible with the existing LUKS volumes. My only issue is that I can’t complete an installation via Calamaris without it wanting to overwrite a LUKS2 partition.

The only workaround I’m currently aware of is installing EndeavourOS onto an external drive to give the installer a target, and then moving that installation to the internal drive afterwards. I find this method quite inefficient, which is why I’m asking if there is a better way.

Hello EndeavourOS community,

A short update:

I have reproduced my situation in a VM using the current EndeavourOS ISO (EndeavourOS_Titan-Nova-2026.08.15.iso). Unfortunately, it was unsuccessful there as well.

For better traceability, here are a few screenshots of the problem:






Here the calamaris Istall log:

https://termbin.com/p6qsq

Calamares::JobThread::run()
2026-08-29 - 14:41:39 [6]:     Starting job "mount" ( 7 / 40 ) 
2026-08-29 - 14:41:40 [6]: [PYTHON JOB]: Found gettext "de_DE" in "/usr/share/locale/de_DE" 
2026-08-29 - 14:41:40 [6]:     .. Running QList("mount", "-t", "btrfs", "-o", "noatime,compress=zstd", "/dev/mapper/crypt_vda2", "/tmp/calamares-root-_5n8b5kn/") 
2026-08-29 - 14:41:40 [6]:     .. Target cmd: QList("mount", "-t", "btrfs", "-o", "noatime,compress=zstd", "/dev/mapper/crypt_vda2", "/tmp/calamares-root-_5n8b5kn/") Exit code: 32 output:
mount: /tmp/calamares-root-_5n8b5kn: special device /dev/mapper/crypt_vda2 does not exist.
       dmesg(1) may have more information after failed mount system call.
2026-08-29 - 14:41:40 [6]:     .. Running QList("udevadm", "settle") 
2026-08-29 - 14:41:40 [6]:     .. Running QList("sync") 
2026-08-29 - 14:41:40 [2]: WARNING: [PYTHON JOB]: "Cannot mount /dev/mapper/crypt_vda2" 
2026-08-29 - 14:41:40 [1]: virtual Calamares::JobResult Calamares::Python::Job::exec()
2026-08-29 - 14:41:40 [1]:     ERROR: Error while running: CalledProcessError: Command '['btrfs', 'subvolume', 'create', '/tmp/calamares-root-_5n8b5kn/@']' returned non-zero exit status 1.

At:
  /usr/lib/python3.14/subprocess.py(420): check_call
  /usr/lib/calamares/modules/mount/main.py(294): mount_partition
  /usr/lib/calamares/modules/mount/main.py(387): run
 
2026-08-29 - 14:41:40 [6]: virtual void 

Is the part from log showing the issue.

New ISO is only a rebuild with some fixes. But basically the same installer version.

Yes, I saw that. I just don’t understand why calamaris cannot be mounted /dev/mapper/crypt_vga2 ; it definitely exists:

[root@EndeavourOS ~]# lsblk -f
NAME           FSTYPE      FSVER            LABEL       UUID                                 FSAVAIL FSUSE% MOUNTPOINTS
loop0          squashfs    4.0                                                                     0   100% /run/archiso/airootfs
sr0            iso9660     Joliet Extension EOS_202608  2026-08-15-14-13-08-00                     0   100% /run/archiso/bootmnt
vda                                                                                                         
├─vda1         vfat        FAT32                        3824-B5A7                                           
├─vda2         crypto_LUKS 2                            0ede1ab3-7ca3-4e09-b344-6a9f0c68f8a0                
│ └─crypt_vda2 btrfs                        endeavouros 371723db-19c2-4814-8a55-77ad087d03a6                
└─vda3         crypto_LUKS 2                            6fa459f4-bff3-46d1-8e47-fdeff5b2ec3d

ls -la /dev/mapper/crypt_vda2 
lrwxrwxrwx 1 root root 7 Aug 29 16:42 /dev/mapper/crypt_vda2 -> ../dm-0

Manual mounting works without any problems, for example with:

mount /dev/mapper/crypt_vga2 /mnt

but that doesn’t help me because the installer wants to mount BTRFS in a temporary directory under /tmp, which changes every time.

Monitoring with dmesg also provided no new insights for me. The error must be caused by Calamares.

The only thing I was able to determine is that my manual mount is closed or no longer exists after Calamares has run and issued the error message. Something must be happening during the installation process that closes the mount beforehand, which then leads to the error.

However, if I don’t mount it manually beforehand, Calamares does not recognize the BTRFS within the LUKS volume and only offers to overwrite the LUKS volume.

Sorry, let me correct myself. I didn’t mean mounting; what I meant is that if I don’t manually open the LUKS2 volume beforehand, the Calamares installer does not recognize the BTRFS. And as soon as the installation begins, Calamares apparently closes the LUKS2 volume during the process, because after the error message, the LUKS2 volume is closed again.

I found the moment in the log where Calamares closes the LUKS2 volume again.

2026-08-29 - 14:41:37 [6]: virtual void Calamares::JobThread::run()
2026-08-29 - 14:41:37 [6]:     Starting job "Löse alle temporären mounts" ( 2 / 40 ) 
2026-08-29 - 14:41:37 [6]: virtual void Calamares::JobThread::run()
2026-08-29 - 14:41:37 [6]:     Starting job "Lösche Mount-Points für Partitionierungs Operation auf /dev/vda" ( 3 / 40 ) 
2026-08-29 - 14:41:37 [6]: QStringList getPartitionsForDevice(const QString&)
2026-08-29 - 14:41:37 [6]:     Reading from "/proc/partitions" looking for "vda" 
2026-08-29 - 14:41:37 [6]: virtual Calamares::JobResult ClearMountsJob::exec()
2026-08-29 - 14:41:37 [6]:     ClearMountsJob finished. Here's what was done: 
     "Mapper device /dev/mapper/crypt_vda2 erfolgreich geschlossen." 
2026-08-29 - 14:41:37 [6]:     .. Running QList("udevadm", "settle") 
2026-08-29 - 14:41:37 [6]:     .. Running QList("sync") 
2026-08-29 - 14:41:37 [6]: virtual void Calamares::JobThread::run()
2026-08-29 - 14:41:37 [6]:     Starting job "Partition /dev/vda1 (Dateisystem: fat32, Größe: 2048 MiB) auf vda formatieren" ( 4 / 40 ) 
2026-08-29 - 14:41:39 [6]: virtual void Calamares::JobThread::run()
2026-08-29 - 14:41:39 [6]:     Starting job "Setze Partitionsinformationen" ( 5 / 40 ) 
2026-08-29 - 14:41:39 [6]: QVariantList FillGlobalStorageJob::createPartitionList() const
2026-08-29 - 14:41:39 [6]:     Building partition information map 
2026-08-29 - 14:41:39 [6]:     .. partitions on "/dev/vda" 
2026-08-29 - 14:41:39 [6]:     ..  mapping for "" "unallocated" 

Unfortunately, I am not familiar enough with Calamares to fix this.