Guide: How to install and configure EndeavourOS for bootable BTRFS snapshots using limine and limine-snapper-sync

This is a write-up for installing EndeavourOS to utilize limine, dracut, snapper, limine-snapper-sync, and pac-snap packages to do a few things:

  • Create bootable BTRFS snapshots for quick and easy system-restore, in case an update or change has caused problems for your system.
  • Create bootable BTRFS snapshots even for kernel updates
  • Utilize limine bootloader, dracut, snapper, and snap-pac functionality for automatically creating both pre and post snapshots when updating your system with yay or pacman.

You can use this guide on your already existing EndeavourOS system, though you may have to modify your subvolume layout in some cases, and will have to complete this in your way. This guide is specific for individuals who are freshly installing EndeavourOS (Mercury)

By following this guide, you will be installing EndeavourOS, setting up BTRFS subvolumes, configuring limine to be your system’s bootloader, using EndeavourOS’ default of dracut for generating initramfs images, snapper for btrfs snapshots, limine-dracut-support to integrate limine and dracut to allow managing boot entries for the Limine bootloader on UEFI systems, snap-pac for automated snapshots when performing system upgrades, package updates, and kernel updates, and limine-snapper-sync to synchronize the functionality of snapper with limine. All of this together will allow you to boot into your snapshots for easy system restoration/recovery all while using limine’s quick bootloader functionality.

If you have any suggestions, please don’t hesitate to send them my way! I did this to my system, my girlfriend’s system, and our living room laptop and this guide worked for all of these systems just fine, so I figured this write-up might be helpful to some human beings out there who also want to use EndeavourOS with bootable BTRFS snapshots for quick and easy system restoration, without using GRUB (the decryption process of GRUB is noticably slower than an alternative like limine). I tested for all functionality, including kernel updates by waiting until the most recent (Linux 6.13.8-arch1-1) kernel was available in the official Arch repo, running yay, and watching all the automation work its magic. Please note that this process will not play nicely with the BTRFS Assistant package, but I will be testing in the neat future to confirm/deny this. Big props to the developers of all the required packages, in a really big way. If this process works for you, please consider donating to them so they feel some gratification and potentially inspiration to continue developing these packages. Here are the steps:

  1. Download EndeavourOS ISO, verify ISO and key signatures, and write a USB device with the ISO. Here’s how to verify key signatures from EndeavourOS discovery.

  2. Once you are in live environment, connect to your network/wi-fi if possible to opt for the online install method. I don’t think this part is required, but the online method is certainly the better option than the offline method.

  3. Before going through the OS setup, open terminal and run the following command:
    sudo nano /etc/calamares/modules/mount.conf
    This will cause your terminal to use the nano text editor so that we can edit this file to include the following subvolumes and associated directories.

mountPoint: /
subvolume: /@
mountPoint: /home
subvolume: /@home
mountPoint: /var/cache
subvolume: /@cache
mountPoint: /var/log
subvolume: /@log
mountPoint: /.snapshots
subvolume: /@snapshots
mountPoint: /var/lib/libvirt/images
subvolume: /@images

4.Notes:*
We are editing this calamares configuration file to specify from the beginning what we’d like our BTRFS subvolumes to be, as well as their associated directories. You could configure this post-OS installation, but I find this way to save more time, which we all seem to be on limited supply of these days haha
Below you will find an explanation of each proposed subvolume, their respecrice mountpoints, and a brief explanation as to why we are setting things up like this. The end result will be a snapshots which captures everything it should, and nothing it shouldn’t, as we aren’t concerned with backing up our home directory, logs, cache, etc. We want these directories to be untouched by the snapshot process, so if we were to restore from a snapshot, those nested subvolumes under the root (/@) subvolume would remain untouched. Please see below for a brief synopsis:
/@ subvolume is your root directory, everything other than the below directories and their child directories will get backed up.
/@cache subvolume is associated with the directory for cached data from applications, this isn’t worth backing up/snapshotting
/@log subvolume is associated with the directory which holds your log files, which we wouldn’t want to snapshot back to; we want to preserve our logs.
/@snapshots subvolume is associated with a directory for storing snapshots. We don’t want this directory being affected by restoring snapshots either.
/@images subvolume is associated with the directory for virtual machines images. This configuration might not be applicable to you, but I decided to include it in case anyone uses their EndeavourOS to run VMs. Setting this up will prevent restoring snapshot from affecting your VM images.

  1. Once you’ve edited the mount.conf file, run the EndeavourOS installer. At this point, you can choose any configuration you’d like, though two configurations are required for this process to work:
    You will need to choose systemd-boot as your bootloader and ensure BTRFS is chosen as your filesystem type for the storage device you plan to install EndeavourOS on. I recommend encrypting your drive for security sake, but you do you. You can choose any Desktop Environment, that aspect won’t affect the rest of this operation. Once you’ve made all of your choices in the installer, go ahead and install, wait, and reboot when prompted. Log into your system once it comes up.

  2. Limine is a modern, advanced, portable, multiprotocol bootloader and boot manager that supports Linux, multiboot1 and 2, the native Limine boot protocol, and more. We install and use this bootloader because it is the foundation for all the other packages to work in harmony with each other to achieve results similar to GRUB, but much more speedy, especially if you are using an encrypted drive.
    Once you’re in your system, open terminal and install Limine:
    sudo pacman -S limine

  3. Snapper is a is a tool created by openSUSE’s Arvin Schnell that helps with managing snapshots of Btrfs subvolumes. It can create and compare snapshots, revert between snapshots, and supports automatic snapshots timelines.
    After installing limine, let’s install snapper:
    sudo pacman -S snapper

  4. In the step after this, we will be using snapper to create a snapshot config for us. For this to be possible, we need to unmount and delete the /.snapshots directory we created during step 3.
    To unmount the snapshots directory and delete it from your system, use the following commands in terminal:
    sudo umount /.snapshots
    sudo rm -r /.snapshots

  5. Afterward, run the follow command to have snapper create a default config file:
    sudo snapper -c root create-config /

  6. Once the snapper default configuration file command has ran, we will need to delete the subvolume that the tool created. This seems redundant, but snapper was just trying to help. In our case, this help isn’t needed and could cause confusion down the line. To do this, enter the following command into your terminal:
    sudo btrfs subvolume delete /.snapshots
    Then we need to see what the default BTRFS subvolume is by entering the following into your terminal:
    sudo btrfs subvol get-default /
    You will see a response of: ID 5 (FS_TREE)
    We need to change this to be the ID of the root subvolume. To find this, we need to enter the following command into terminal:
    sudo btrfs subvol list /
    You will see this line returned at the top: ID 256 gen 280 top level 5 path @
    Now we just need to set this ID to be the default by entering the following into terminal:
    sudo btrfs subvolume set-default 256 /
    The ID should be exactly as listed here, but please use this opportunity to double check by looking at your specific ID for your root subvolume.

  7. Next, we need to install a few more prerequisites required by limine-snapper-sync for this process to work properly. Run the following commands to install all of these packages:
    sudo pacman -S btrfs-progs inotify-tools jdk-openjdk

  8. After those packages are installed, we will need to remove a package that was installed during the EndeavourOS installation. This package conflicts with a necessary package required for this process to operate properly. In your terminal, run the following command:
    sudo pacman -Rns kernel-install-for-dracut
    When you press enter, you will be prompted a question by the terminal:
    :: HoldPkg was found in target list. Do you want to continue? [y/N]
    Make sure you enter y or yes at this prompt, then proceed to the next step.

  9. Limine-dracut-support is designed for users who prefer Dracut for generating initramfs or UKI. It simplifies kernel management by automating the addition and removal of kernels in the Limine bootloader.
    Once the kernel-install-for-dracut package has been removed, run this command to install limine-dracut-support:
    yay -S limine-dracut-support

  10. Limine-snapper-sync is a tool that syncs Limine boot entries with Snapper snapshots.
    To install this package, run this command:
    yay -S limine-snapper-sync

  11. Run the following command in terminal to verify an ESP path is detected:
    bootctl --print-esp-path
    You should see the terminal respond with a path to your ESP, and since we are using Endeavour defaults for this aspect, you should very likely see /efi as the returned output in terminal. If so, continue on. If not, you will need to troubleshoot. I haven’t seen this fail yet, though.

  12. Once you’ve verified a path to your ESP, you will want to enable these services with the following commands:
    sudo systemctl enable --now limine-snapper-sync.service
    sudo systemctl enable --now snapper-cleanup.timer

  13. Look for file on your system with your /etc/default/ directory called limine. If it does or does not exist, the following command will either create and edit the file if it doesn’t already exist, or it will just edit the file if it does exist.
    sudo nano /etc/default/limine

  14. At this step, we need to ensure this configuration file for limine is configured properly for your system. Please reference the Tool Configuration section of the developer’s github for more details. I have posted below my configuration, but you may want to verify everything, but most importantly your ESP_PATH and TARGET_OS_NAME. To do this, you can run sudo nano /efi/limine.conf to reference OS name, and the bootctl --print-esp-path command from earlier should have shown your path as /efi. Once this entire process is setup, references to your snapshots will also have entries here. For me personally, I just copy and paste this block of code below into the /etc/default/limine using the nano text editor, save and exit:

### OS Entry Targeting:
### The tool does not automatically know the custom OS name used in /<ESP>/limine.conf, which can contain multiple OS names for multi-boot scenarios.
### You need to specify the corresponding OS name here to match the name used in /<ESP>/limine.conf.
### Alternatively, you can add "comment: machine-id=<machine-id>" to your OS entry block in /<ESP>/limine.conf. 
### The machine-ID helps the tool to automatically target the correct OS entry. Changing the OS name does not matter.
TARGET_OS_NAME="EndeavourOS"


### Max Snapshot Entries:
### Set the maximum number of snapshot entries for your OS. This depends on the ESP size and how many kernels will be installed.
### Note: The tool uses a deduplication function to prevent copying kernel versions that already exist.
MAX_SNAPSHOT_ENTRIES=8


### ESP Usage Limit:
### Set a usage limit for your ESP as a percentage between 1 and 99. The default value is 80. 
### The tool will stop creating new snapshot entries when this limit is reached.
### Tip for Arch Linux users: Install "journalctl-desktop-notification" from AUR, it will notify you when the usage limit is exceeded.
LIMIT_USAGE_PERCENT=80


### ESP Path:
### Specify the mount path of your ESP.
### Note: If you use systemd, you do not need to set this, as systemd (bootctl) will automatically detect the ESP path.
### However, specifying the ESP path manually can improve performance and reliability.
ESP_PATH="/efi"


### Snapper Configuration Name:
### Specify the Snapper configuration name. If not set, the tool will automatically detect it from "snapper list-configs".
### Specifying it manually improves performance by avoiding automatic detection overhead.
SNAPPER_CONFIG_NAME="root"


### Root Subvolume Path:
### Set the path to your root subvolume. The default value for some distros is "/@".
ROOT_SUBVOLUME_PATH="/@"


### Root Snapshot Path:
### Specify the path to your root snapshots. The default is "/@/.snapshots", which is used for the default Snapper layout.
### Note: The tool supports Snapper with any custom layout within the same filesystem, but not random Btrfs layouts without Snapper.
ROOT_SNAPSHOTS_PATH="/@snapshots"


### Restore Method Selection:
### Choose whether to enable rsync for restoration. If enabled, the tool will prompt you to choose between rsync or btrfs during the restore process.
### Advantage of rsync: The subvolume ID remains unchanged without "messing up" the Btrfs metadata.
### Disadvantage of rsync: Slower compared to Btrfs, which directly creates a new subvolume from the selected snapshot.
### "yes": Enables the prompt for choosing rsync or btrfs.
### "no":  Disables the prompt, defaulting to btrfs for "one-click-restore."
ENABLE_RSYNC_ASK=no


### Btrfs UUID:
### Specify the UUID of your Btrfs filesystem, used only during the restore process.
### If not set, the tool automatically determines the UUID during initialization and saves it in 'snapshots.json'. 
### If the saved UUID becomes outdated, set it manually.
#UUID=


### Authentication Method for Restore:
### Specify an authentication method for restore process. Options include 'sudo', 'doas', 'pkexec', `run0` or another method of your choice.
### If not set, 'pkexec' is used for Wayland/X11 environments, and 'sudo' for TTY.
#AUTH_METHOD=sudo


### Specify a terminal app and its argument to open the console UI for running the restore process with details.
### For example, "konsole -e" for KDE or "gnome-terminal -- bash -c" for GNOME.
#TERMINAL=konsole
#TERMINAL_ARG="-e"


### Snapshot Entry Formatting:
### Set the number of spaces to indent each line in all snapshot entries within /<ESP>/limine.conf.
SPACE_NUMBER=5


### Snapshot Name Format:
### Choose the format for how snapshot entries look in the Limine bootloader:
### 0. ID=111 2023-12-20 10:59:59 (default)
### 1. 111│2023-12-20 10:59:59
### 2. 111 │ 2023-12-20 10:59:59
### 3. 2023-12-20 10:59:59│111
### 4. 2023-12-20 10:59:59 │ 111
### 5. 2023-12-20 10:59:59
### 6. 111
SNAPSHOT_FORMAT_CHOICE=2


### Hash Function for Deduplication and Checksum:
### Select a hash function to avoid copying duplicate boot files. Options are "blake3", "sha1", or "sha256".
### WARNING: Changing the hash function will not affect files named with the previous hash function, potentially increasing duplication.
### Note: "blake3" must be installed manually if chosen.
HASH_FUNCTION=sha256


### Notification Icon:
### Set a custom icon to display in notifications when booting into a read-only snapshot and prompting for restoration.
NOTIFICATION_ICON="/usr/share/icons/hicolor/128x128/apps/LimineSnapperSync.png"


### Automatic Config Backup:
### Create a backup of 'limine.conf' and 'snapshots.json' before saving changes if they are older than the specified time (in hours).
### If not set, the default threshold is 8 hours.
BACKUP_THRESHOLD=8


### Commands Before Save
### Run custom commands before saving 'limine.conf'.
### If using multiple commands, separate them with '&&' or '||'.
### Note: Use single quotes (') for command argument when required, not double quotes (") as escape characters.
### Example: 'limine-reset-enroll' command is provided by 'limine-dracut-support' or 'limine-entry-tool' package.
COMMANDS_BEFORE_SAVE="limine-reset-enroll"


### Commands After Save
### Run custom commands after saving 'limine.conf'.
### If using multiple commands, separate them with '&&' or '||'.
### Note: Use single quotes (') for command argument when required, not double quotes (") as escape characters.
### Example: 'limine-enroll-config' command is provided by 'limine-dracut-support' or 'limine-entry-tool' package.
COMMANDS_AFTER_SAVE="limine-enroll-config"

  1. We’re almost there! Just need to install snap-pac to setup automatic snapshots which occur pre AND post any install/update/upgrade/removal pacman/yay package commands. Snap-pac is a set of pacman hooks that use snapper to create pre/post btrfs snapshots before and after pacman transactions, similar to how YaST does with OpenSUSE’s system. This is what ensures that you can reboot to a snapshot before a potentially problematic update was installed. Enter this in your terminal to install this package:
    sudo pacman -S snap-pac

  2. You’re done! All you should do now is reboot and test to verify that the functionality works. At reboot, you will see a different bootloader (Limine), which let’s your choose from your installed linux kernels, the snapshots won’t show just yet. My recommendation is to log back into your normal kernel, install a small package like fastfetch, though any package will do. Once you install the package, reboot, and at the limine splash screen, choose the snapshot that occurred before fastfetch was installed (or whatever package you chose to install to test), and see if the package exists anymore after booting into said snapshot. Once you boot into a snapshot, the inotify-tools package will display a notification saying to restore this snapshot if you’ve confirmed this is what you’d like to do. You can follow the developer’s README for this package for more information.

2 Likes

I would recommend against this layout if you are using btrfs-assistant since it makes restoring much more complicated. It would also allow you to skip several steps in the instructions.

I’m not aware, as I don’t use BTRFS assistant, I just let snap-pac do all the work and boot into a snapshot, restoring using the notification button for restoration. Why would this aspect affect BTRFS assistant?
I tried to minimize the total amount of steps through trial and error mixed with research into the packages and their scripts. This was the quickest and least amount of steps I could come up with, as creating the default snapper config using create-config / will cause issue if you try to run it without first removing the initial snapshots subvolume associated directory.
Let me know if you understand it differently, and I will test your proposed method soon! I did spend a long time figuring out the most efficient method, so I’m all ears to see if I missed some potential efficiency.

So the bulk of the work you’re doing is installing a new bootloader… yeah okay, but at least title the post something like “Guide, How to install and configure bootable BTRFS snapshot with limine bootloader” Glossing over the new bootloader in the intro/title makes it feel disingenuous, and is how you teach newbies to break their system in creative ways. esp the reddit post title feels this way. Uncomfortable to title this a generic “How to: btrfs bootable snaps” when it’s really more of a btrfs install guide for this specific bootloader.

I forget what exactly I had to do to get snapshots working but I severely overcomplicated it, and eventually just rolled back to a manual snapshot and did it in like 5 minutes once I learned what I was doing. It was along the lines of install snap-pac, snapper, snapper-support, and btrfs-assistant, then configure it in btrfs-assistant (which is easy enough to do manually now that I know more). And ofc do the initial install with grub, since sysd does not have bootable snap support last I looked a year ago. I even made a post here lauding the EnOS default btrfs subvol layout, because I tried to create them manually and it turns out that was a bunch of unnecessary work.

While I see your point and will edit this post to include more details, I certainly don’t think this is just a guide to installing and configuring the limine bootloader. Limine is a component of this process, and a foundational one at that, but the “cherry on the sundae” so to speak, IMO, is limine-snapper-sync package. There are other packages involved that make this all work together very well to get similar results to using grub with btrfs snapshots. The entire process to acheive this goal is detailed in this guide, not just limine.

I will edit this post to include more information, for beginners and explanation-sake, so I do appreciate that feedback!

Snapper doesn’t actually store the name of the subvolume that the snapshot was taken from. By default, Snapper creates .snapshots inside the subvolume. When you do a restore, btrfs-assistant uses that to know where the snapshot should be restored to. Since you have created an isolated @snapshots, btrfs-assistant can’t easily know where to restore it to. There is some special code in btrfs-assistant to handle this situation, but it is simpler and more reliable to not do that.

To be clear, I wasn’t implying you should change your guide. Just pointing that out for people who do use btrfs-assistant.

Right, but that is only a problem because you are manually mounting something there. If you didn’t, you could remove these steps:

As a side note, shouldn’t you be running sudo mount /.snapshots after that step?

1 Like

I have a similar setup having @snapshots sub-volume mounted at /snapshots. What’s the best way to do this with btrfs-assistant? Having reread what I quoted from you it does sound like what snapper creates is the preferred setup, I will redo my btrfs-assistant to match that setup, since it sounds like that’s the preferred method with snapper. Thanks @dalto!

1 Like

I will play with the BTRFS assistant on my main system later to verify if it does/does not work, thanks for pointing this out!
I have edited the post to include more details as well. Once I confirm/deny how BTRFS Assistant interacts with my system, I’ll update you and the post some more!
As for needing to remount, no, I don’t have to. I follow this process, reboot after it is all done, and then upon logging in, lsblk and sudo btrfs subvolume list / seem to show the appropriate mountpoints and subvolumes and my fstab also shows appropriately. Perhaps I could edit the post to mount -a after running snapper -c root create-config / to mount before installing snap-pac, I will have to look into this.

1 Like

I am not sure you really need to test it. But if you want to test that specific scenario, it needs to be tested it in a variety of situations.

  • In the running system
  • When booted off a snapshot
  • When booted off an ISO

All those scenarios present different challenges.

So it is getting remounted as part of the reboot.

Just be aware if anyone tried to take a snapshot after that step but before rebooting, it will fail.

1 Like

I’m going test later today, but just curious what you mean when you say “When booted off an ISO”. Do you mean a live, bootable USB ISO like one would use to chroot into their system? I assume that’s what you mean, but I just wanted to be sure before I start the testing :slight_smile:

Yes, you should be able to boot off an ISO, install btrfs-assistant and restore a subvolume

1 Like

Next week I will test adding the mount -a command to this guide to see if this can streamline the process just a bit more. Thanks for the call out on this!

Hi, I’ve two hard disks, and I need to arrange manual partition.

1st disk: partition /efi for about 2 or 3 gb
1st disk partition / for all the rest
2nd disk for all the space for /home

is correct 1st partition /efi?

I would like keep default subvol for endeavouros, for avoid problems with btrfs-assistant and follow the rest of this tutorial.

Any suggestion are accepted.

thank you since now

1 Like

If i understand your question, yes, the first partition will be /efi, make sure you click boot flag for that one.
But outside of that, yes, that should all work. Let me know how it goes!

Well installed with standard default layout for subvolume all has gone well without any issue.
The only problem is on boot, it doesn’t start automatically with endeavouros, on the boot screen, but I must press enter on endeavouros and then start goods.

How may I fix this?

Did you install more than one kernel? If so, this is normal behavior. You can either uninstall a kernel or just start choosing one. I always recommend having at least 2 kernels so if something goes wrong with one, at least you have a chance to still boot in with the other.

No standard and clean 1st installation (fresh)

Can you post a picture of what you are talking about so I can see? All I can imagine is you’re talking about kernel selection, so I’d need a picture so I can verify what you’re asking

when boot the system theresn’t any count down for start endeavouros, I must just press enter for launch endeavouros

This is how limine works by default.
You can edit the limine configuration to have no countdown/startup wait time for selection and then it’ll boot the top level kernel.