How to Install Fedora 38/39 with Full Disk Encryption, Snapshot and Rollback Support

By

Updated on

, ,

83

Comments

Install Fedora 38/39 with Full Disk Encryption, Snapshot and Rollback Support - Feature Image

Fedora Linux 39 has been released! Fedora 39 brings numerous performance and security improvements, as well as hardware support. This release also includes the latest Gnome 45 desktop with improved styling.

In this guide, I will show you how to install Fedora 39 with full disk encryption, snapshot, and rollback support. As a result, if you make a mistake with system configuration changes, package installations, or updates, you won’t have to worry about losing data. Simply restore the snapshot before your problematic change, and you’ll be fine.

In my previous post on how to install Fedora 37 with LUKS full disk encryption, I used Fedora’s default Anaconda installer. The Anaconda installer does not support encrypting the /boot directory. As a result, I had to first create a separate ext4 /boot partition, then after installation, move the contents of the /boot partition to the / volume, then delete the /boot partition, and finally merge the deleted space to the / volume. These are far too many steps.

So, instead of using the standard GUI Anaconda installer, I’ll install Fedora via the command line interface with DNF installroot and chroot environment. This will be straightforward, with no unnecessary steps.

I have updated this post for Fedora 39, which was originally intended for Fedora 38. In terms of btrfs snapshot and rollback support, nothing has changed between Fedora 38 and Fedora 39.

In case you’ve already followed a previous version of this tutorial and want to upgrade to Fedora 39, go straight to the section on upgrading at the end of this article and upgrade from Fedora 38 to Fedora 39. You don’t have to do anything else.

Here’s a quick rundown of what needs to be done:

  1. Boot from the Fedora 39 Workstation Live installation media. Create the necessary partitions on the disk where Fedora 39 will be installed.
  2. Enable LUKS encryption on the partition where Fedora will be installed, and then format all the partitions with the appropriate Linux file systems.
  3. Create and mount all necessary directories and subvolumes for Fedora installation in the /mnt directory.
  4. Install a minimal Fedora distribution in the /mnt directory.
  5. Finish the minimal installation by creating all of the required configuration files.
  6. Boot from Fedora Minimal and configure TPM2 or a key file to automatically decrypt your disk.
  7. Install the GNOME Desktop Environment.
  8. Create any additional subvolumes that are required based on your desktop environment choice.
  9. Install and configure the snapper tool so that you can create, delete, and compare snapshots, as well as undo changes made between snapshots.
  10. Install and configure the grub-btrfs tool so that you can boot to any snapshot from the GRUB menu.
  11. Take a subvolume snapshot of the main volume and set the subvolume as the default ‘/‘ file system to make rollback much easier when using the snapper tool.
  12. And finally, enable automatic timeline snapshots of the ‘/‘ file system using the snapper tool.

If you want to install Fedora 38/39 without LUKS Full Disk Encryption but still have Full System Rollback, please see my other article, How to Install Fedora 38/39 with Snapshot and Rollback Support.

Although it appears to be overwhelming, it is not. I’ll walk you through every step of the installation process.

So let's get started.

Table of Contents

1. Disk and Subvolumes Layout for Fedora

I'll use a hard disk with a capacity of 100 GIB. Fedora 39 suggests that the ESP be at least 500 MiB in size. So I'll create a 512 MiB EFI System Partition. You can, however, increase the size if necessary. I'll create a btrfs volume with the remaining disk space. Fedora creates a SwapOnZRAM during boot, so no separate swap partition is required.

This is how the disk partition looks.

NAME           SIZE   FSTYPE  LABEL    MOUNTPOINT
/dev/vda       100G
├─/dev/vda1    512M   vfat    EFI      /boot/efi
└─/dev/vda2   99.5G   btrfs   FEDORA   /

The system root will be installed on the LUKS encrypted btrfs main volume (/dev/vda2). Then, on the system root, I'll create the following subvolumes to keep them out of root file system snapshots. In the end, this is how the disk layout looks.

NAME              MOUNTPOINT                 TYPE
[main]            /                          mainvolume
home              /home                      subvolume
opt               /opt                       subvolume
cache             /var/cache                 subvolume
crash             /var/crash                 subvolume
log               /var/log                   subvolume
spool             /var/spool                 subvolume
tmp               /var/tmp                   subvolume
www               /var/www                   subvolume
AccountsService   /var/lib/AccountsService   subvolume
gdm               /var/lib/gdm               subvolume
images            /var/lib/libvirt/images    subvolume
.mozilla          /home/$USER/.mozilla       subvolume

The directories for which subvolumes are created and the reasons for doing so are listed below.

/home

Contains user data. It is created to keep user data separate and also to avoid loss of user data on system root rollbacks. To learn more about /home, check this link: /home.

/opt

Contains applications installed by a third party. It is excluded to prevent these applications from being uninstalled during rollbacks. To learn more about /opt, check this link: /opt.

/var/cache, /var/crash, /var/tmp

Directories contain temporary files and caches. So they are created to be excluded from snapshots. Fedora also mounts /tmp with tmpfs at boot, so a separate subvolume for /tmp is unnecessary. To learn more, check these links: /var/cache/var/crash/var/tmp/tmp.

/var/log

Contains log files. It is created to avoid the loss of log data during rollbacks. To learn more about /var/log, check this link: /var/log.

/var/spool

Contains data that is awaiting some kind of later processing such as mail, mail queues, printing, printer spool, and so on. Created to avoid a loss of mail, printing, and spool data after a rollback. To learn more about /var/spool, check this link: /var/spool.

/var/www

Web server directory. It is created to keep hosted web server data separate and to avoid data loss on system root rollbacks.

/var/lib/AccountsService, /var/lib/gdm

Contains login user and Gnome display information. These directories must be writable at all times. When you try to boot a snapshot from the GRUB menu, you are booting into a read-only snapshot, which causes the system to hang just before the Gnome login screen appears.

In case you're using a desktop environment other than Gnome, it's necessary to replace the '/var/lib/gdm' with one that's specific to your desktop environment.

For KDE, it is '/var/lib/sddm'.

For XFCE, it might be '/var/lib/lightdm' and '/var/lib/lightdm-data'. I haven't tested.

To find out about other desktop environments, refer to this page.

/var/lib/libvirt/images

The default location for libvirt-managed virtual machine images. Excluded to avoid replacing virtual machine images with older versions during a rollback.

/home/$USER/.mozilla

By default, Fedora Workstation includes the Firefox browser. If you take a snapshot of your home directory and later undo any changes, you don't want to lose any new bookmarks, passwords, and other user data.

So, I'll create a new subvolume for the '.mozilla' directory. This keeps it separate from the home subvolume and prevents data loss during undo operations.

If you use the Chrome web browser, create a subvolume for the '/home/$USER/.config/google-chrome' directory.

Depending on your usage, you may also want to consider creating subvolumes in your home directory for the following directories:

  • GnuPG/home/$USER/.gnupg
  • SSH/home/$USER/.ssh
  • Thunderbird Mail/home/$USER/.thunderbird

2. Create Partitions and File Systems

Boot your system using the Fedora 39 Workstation Live installer in UEFI mode. In the 'Welcome to Fedora' window, click the 'Not Now' button to return to the Gnome desktop. Next, launch Gnome Terminal to begin preparing the system for Fedora 39 installation.

Locate the disk on which you want to install Fedora. For me, it is /dev/vda. Yours might be different.

$ sudo -i

# lsblk -pd
NAME       MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
/dev/loop0   7:0    0  1.9G  1 loop 
/dev/loop1   7:1    0  7.6G  1 loop 
/dev/loop2   7:2    0   32G  0 loop 
/dev/sr0    11:0    1    2G  0 rom  /run/initramfs/live
/dev/zram0 251:0    0  3.8G  0 disk [SWAP]
/dev/vda   252:0    0  100G  0 disk

The Fedora 39 Workstation Live installer is missing the gdisk package, which is necessary for creating partitions. So, install it.

# dnf -y install gdisk

Create an EFI System Partition of 512 MiB. I'll name the partition 'EFI', but you can give it any name.

# sgdisk -n 1::+512M -t 1:ef00 -c 1:'EFI' /dev/vda

Create a Linux filesystem partition on which Fedora will be installed. I will use the entire remaining space. I'll name this partition 'Fedora 39', but you can give it any name.

# sgdisk -n 2:: -t 2:8300 -c 2:'Fedora 39' /dev/vda

List the partitions you just created to ensure that everything is in order.

# sgdisk -p /dev/vda
Disk /dev/vda: 209715200 sectors, 100.0 GiB
...
Total free space is 2014 sectors (1007.0 KiB)

Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048         1050623   512.0 MiB   EF00  EFI
   2         1050624       209715166   99.5 GiB    8300  Fedora 39

Format the /dev/vda1 partition with the FAT32 file system. I'll name the volume 'EFI', but you may name it whatever you want.

# mkfs.fat -F 32 -n EFI /dev/vda1

Initialize the /dev/vda2 partition as a LUKS device and set the initial passphrase.

# cryptsetup luksFormat --type luks2 --label FEDORA_LUKS \
    --pbkdf pbkdf2 --pbkdf-force-iterations 500000 /dev/vda2

WARNING!
========
This will overwrite data on /dev/vda2 irrevocably.

Are you sure? (Type 'yes' in capital letters): YES
Enter passphrase for /dev/vda2: 
Verify passphrase:

GRUB currently only supports pbkdf2 algorithm. For pbkdf2, the minimum iteration count is 1000 and the maximum is 4294967295. The more powerful your CPU, the higher the iteration count. And, the higher the iteration count, the longer it takes to unlock the LUKS in the GRUB. So I have set the iteration count to 500000. Lowering the iterations reduces security. To get around it, use a stronger passphrase with higher entropy (password entropy > 60 bits is suggested).

Now, open the LUKS device /dev/vda2 and map it to the temporary name tmpluks. I'll map the LUKS device with the proper UUID later. When prompted, enter the LUKS passphrase you provided.

# cryptsetup luksOpen /dev/vda2 tmpluks
Enter passphrase for /dev/vda2:

Format the mapped device with the btrfs file system. I'll name the volume FEDORA, but you may name it whatever you want.

# mkfs.btrfs -L FEDORA /dev/mapper/tmpluks

This is how your setup should look. The UUIDs will be unique to your system.

# udevadm trigger

# lsblk -p -o name,fstype,fsver,label,uuid /dev/vda
NAME                    FSTYPE      FSVER LABEL       UUID
/dev/vda                                              
├─/dev/vda1             vfat        FAT32 EFI         26CB-F6DD
└─/dev/vda2             crypto_LUKS 2     FEDORA_LUKS adcf2b8d-4884-4627-9964-ad790471eb13
  └─/dev/mapper/tmpluks btrfs             FEDORA      b481869f-2320-4d0a-8073-30d6c6f1cc81

3. Create Directories and Subvolumes

First, mount /dev/mapper/tmpluks to the /mnt directory.

# mount -v -o compress=zstd:1 /dev/mapper/tmpluks /mnt
# restorecon -RFv /mnt

Then, create the necessary directories and subvolumes. As previously stated, these subvolumes are created on the system root to avoid being included in the rollback regime because some of these directories contain temporary files and caches, others contain data that you do not want to lose if you rollback the system root, and some should be in Read-Write mode when booting into a Read-only snapshot.

# mkdir -vp /mnt/boot/efi
# mkdir -vp /mnt/var/lib/libvirt

# mount -v /dev/vda1 /mnt/boot/efi

# btrfs subvolume create /mnt/home
# btrfs subvolume create /mnt/opt

# btrfs subvolume create /mnt/var/cache
# btrfs subvolume create /mnt/var/crash
# btrfs subvolume create /mnt/var/log
# btrfs subvolume create /mnt/var/spool
# btrfs subvolume create /mnt/var/tmp
# btrfs subvolume create /mnt/var/www

# btrfs subvolume create /mnt/var/lib/libvirt/images

Change the permissions of the directory /mnt/var/tmp.

# chmod 1777 /mnt/var/tmp

# ls -lhd /mnt/var/tmp
drwxrwxrwt. 1 root root 0 Nov  7 10:14 /mnt/var/tmp

When using QCOW2 images as virtual disks in KVM, the IO performance suffers. So disable the CoW feature in the /mnt/var/lib/libvirt/images directory.

# chattr -R +C /mnt/var/lib/libvirt/images

# lsattr -d /mnt/var/lib/libvirt/images
---------------C------ /mnt/var/lib/libvirt/images

List the subvolumes. This is how it should look.

# btrfs subvolume list /mnt
ID 256 gen 8  top level 5 path home
ID 257 gen 9  top level 5 path opt
ID 258 gen 9  top level 5 path var/cache
ID 259 gen 9  top level 5 path var/crash
ID 260 gen 9  top level 5 path var/log
ID 261 gen 10 top level 5 path var/spool
ID 262 gen 11 top level 5 path var/tmp
ID 263 gen 10 top level 5 path var/www
ID 264 gen 10 top level 5 path var/lib/libvirt/images

I'll create the remaining subvolumes when I install the desktop environment.

4. Bootstrap a Fedora System in a Chroot Environment

Create a Fedora system in the /mnt directory using DNF installroot. I'm going to install the basesystem package first, which defines the basic elements of a Fedora system.

# dnf --releasever=39 --installroot=/mnt install basesystem

I'll build a Fedora system for version 39. If you want to install Fedora 38, replace --releasever=39 with --releasever=38.

Bind mount the directories /sys, /dev, and /proc into /mnt. Copy from 'for' to 'done', paste it into the terminal, and hit [Enter].

# for dir in sys dev proc ; do
    mount -v --rbind "/${dir}" "/mnt/${dir}" 
    mount -v --make-rslave "/mnt/${dir}"
done

Now that the directories have been bind mounted, install Fedora Minimal in the /mnt directory. I've included Fedora Minimal package groups, kernel, language packs, grub, and some other relevant packages.

# dnf --releasever=39 --installroot=/mnt install @minimal-environment \
    kernel langpacks-en glibc-langpack-en glibc-all-langpacks \
    grub2-efi-x64 grub2-efi-x64-modules grub2-tools grub2-common shim \
    cryptsetup vim git inotify-tools make tpm2-tss bash-completion finger

Replace --releasever=39 with --releasever=38 to install Fedora 38.

Copy the resolv.conf file from the host to the /mnt/etc/ directory so that you can connect to the internet. But first, you must delete the existing symbolic link to the resolv.conf file.

# rm -vf /mnt/etc/resolv.conf
# cp -v /etc/resolv.conf /mnt/etc/

Set the timezone, locale, keymap, hostname, and machine-id.

# systemd-firstboot --root=/mnt \
    --timezone=Asia/Kolkata \
    --locale=en_IN.UTF-8 \
    --keymap=in-eng \
    --hostname=fedora \
    --setup-machine-id

I set the time zone to India and the keyboard language to India English. Change the setting according to your location. I've also set the hostname to 'fedora', but you can name it whatever you want.

To determine your time zone, run the following command.

# timedatectl list-timezones

To determine your locale, run the following command.

# localectl list-locales

To determine your keymap, run the following command.

# localectl list-keymaps

While the systemd-firstboot command adds your keymap to the vconsole.conf file, it does not add the console font type. Fedora/RHEL by default uses the console font type 'eurlatgr' for European-based languages written in Latin/Greek letters. So let's include it.

# echo "FONT=eurlatgr" >> /mnt/etc/vconsole.conf

Read the file /mnt/usr/lib/kbd/consolefonts/README.eurlatgr for more information. You can find additional font types in the /mnt/usr/lib/kbd/consolefonts directory.

You must also configure the system keyboard mapping for X11 and the virtual console. The two most important options are 'X11 Layout' (XkbLayout) and 'X11 Variant' (XkbVariant). It is set by localectl, but because you cannot use localectl in the chroot environment, you must manually create a file to which localectl writes.

First, create a directory /mnt/etc/X11/xorg.conf.d.

# mkdir -vp /mnt/etc/X11/xorg.conf.d

Copy and paste the following command from 'cat' to 'EOF' into your terminal, then press the [Enter] key.

# cat <<'EOF' >> /mnt/etc/X11/xorg.conf.d/00-keyboard.conf
Section "InputClass"
        Identifier "system-keyboard"
        MatchIsKeyboard "on"
        Option "XkbLayout" "in"
        Option "XkbVariant" "eng"
EndSection
EOF

To determine your X11 Layout (XkbLayout), run the following command.

# localectl list-x11-keymap-layouts

For me, It was "in" to refer to India. You must, however, choose your relevant code.

To determine your X11 Variant (XkbVariant), run the following command. You can use the layout code obtained from the previous command to limit the output to variants appropriate for the specific layout.

# localectl list-x11-keymap-variants in

For me, it was "eng" for English. Yours could be different depending on your layout.

Finally, chroot into the /mnt directory.

# chroot /mnt /bin/bash

5. Create a User Account

Now that you're in a chroot environment, reinstall the polkit package before creating a user account so that the polkit's scripts are properly regenerated.

Enable the fastest mirrors to speed up package downloads. Copy the command from cat to EOF, paste it into your terminal, and hit [Enter].

# cat <<'EOF' >> /etc/dnf/dnf.conf
defaultyes=True
fastestmirror=True
max_parallel_downloads=10
EOF

Clear all previous caches and update the local DNF metadata cache.

# dnf clean all
# dnf makecache

Reinstall the polkit package.

# dnf -y reinstall polkit

After reinstalling the polkit package, proceed to create a user account.

A user account is required for logging into the Fedora Linux operating system. I'll create a user called 'madhu' with root privileges. Change the user name to something more specific to you.

# useradd madhu --comment 'Madhu Desai' --create-home --groups wheel \
    --shell /bin/bash

Set the user password.

# passwd madhu

Ensure that a user account has been created with the correct information

# finger madhu
Login: madhu          			Name: Madhu Desai
Directory: /home/madhu              	Shell: /bin/bash
Never logged in.
No mail.
No Plan.

6. Create the /etc/fstab File

You need to create /etc/fstab file so that the Fedora operating system will boot without any errors.

Set the btrfs subvolume mount options.

# OPTIONS="compress=zstd:1,x-systemd.device-timeout=0"

Get the UUID of your EFI partition.

# EFI_UUID="$(grub2-probe --target=fs_uuid /boot/efi)"

Get the UUID of your btrfs system root.

# ROOT_UUID="$(grub2-probe --target=fs_uuid /)"

Get your subvolmes.

# SUBVOLUMES=($(btrfs subvolume list / | awk '!/machines|portables/ {print $9}' | xargs))

Print system root mount in /etc/fstab file.

# printf "%-41s %-24s %-5s %-s %-sn" \
    "UUID=${ROOT_UUID}" \
    "/" \
    "btrfs" \
    "defaults,${OPTIONS}" \
    "0 0" >> /etc/fstab

Print EFI partition mount in /etc/fstab file.

# printf "%-41s %-24s %-5s %-s %-sn" \
    "UUID=${EFI_UUID}" \
    "/boot/efi" \
    "vfat" \
    "umask=0077,shortname=winnt" \
    "0 0" >> /etc/fstab

Print the rest of the subvolume mounts in /etc/fstab file. Copy from 'for' to 'done', paste it into the terminal, and hit [Enter].

# for dir in "${SUBVOLUMES[@]}" ; do
    printf "%-41s %-24s %-5s %-s %-sn" \
    "UUID=${ROOT_UUID}" \
    "/${dir}" \
    "btrfs" \
    "subvol=${dir},${OPTIONS}" \
    "0 0" >> /etc/fstab
    restorecon -RF "/${dir}"
done

Examine your /etc/fstab file. This is what it should look like. The UUID will be unique to your system.

# cat /etc/fstab
UUID=b481869f-2320-4d0a-8073-30d6c6f1cc81 /                        btrfs defaults,compress=zstd:1,x-systemd.device-timeout=0 0 0
UUID=26CB-F6DD                            /boot/efi                vfat  umask=0077,shortname=winnt 0 0
UUID=b481869f-2320-4d0a-8073-30d6c6f1cc81 /home                    btrfs subvol=home,compress=zstd:1,x-systemd.device-timeout=0 0 0
UUID=b481869f-2320-4d0a-8073-30d6c6f1cc81 /opt                     btrfs subvol=opt,compress=zstd:1,x-systemd.device-timeout=0 0 0
UUID=b481869f-2320-4d0a-8073-30d6c6f1cc81 /var/cache               btrfs subvol=var/cache,compress=zstd:1,x-systemd.device-timeout=0 0 0
UUID=b481869f-2320-4d0a-8073-30d6c6f1cc81 /var/crash               btrfs subvol=var/crash,compress=zstd:1,x-systemd.device-timeout=0 0 0
UUID=b481869f-2320-4d0a-8073-30d6c6f1cc81 /var/log                 btrfs subvol=var/log,compress=zstd:1,x-systemd.device-timeout=0 0 0
UUID=b481869f-2320-4d0a-8073-30d6c6f1cc81 /var/spool               btrfs subvol=var/spool,compress=zstd:1,x-systemd.device-timeout=0 0 0
UUID=b481869f-2320-4d0a-8073-30d6c6f1cc81 /var/tmp                 btrfs subvol=var/tmp,compress=zstd:1,x-systemd.device-timeout=0 0 0
UUID=b481869f-2320-4d0a-8073-30d6c6f1cc81 /var/www                 btrfs subvol=var/www,compress=zstd:1,x-systemd.device-timeout=0 0 0
UUID=b481869f-2320-4d0a-8073-30d6c6f1cc81 /var/lib/libvirt/images  btrfs subvol=var/lib/libvirt/images,compress=zstd:1,x-systemd.device-timeout=0 0 0

Mount all of the subvolumes listed in the /etc/fstab file.

# mount -va
/                        : ignored
/boot/efi                : already mounted
/home                    : successfully mounted
/opt                     : successfully mounted
/var/cache               : successfully mounted
/var/crash               : successfully mounted
/var/log                 : successfully mounted
/var/spool               : successfully mounted
/var/tmp                 : successfully mounted
/var/www                 : successfully mounted
/var/lib/libvirt/images  : successfully mounted

Check your subvolumes.

# btrfs subvolume list /
ID 256 gen 55 top level 5 path home
ID 257 gen 55 top level 5 path opt
ID 258 gen 55 top level 5 path var/cache
ID 259 gen 55 top level 5 path var/crash
ID 260 gen 55 top level 5 path var/log
ID 261 gen 55 top level 5 path var/spool
ID 262 gen 55 top level 5 path var/tmp
ID 263 gen 55 top level 5 path var/www
ID 264 gen 55 top level 5 path var/lib/libvirt/images
ID 265 gen 32 top level 5 path var/lib/portables

Your setup should now look somewhat like this.

# lsblk -p /dev/vda
NAME                    MAJ:MIN RM  SIZE RO TYPE  MOUNTPOINTS
/dev/vda                252:0    0  100G  0 disk  
├─/dev/vda1             252:1    0  512M  0 part  /boot/efi
└─/dev/vda2             252:2    0 99.5G  0 part  
  └─/dev/mapper/tmpluks 253:2    0 99.5G  0 crypt /var/lib/libvirt/images
                                                  /var/www
                                                  /var/tmp
                                                  /var/spool
                                                  /var/log
                                                  /var/crash
                                                  /var/cache
                                                  /opt
                                                  /home
                                                  /

7. Enable Crypto Disk and Snapshot Booting

Enable crypto disk and snapshot booting to allow encrypted /boot and snapper snapshots to boot directly from GRUB.

When you enable the GRUB_ENABLE_CRYPTODISK option in GRUB, it will check for encrypted disks and generate the extra commands needed to access them during boot.

With the SUSE_BTRFS_SNAPSHOT_BOOTING option in GRUB enabled, snapper snapshots can boot directly from GRUB. This is also useful when rolling back a snapshot.

Get the UUID of your LUKS partition.

# LUKS_DEV_UUID="$(cryptsetup luksUUID /dev/vda2)"

# echo $LUKS_DEV_UUID
adcf2b8d-4884-4627-9964-ad790471eb13

First, create a /etc/default/grub file with the UUID of your LUKS partition in it.

Copy the command from cat to EOF, paste it into your terminal, and hit [Enter].

# cat <<EOF > /etc/default/grub
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="\$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="rd.luks.uuid=luks-$LUKS_DEV_UUID quiet"
GRUB_DISABLE_RECOVERY="true"
GRUB_ENABLE_BLSCFG=true
GRUB_ENABLE_CRYPTODISK=y
SUSE_BTRFS_SNAPSHOT_BOOTING="true"
EOF

This is how it should look. The UUID will be unique to your system.

# cat /etc/default/grub
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="rd.luks.uuid=luks-adcf2b8d-4884-4627-9964-ad790471eb13 quiet"
GRUB_DISABLE_RECOVERY="true"
GRUB_ENABLE_BLSCFG=true
GRUB_ENABLE_CRYPTODISK=y
SUSE_BTRFS_SNAPSHOT_BOOTING="true"

You must also modify the /boot/efi/EFI/fedora/grub.cfg file now that crypto disk and snapshot booting are enabled.

# sed -i "1i cryptomount -u ${LUKS_DEV_UUID//-/}" /boot/efi/EFI/fedora/grub.cfg
# sed -i '1i set btrfs_relative_path="yes"' /boot/efi/EFI/fedora/grub.cfg

This is how it should appear. The UUID in the cryptomount line is that of the /dev/vda2 partition, with no dashes (-).

# cat /boot/efi/EFI/fedora/grub.cfg
set btrfs_relative_path="yes"
cryptomount -u adcf2b8d488446279964ad790471eb13
search --no-floppy --fs-uuid --set=dev b481869f-2320-4d0a-8073-30d6c6f1cc81
set prefix=($dev)/boot/grub2
export $prefix
configfile $prefix/grub.cfg

Then, update the grub.cfg file.

# grub2-mkconfig -o /boot/grub2/grub.cfg

This is how the GRUB BLS should appear.

# grubby --info=DEFAULT
index=0
kernel="/boot/vmlinuz-6.5.9-300.fc39.x86_64"
args="ro rd.luks.uuid=luks-adcf2b8d-4884-4627-9964-ad790471eb13 quiet ${extra_cmdline}"
root="UUID=b481869f-2320-4d0a-8073-30d6c6f1cc81"
initrd="/boot/initramfs-6.5.9-300.fc39.x86_64.img"
title="Fedora Linux (6.5.9-300.fc39.x86_64) 39 (Thirty Nine)"
id="7615546df2f845a38fa3f1a06a5f127d-6.5.9-300.fc39.x86_64"

Add the encrypted block device to the /etc/crypttab file so that it is enabled when the system boots.

# echo "luks-${LUKS_DEV_UUID} UUID=${LUKS_DEV_UUID} none discard" >> /etc/crypttab

# cat /etc/crypttab
luks-adcf2b8d-4884-4627-9964-ad790471eb13 UUID=adcf2b8d-4884-4627-9964-ad790471eb13 none discard

Enable NetworkManager and auditd systemd services.

# systemctl enable NetworkManager
# systemctl enable auditd

Execute the following command so that the SELinux contexts are relabeled on the next boot.

# fixfiles onboot

Now exit the chroot environment, unmount all mounts, and restart your computer.

# exit
# umount -vR /mnt
# reboot

The system will reboot twice. The first time it boots, it relabels SELinux contexts, and the second time it logs in to the operating system.

You will also be prompted for the passphrase twice. The first time is before loading GRUB, and the second time is before mounting the root file system. In the following section, I will enable the single passphrase prompt.

Depending on your computer's CPU, it may take up to 15 seconds for the GRUB to display the menu. So please be patient.

When you input your passphrase in the first LUKS prompt, no "*" cursor indication appears. So you should assume you have entered your passphrase correctly. Simply enter your LUKS passphrase blindly and hit the [Enter] key.

The Fedora Minimal installation is now complete.

You may now remove the Fedora Live installation media. From now on, the configuration will be performed on Fedora 39 Minimal itself.

8. Bypass the Additional Passphrase Prompt

While GRUB requests a passphrase in order to decrypt the encrypted /boot files, this information is not passed on to initramfs. As a result, the root (/) must be unlocked once more during the initramfs stage. This means that the user must enter his passphrase twice.

I'll show you two methods for automatically decrypting your disk without requiring a passphrase: using a key file or TPM2. Choose your preferred method.

8.1 Using a Key File

If you want to decrypt your LUKS-encrypted volumes using a key file, use this method. SecureBoot does not need to be enabled for this.

First, change to super user.

$ sudo -i

Create the /etc/cryptsetup-keys.d directory if it does not already exist.

# mkdir -v /etc/cryptsetup-keys.d

Create a key file with 4KiB of random data. The key file has to be in volume.key format.

# dd if=/dev/random \
   of=/etc/cryptsetup-keys.d/luks-$(cryptsetup luksUUID /dev/vda2).key \
   bs=512 count=8

Ensure that only the root user has read access to the key file.

# chmod 0400 /etc/cryptsetup-keys.d/*.key

Attach the created key to the encrypted device’s available key slot. When prompted for a passphrase, enter the same LUKS passphrase.

# cryptsetup luksAddKey \
    --pbkdf pbkdf2 \
    --pbkdf-force-iterations 500000 \
    /dev/vda2 \
    /etc/cryptsetup-keys.d/luks-$(cryptsetup luksUUID /dev/vda2).key

Add the key to /etc/dracut.conf.d/cryptodisk.conf file to include it in the initramfs image.

# echo 'install_items+=" /etc/cryptsetup-keys.d/* "' \
    >> /etc/dracut.conf.d/cryptodisk.conf

Rebuild the initramfs image.

# dracut --verbose --force

Reboot the computer to ensure that everything is working properly. The LUKS passphrase should only be asked once before the GRUB menu appears.

# reboot

8.2 Using TPM2 Method

This method allows you to decrypt your LUKS-encrypted volumes using the TPM on your computer. You must have SecureBoot enabled for this method to work.

First, change to super user.

$ sudo -i

Make sure SecureBoot is enabled.

# mokutil --sb-state
SecureBoot enabled

If it is disabled, you must enable it in the BIOS.

Next, see if your computer supports TPM.

# systemd-cryptenroll --tpm2-device=list
PATH        DEVICE      DRIVER 
/dev/tpmrm0 MSFT0101:00 tpm_crb

As you can see from the output, my TPM2 device node path is /dev/tpmrm0.

Get the UUID of your LUKS partition.

# LUKS_DEV_UUID="$(cryptsetup luksUUID /dev/vda2)"

# echo $LUKS_DEV_UUID
adcf2b8d-4884-4627-9964-ad790471eb13

Now enroll your encrypted volume. When prompted for a passphrase, enter the same LUKS passphrase.

# systemd-cryptenroll /dev/disk/by-uuid/${LUKS_DEV_UUID} \
    --tpm2-device=/dev/tpmrm0
🔐 Please enter current passphrase for disk /dev/disk/by-uuid/adcf2b8d-4884-4627-9964-ad790471eb13: ***********             
New TPM2 token enrolled as key slot 1.

According to the systemd-cryptenroll man page, it should be sufficient for most applications to bind against PCR 7, which is also the default. For more information, see man systemd-cryptenroll.

Add the TPM2 device node path to the kernel command line parameter 'rd.luks.options='.

# grubby --update-kernel=ALL \
    --args="rd.luks.options=tpm2-device=/dev/tpmrm0"

Check to see if the TPM2 device node path has been added to the grub kernel parameter.

# grubby --info=DEFAULT
index=0
kernel="/boot/vmlinuz-6.5.9-300.fc39.x86_64"
args="ro rd.luks.uuid=luks-adcf2b8d-4884-4627-9964-ad790471eb13 quiet ${extra_cmdline} rd.luks.options=tpm2-device=/dev/tpmrm0"
root="UUID=b481869f-2320-4d0a-8073-30d6c6f1cc81"
initrd="/boot/initramfs-6.5.9-300.fc39.x86_64.img"
title="Fedora Linux (6.5.9-300.fc39.x86_64) 39 (Thirty Nine)"
id="7615546df2f845a38fa3f1a06a5f127d-6.5.9-300.fc39.x86_64"

Changes should also be reflected in the /etc/crypttab file.

# echo "luks-${LUKS_DEV_UUID} UUID=${LUKS_DEV_UUID} - tpm2-device=auto,discard" > /etc/crypttab

# cat /etc/crypttab
luks-adcf2b8d-4884-4627-9964-ad790471eb13 UUID=adcf2b8d-4884-4627-9964-ad790471eb13 - tpm2-device=auto,discard

Update the grub.cfg file.

# grub2-mkconfig -o /boot/grub2/grub.cfg

Run dracut to rebuild the initramfs.

# dracut --verbose --force

Check that the TPM has been added to the encrypted volume.

# systemd-cryptenroll /dev/vda2
SLOT TYPE    
   0 password
   1 tpm2

Finally, reboot.

# reboot

The LUKS passphrase should only be asked once before the GRUB menu appears.

9. Install the Desktop Environment

You can now install the desktop environment of your choice.

Change to super user.

$ sudo -i

To find out which desktop environments are available to you, run the following command.

# dnf group list available hidden --ids

I will, however, install the GNOME 45 desktop environment that comes with Fedora's official desktop edition 'Fedora Workstation'.

# dnf group install 'Fedora Workstation'

Create subvolumes for the directories /var/lib/AccountsService and /var/lib/gdm. These subvolumes are only relevant if you install GNOME desktop. They contain login user information as well as Gnome display information.

Create AccountsService subvolume.

# mv -v /var/lib/AccountsService{,-old}
# btrfs subvolume create /var/lib/AccountsService
# cp -arv /var/lib/AccountsService{-old/.,/}
# restorecon -RFv /var/lib/AccountsService
# rm -rfv /var/lib/AccountsService-old

Create gdm subvolume.

# mv -v /var/lib/gdm{,-old}
# btrfs subvolume create /var/lib/gdm
# cp -arv /var/lib/gdm{-old/.,/}
# restorecon -RFv /var/lib/gdm
# rm -rfv /var/lib/gdm-old
# chmod 1770 /var/lib/gdm
# chown -R gdm:gdm /var/lib/gdm

In the user's home directory, create a subvolume called .mozilla.

# USERNAME="$(id -nu 1000)"

# echo $USERNAME
madhu

# btrfs subvolume create /home/$USERNAME/.mozilla
# chown -R $USERNAME: /home/$USERNAME/.mozilla
# restorecon -RFv /home/$USERNAME/.mozilla

In the /etc/fstab file, add the newly created subvolumes. The updated lines are displayed in amber. Replace UUID and user name with your setup's UUID and user name.

# cat /etc/fstab
UUID=b481869f-2320-4d0a-8073-30d6c6f1cc81 /                        btrfs defaults,compress=zstd:1,x-systemd.device-timeout=0 0 0
UUID=26CB-F6DD                            /boot/efi                vfat  umask=0077,shortname=winnt 0 0
UUID=b481869f-2320-4d0a-8073-30d6c6f1cc81 /home                    btrfs subvol=home,compress=zstd:1,x-systemd.device-timeout=0 0 0
UUID=b481869f-2320-4d0a-8073-30d6c6f1cc81 /opt                     btrfs subvol=opt,compress=zstd:1,x-systemd.device-timeout=0 0 0
UUID=b481869f-2320-4d0a-8073-30d6c6f1cc81 /var/cache               btrfs subvol=var/cache,compress=zstd:1,x-systemd.device-timeout=0 0 0
UUID=b481869f-2320-4d0a-8073-30d6c6f1cc81 /var/crash               btrfs subvol=var/crash,compress=zstd:1,x-systemd.device-timeout=0 0 0
UUID=b481869f-2320-4d0a-8073-30d6c6f1cc81 /var/log                 btrfs subvol=var/log,compress=zstd:1,x-systemd.device-timeout=0 0 0
UUID=b481869f-2320-4d0a-8073-30d6c6f1cc81 /var/spool               btrfs subvol=var/spool,compress=zstd:1,x-systemd.device-timeout=0 0 0
UUID=b481869f-2320-4d0a-8073-30d6c6f1cc81 /var/tmp                 btrfs subvol=var/tmp,compress=zstd:1,x-systemd.device-timeout=0 0 0
UUID=b481869f-2320-4d0a-8073-30d6c6f1cc81 /var/www                 btrfs subvol=var/www,compress=zstd:1,x-systemd.device-timeout=0 0 0
UUID=b481869f-2320-4d0a-8073-30d6c6f1cc81 /var/lib/libvirt/images  btrfs subvol=var/lib/libvirt/images,compress=zstd:1,x-systemd.device-timeout=0 0 0
UUID=b481869f-2320-4d0a-8073-30d6c6f1cc81 /var/lib/AccountsService btrfs subvol=var/lib/AccountsService,compress=zstd:1,x-systemd.device-timeout=0 0 0
UUID=b481869f-2320-4d0a-8073-30d6c6f1cc81 /var/lib/gdm             btrfs subvol=var/lib/gdm,compress=zstd:1,x-systemd.device-timeout=0 0 0
UUID=b481869f-2320-4d0a-8073-30d6c6f1cc81 /home/madhu/.mozilla     btrfs subvol=home/madhu/.mozilla,compress=zstd:1,x-systemd.device-timeout=0 0 0

Reload the /etc/fstab file to mount all filesystems.

# systemctl daemon-reload

# mount -va
/                        : ignored
/boot/efi                : already mounted
/home                    : already mounted
/opt                     : already mounted
/var/cache               : already mounted
/var/crash               : already mounted
/var/log                 : already mounted
/var/spool               : already mounted
/var/tmp                 : already mounted
/var/www                 : already mounted
/var/lib/libvirt/images  : already mounted
/var/lib/AccountsService : successfully mounted
/var/lib/gdm             : successfully mounted
/home/madhu/.mozilla     : successfully mounted

Check your subvolumes.

# btrfs subvolume list /
ID 256 gen 126 top level 5 path home
ID 257 gen 55  top level 5 path opt
ID 258 gen 121 top level 5 path var/cache
ID 259 gen 111 top level 5 path var/crash
ID 260 gen 132 top level 5 path var/log
ID 261 gen 119 top level 5 path var/spool
ID 262 gen 120 top level 5 path var/tmp
ID 263 gen 107 top level 5 path var/www
ID 264 gen 111 top level 5 path var/lib/libvirt/images
ID 265 gen 119 top level 5 path var/lib/portables
ID 266 gen 119 top level 5 path var/lib/machines
ID 267 gen 124 top level 5 path var/lib/AccountsService
ID 268 gen 126 top level 5 path var/lib/gdm
ID 269 gen 127 top level 256 path home/madhu/.mozilla

Your setup should now look somewhat like this.

# lsblk -o name,mountpoints /dev/vda
NAME                                          MOUNTPOINTS
vda                                           
├─vda1                                        /boot/efi
└─vda2                                        
  └─luks-adcf2b8d-4884-4627-9964-ad790471eb13 /home/madhu/.mozilla
                                              /var/lib/gdm
                                              /var/lib/AccountsService
                                              /var/www
                                              /var/tmp
                                              /var/spool
                                              /var/lib/libvirt/images
                                              /var/log
                                              /var/crash
                                              /var/cache
                                              /opt
                                              /home
                                              /

Now that you've installed the desktop environment, enable boot animation and make the spinner theme your default.

# plymouth-set-default-theme spinner -R

Enable Red Hat Graphical Boot in /etc/default/grub as well.

# sed -i 's/quiet/rhgb quiet/' /etc/default/grub

Finally, update the grub.cfg file.

# grub2-mkconfig -o /boot/grub2/grub.cfg

Fedora Workstation installation is complete. Reboot the system now.

# reboot

You will now be logged into the Fedora 39 Workstation with the all-new Gnome 45 desktop interface.

Install Fedora 38/39 with Full Disk Encryption, Snapshot and Rollback Support - Gnome 45

10. Install and Configure Snapper

Install snapper and the optional package python3-dnf-plugin-snapper. The python3-dnf-plugin-snapper package allows you to create pre and post snapshots every time you install a package on the system with the dnf package manager.

$ sudo dnf install snapper python3-dnf-plugin-snapper

Create new snapper configurations named root and home for the Btrfs volume at / and /home, respectively.

$ sudo snapper -c root create-config /
$ sudo snapper -c home create-config /home

The snapper configuration files will be saved in the /etc/snapper/configs/ directory.

Verify the snapper configuration files have been created.

$ sudo snapper list-configs
Config | Subvolume
-------+----------
home   | /home    
root   | /

Allow regular user to use snapper without requiring root privileges. Add your user name to the snapper's root and home configurations to set the ACL on the /.snapshots and /home/.snapshots directories.

$ sudo snapper -c root set-config ALLOW_USERS=$USER SYNC_ACL=yes
$ sudo snapper -c home set-config ALLOW_USERS=$USER SYNC_ACL=yes

Add the newly created snapshot subvolumes to the /etc/fstab file. The updated lines are in amber.

$ sudo vim /etc/fstab
...
UUID=b481869f-2320-4d0a-8073-30d6c6f1cc81 /home/madhu/.mozilla     btrfs subvol=home/madhu/.mozilla,compress=zstd:1,x-systemd.device-timeout=0 0 0
UUID=b481869f-2320-4d0a-8073-30d6c6f1cc81 /.snapshots              btrfs subvol=.snapshots,compress=zstd:1,x-systemd.device-timeout=0 0 0
UUID=b481869f-2320-4d0a-8073-30d6c6f1cc81 /home/.snapshots         btrfs subvol=home/.snapshots,compress=zstd:1,x-systemd.device-timeout=0 0 0

Reload the /etc/fstab file.

$ sudo systemctl daemon-reload
$ sudo mount -va

Your subvolumes will look like this.

$ sudo btrfs subvolume list /
ID 256 gen 176 top level 5 path home
ID 257 gen 55  top level 5 path opt
ID 258 gen 168 top level 5 path var/cache
ID 259 gen 137 top level 5 path var/crash
ID 260 gen 177 top level 5 path var/log
ID 261 gen 163 top level 5 path var/spool
ID 262 gen 166 top level 5 path var/tmp
ID 263 gen 137 top level 5 path var/www
ID 264 gen 137 top level 5 path var/lib/libvirt/images
ID 265 gen 162 top level 5 path var/lib/portables
ID 266 gen 162 top level 5 path var/lib/machines
ID 267 gen 162 top level 5 path var/lib/AccountsService
ID 268 gen 164 top level 5 path var/lib/gdm
ID 269 gen 127 top level 256 path home/madhu/.mozilla
ID 270 gen 174 top level 5 path .snapshots
ID 271 gen 174 top level 256 path home/.snapshots

And your setup should look something like this.

$ lsblk -o name,mountpoints /dev/vda
NAME                                          MOUNTPOINTS
vda                                           
├─vda1                                        /boot/efi
└─vda2                                        
  └─luks-adcf2b8d-4884-4627-9964-ad790471eb13 /home/.snapshots
                                              /.snapshots
                                              /home/madhu/.mozilla
                                              /var/www
                                              /var/tmp
                                              /var/spool
                                              /var/log
                                              /var/lib/libvirt/images
                                              /var/lib/gdm
                                              /var/lib/AccountsService
                                              /var/crash
                                              /var/cache
                                              /opt
                                              /home
                                              /

Disable the indexing of the .snapshots directories by updatedb. It is enabled by default, which can cause significant slowdown and excessive memory usage if you have a large number of snapshots.

$ echo 'PRUNENAMES = ".snapshots"' | sudo tee -a /etc/updatedb.conf

List the snapshots for / volume. For the root, you may use snapper -c root ls or simply snapper ls. Both provide the same output.

$ snapper ls
 # | Type   | Pre # | Date | User | Cleanup | Description | Userdata
---+--------+-------+------+------+---------+-------------+---------
0  | single |       |      | root |         | current     |

List the snapshots for /home subvolume.

$ snapper -c home ls
 # | Type   | Pre # | Date | User | Cleanup | Description | Userdata
---+--------+-------+------+------+---------+-------------+---------
0  | single |       |      | root |         | current     |

At this stage, you do not have any snapshots, we will create some later.

11. Install and Configure Grub-Btrfs

The grub-btrfs package adds 'Fedora Linux snapshots' to the GRUB menu and allows you to test a snapshot in read-only mode before rolling back to it in read-write mode.

Clone the grub-btrfs repository.

$ git clone https://github.com/Antynea/grub-btrfs

The setup is pre-configured to work with Arch and Gentoo out of the box. You must make a few changes to the grub-btrfs config file to make it work with Fedora.

$ cd grub-btrfs

$ sed -i '/#GRUB_BTRFS_SNAPSHOT_KERNEL/a GRUB_BTRFS_SNAPSHOT_KERNEL_PARAMETERS="systemd.volatile=state"' config
$ sed -i '/#GRUB_BTRFS_GRUB_DIRNAME/a GRUB_BTRFS_GRUB_DIRNAME="/boot/grub2"' config
$ sed -i '/#GRUB_BTRFS_MKCONFIG=/a GRUB_BTRFS_MKCONFIG=/sbin/grub2-mkconfig' config
$ sed -i '/#GRUB_BTRFS_SCRIPT_CHECK=/a GRUB_BTRFS_SCRIPT_CHECK=grub2-script-check' config

Then install it.

$ sudo make install

Update grub.cfg and enable the grub-btrfsd.service.

$ sudo grub2-mkconfig -o /boot/grub2/grub.cfg
$ sudo systemctl enable --now grub-btrfsd.service

You will receive the 'No snapshots found' error since you have not yet created any snapshots, but don't worry, it will function properly after you do.

Your grub-btrfs installation is now complete. You may now delete the cloned grub-btrfs repository.

$ cd ..
$ rm -rvf grub-btrfs

12. Create a System Root Snapshot and Set It as the Default

Now that everything in Fedora has been installed and configured, it is time to take a subvolume snapshot of the main volume and set the subvolume as the default ‘/‘ file system. By manually creating a subvolume snapshot of the main volume and making it the default, you can easily rollback without having to specify the snapshot number and the 'ambit' during the rollback when using the snapper tool.

Create a directory named '1' in the /.snapshots directory.

$ sudo mkdir -v /.snapshots/1

Create an XML file called info.xml in the /.snapshots/1/ directory. Copy the following command from 'sudo' to 'EOF', paste it into your terminal, and hit the <Enter> button.

$ sudo bash -c "cat > /.snapshots/1/info.xml" <<EOF
<?xml version="1.0"?>
<snapshot>
  <type>single</type>
  <num>1</num>
  <date>$(date -u +"%F %T")</date>
  <description>first root subvolume</description>
</snapshot>
EOF

Verify that the date is set properly and is in the Coordinated Universal Time (UTC) format.

$ cat /.snapshots/1/info.xml
<?xml version="1.0"?>
<snapshot>
  <type>single</type>
  <num>1</num>
  <date>2023-11-08 07:28:14</date>
  <description>first root subvolume</description>
</snapshot>

Now, create a read-write subvolume snapshot of the system root in the /.snapshots/1/ directory.

$ sudo btrfs subvolume snapshot / /.snapshots/1/snapshot

Get the subvolid of the /.snapshots/1/snapshot subvolume.

$ sudo btrfs inspect-internal rootid /.snapshots/1/snapshot
272

Using subvolid 272, set the /.snapshots/1/snapshot subvolume as the default subvolume for the root (/) filesystem.

$ sudo btrfs subvolume set-default 272 /

And reboot your system.

$ sudo reboot

After rebooting, confirm that the /.snapshots/1/snapshot subvolume is indeed the default for the / filesystem.

$ sudo btrfs subvolume get-default /
ID 272 gen 218 top level 270 path .snapshots/1/snapshot

Now check the snapshots in snapper.

$ snapper ls
 # | Type   | Pre # | Date                                   | User | Cleanup | Description          | Userdata
---+--------+-------+----------------------------------------+------+---------+----------------------+---------
0  | single |       |                                        | root |         | current              |         
1* | single |       | Wednesday 08 November 2023 12:58:14 PM | root |         | first root subvolume |

As you can see, the /.snapshots/1/snapshot subvolume is also visible as snapshot #1 in snapper. The asterisk (*) indicates that this snapshot is the default and is currently active.

The installation of Fedora 39 with LUKS full disk encryption, snapshot, and rollback support is now complete. You can now begin taking snapshots.

13. Snapper Tests

I'll run some tests here to make sure everything is in working order and that there are no problems.

Test 1: Undo the Changes Made by the DNF Installer

In this test, I will use the dnf package manager to install a small package named ps_mem. I'll check the system after it's installed to see what changes were made. I'll then attempt to undo the changes and see if I can get the system back to its pre-installation state.

Install the ps_mem package. It displays the core memory used per program (not per process).

$ sudo dnf install ps_mem

Run the ps_mem program to see if it was installed successfully.

$ sudo ps_mem
 Private  +   Shared  =  RAM used	Program

148.0 KiB +  16.5 KiB = 164.5 KiB	fusermount3
200.0 KiB +  13.5 KiB = 213.5 KiB	inotifywait
292.0 KiB +  15.5 KiB = 307.5 KiB	mcelog
...
 48.3 MiB +   6.3 MiB =  54.6 MiB	gnome-software
234.1 MiB +  24.2 MiB = 258.3 MiB	gnome-shell
367.5 MiB +   2.0 MiB = 369.6 MiB	packagekitd
---------------------------------
                          1.3 GiB
=================================

Check the snapper for snapshots.

$ snapper ls
 # | Type   | Pre # | Date                                   | User | Cleanup | Description                 | Userdata
---+--------+-------+----------------------------------------+------+---------+-----------------------------+---------
0  | single |       |                                        | root |         | current                     |         
1* | single |       | Wednesday 08 November 2023 12:58:14 PM | root |         | first root subvolume        |         
2  | pre    |       | Wednesday 08 November 2023 01:13:40 PM | root | number  | /usr/bin/dnf install ps_mem |         
3  | post   |     2 | Wednesday 08 November 2023 01:13:41 PM | root | number  | /usr/bin/dnf install ps_mem |

As you can see, the ps_mem package has pre (#2) and post (#3) snapshots.

Let's take a look at the changes it made to the system between snapshots #2 and #3.

$ snapper status 2..3
+..... /usr/bin/ps_mem
c..... /usr/lib/sysimage/rpm/rpmdb.sqlite-shm
c..... /usr/lib/sysimage/rpm/rpmdb.sqlite-wal
+..... /usr/share/doc/ps_mem
+..... /usr/share/doc/ps_mem/LICENSE
+..... /usr/share/man/man1/ps_mem.1.gz
c..... /var/lib/dnf/history.sqlite-shm
c..... /var/lib/dnf/history.sqlite-wal
-..... /var/lib/dnf/rpmdb_lock.pid

Now I'll undo the changes.

$ sudo snapper undochange 2..3
create:1 modify:4 delete:4

Check again to ensure that the ps_mem package was successfully uninstalled.

$ sudo ps_mem
sudo: ps_mem: command not found

Cool! The undo was successful. But, because I want to keep the package ps_mem, I'll undo the changes again. This time between snapshots #3 and #2.

$ sudo snapper undochange 3..2
create:4 modify:4 delete:1

Now run ps_mem again to see if it exists.

$ sudo ps_mem
 Private  +   Shared  =  RAM used	Program

148.0 KiB +  16.5 KiB = 164.5 KiB	fusermount3
200.0 KiB +  13.5 KiB = 213.5 KiB	inotifywait
292.0 KiB +  15.5 KiB = 307.5 KiB	mcelog
...
 48.3 MiB +   6.3 MiB =  54.6 MiB	gnome-software
234.1 MiB +  24.2 MiB = 258.3 MiB	gnome-shell
367.5 MiB +   2.0 MiB = 369.6 MiB	packagekitd
---------------------------------
                          1.3 GiB
=================================

Test 1 is successful.

Test 2: Undo Any Changes Made to Individual Files

Assume you're configuring something and editing a configuration file. Then you realize you messed up the configuration file. You want to see what changes you made to the original file and possibly wish you could undo the changes.

You can use snapper to undo not only all changes between two snapshots, but also a single file.

In this test, I will simply delete the last line of the /etc/hosts file. Then I'll compare it to the same file in snapshot #3 to see what changed and if I can undo all of the changes and restore it to its original state.

This is how the original /etc/hosts file looks.

$ cat /etc/hosts
# Loopback entries; do not change.
# For historical reasons, localhost precedes localhost.localdomain:
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
# See hosts(5) for proper format and other examples:
# 192.168.1.10 foo.mydomain.org foo
# 192.168.1.13 bar.mydomain.org bar

Now I'll remove the last line.

$ sudo sed -i '$d' /etc/hosts

$ cat /etc/hosts
# Loopback entries; do not change.
# For historical reasons, localhost precedes localhost.localdomain:
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
# See hosts(5) for proper format and other examples:
# 192.168.1.10 foo.mydomain.org foo

Using snapper, compare the /etc/hosts file with the one in snapshot #3.

$ snapper diff 3..0 /etc/hosts
--- /.snapshots/3/snapshot/etc/hosts	2023-07-25 05:30:00.000000000 +0530
+++ /etc/hosts	2023-11-08 13:21:53.905775069 +0530
@@ -4,4 +4,3 @@
 ::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
 # See hosts(5) for proper format and other examples:
 # 192.168.1.10 foo.mydomain.org foo
-# 192.168.1.13 bar.mydomain.org bar

The number 0 in the command 3..0 represents the current snapshot, while the number 3 represents snapshot #3.

As you can see in the last line, the /etc/hosts file in the current snapshot is missing that line compared to the one in snapshot #3. If you want to learn how to read the output, take a look at the man pages man diff and man snapper.

To replace the /etc/hosts file with the one in snapshot #3, use the following command.

$ sudo snapper undochange 3..0 /etc/hosts
create:0 modify:1 delete:0

Check to see if the /etc/hosts file has indeed been rolled back.

$ cat /etc/hosts
# Loopback entries; do not change.
# For historical reasons, localhost precedes localhost.localdomain:
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
# See hosts(5) for proper format and other examples:
# 192.168.1.10 foo.mydomain.org foo
# 192.168.1.13 bar.mydomain.org bar

Test 2 is successful.

Test 3: Create Manual Pre-Post Snapshots and Undo the Changes

In my previous article, I performed a manual pre-post snapshots test for installing a package with Gnome Software. The concept for both tests is the same. If you want, you can also run that test.

In this test, I will begin by creating manual 'pre' snapshots of the / and /home directories. Then I'll install a small package called Color Picker (gcolor3) from GitHub by compiling it from the source file. When I'm finished, regardless of whether the compiling was successful or not, I'll create 'post' snapshots for the previously created 'pre' snapshots. I'll then look at the changes it made to the system between the pre-post snapshots and, finally, undo everything.

Create a manual 'pre' snapshot for both the / and /home directories.

$ snapper -c root create -t pre -c number -d 'Pre Color Picker'
$ snapper -c home create -t pre -c number -d 'Pre Color Picker'

List the snapshots.

$ snapper ls
 # | Type   | Pre # | Date                                   | User  | Cleanup | Description                 | Userdata
---+--------+-------+----------------------------------------+-------+---------+-----------------------------+---------
0  | single |       |                                        | root  |         | current                     |         
1* | single |       | Wednesday 08 November 2023 12:58:14 PM | root  |         | first root subvolume        |         
2  | pre    |       | Wednesday 08 November 2023 01:13:40 PM | root  | number  | /usr/bin/dnf install ps_mem |         
3  | post   |     2 | Wednesday 08 November 2023 01:13:41 PM | root  | number  | /usr/bin/dnf install ps_mem |         
4  | pre    |       | Wednesday 08 November 2023 01:29:23 PM | madhu | number  | Pre Color Picker            |         

$ snapper -c home ls
 # | Type   | Pre # | Date                                   | User  | Cleanup | Description      | Userdata
---+--------+-------+----------------------------------------+-------+---------+------------------+---------
0  | single |       |                                        | root  |         | current          |         
1  | pre    |       | Wednesday 08 November 2023 01:29:33 PM | madhu | number  | Pre Color Picker | 

Install the pre-requisite packages before compiling the source file.

$ sudo dnf install meson gcc-c++ libhandy-devel libportal-devel \
    libportal-gtk3-devel

Compile the source.

$ git clone https://github.com/Hjdskes/gcolor3.git
$ cd gcolor3
$ meson setup build
$ ninja-build -C build
$ sudo ninja-build -C build install

Make sure the Color Picker package has been installed properly. Enter gcolor3 into the terminal and hit <Enter>. The Color Picker app must be open and appear as shown.

Install Fedora 38/39 with Full Disk Encryption, Snapshot and Rollback Support - Gcolor3

Now that you have successfully installed the Color Picker application, close the application and create 'post' snapshots for the / and /home directories.

$ snapper -c home create -t post --pre-number 1 -c number -d 'Post Color Picker'
$ snapper -c root create -t post --pre-number 4 -c number -d 'Post Color Picker'

List the snapshots.

$ snapper -c root ls
 # | Type   | Pre # | Date                                   | User  | Cleanup | Description                                                                            | Userdata
---+--------+-------+----------------------------------------+-------+---------+----------------------------------------------------------------------------------------+---------
0  | single |       |                                        | root  |         | current                                                                                |         
1* | single |       | Wednesday 08 November 2023 12:58:14 PM | root  |         | first root subvolume                                                                   |         
2  | pre    |       | Wednesday 08 November 2023 01:13:40 PM | root  | number  | /usr/bin/dnf install ps_mem                                                            |         
3  | post   |     2 | Wednesday 08 November 2023 01:13:41 PM | root  | number  | /usr/bin/dnf install ps_mem                                                            |         
4  | pre    |       | Wednesday 08 November 2023 01:29:23 PM | madhu | number  | Pre Color Picker                                                                       |         
5  | pre    |       | Wednesday 08 November 2023 01:32:52 PM | root  | number  | /usr/bin/dnf install meson gcc-c++ libhandy-devel libportal-devel libportal-gtk3-devel |         
6  | post   |     5 | Wednesday 08 November 2023 01:33:16 PM | root  | number  | /usr/bin/dnf install meson gcc-c++ libhandy-devel libportal-devel libportal-gtk3-devel |         
7  | post   |     4 | Wednesday 08 November 2023 01:36:50 PM | madhu | number  | Post Color Picker                                                                      |         

$ snapper -c home ls
 # | Type   | Pre # | Date                                   | User  | Cleanup | Description       | Userdata
---+--------+-------+----------------------------------------+-------+---------+-------------------+---------
0  | single |       |                                        | root  |         | current           |         
1  | pre    |       | Wednesday 08 November 2023 01:29:33 PM | madhu | number  | Pre Color Picker  |         
2  | post   |     1 | Wednesday 08 November 2023 01:36:37 PM | madhu | number  | Post Color Picker | 

Review the changes made to the system between the pre and post snapshots.

$ snapper -c home status 1..2
c..... /home/madhu/.cache/gnome-software/appstream/components.xmlb
+..... /home/madhu/.config/gcolor3
+..... /home/madhu/.config/gcolor3/config.ini
...
-..... /home/madhu/.local/share/gvfs-metadata/root-1cb93aa6.log
+..... /home/madhu/.local/share/gvfs-metadata/root-dd9963bb.log
c..... /home/madhu/.local/share/ibus-typing-booster/debug.log

$ snapper -c root status 4..7
c..... /boot/grub2/grub-btrfs.cfg
c..... /etc/ld.so.cache
+..... /usr/bin/brotli
...
c..... /var/lib/dnf/history.sqlite-wal
+..... /var/lib/PackageKit/prepared-update
c..... /var/lib/PackageKit/transactions.db

This is the total number of files added, removed, or modified.

$ snapper -c home status 1..2 | wc -l
278

$ snapper -c root status 4..7 | wc -l
13912

I'll now undo the changes in the / and /home directories.

$ sudo snapper -c home undochange 1..2
create:1 modify:3 delete:274

$ sudo snapper -c root undochange 4..7
create:0 modify:11 delete:13901

The Color Picker package will be completely removed from the system.

Log out and then log back in.

$ gnome-session-quit

Check again to see if the Color Picker has been completely removed.

$ gcolor3
bash: gcolor3: command not found...

Since you removed the Color Picker package, there is no reason to keep its pre-post snapshots if you do not intend to use it again. So you can delete those snapshots.

$ snapper -c home delete 1-2
$ snapper -c root delete 4-7

Test 3 is successful.

Test 4: Rollback to a Previous Snapshot from the GRUB Menu

In this rollback test, I will delete the most critical files and directories on which the Linux operating system relies. These include Linux kernel and initramfs files in the /boot directory, the /etc directory, which contains all configuration files, and the /usr directory, which contains all drivers, kernel modules, and library files.

Once I delete these files and directories, I will be unable to issue any commands because the Linux OS is pretty much dead, and the system will undoubtedly fail the next time it boots. So I'll hard boot the system and see if I can save the day by rolling back to a working snapshot.

So, before I delete them, here's how they appear.

$ sudo du -sch /boot /etc /usr
151M	/boot
33M	/etc
5.6G	/usr
5.8G	total

Now delete the files and directories.

$ sudo rm -rvf /boot/{vmlinuz,initramfs}* /etc /usr

Boom!!! All critical files have been removed. Your Linux system is no longer operational. Reboot the system. Your system should now fail to boot and display something like this.

Install Fedora 38/39 with Full Disk Encryption, Snapshot and Rollback Support - Boot Error

Return to the GRUB menu and this time boot from snapshot #3.

Install Fedora 38/39 with Full Disk Encryption, Snapshot and Rollback Support - Snapshots Menu
Install Fedora 38/39 with Full Disk Encryption, Snapshot and Rollback Support - Snapshot No 3
Install Fedora 38/39 with Full Disk Encryption, Snapshot and Rollback Support - Select Latest Kernel

Open the terminal and make sure everything is back to normal.

$ sudo ls /boot /etc /usr

Because you booted into the snapshot, the '/' file system is read-only.

$ sudo btrfs property get -ts /
ro=true

Now that everything appears to be operating properly, it is time to roll back this snapshot in read-write mode.

$ snapper ls
 # | Type   | Pre # | Date                                   | User | Cleanup | Description                 | Userdata
---+--------+-------+----------------------------------------+------+---------+-----------------------------+---------
0  | single |       |                                        | root |         | current                     |         
1+ | single |       | Wednesday 08 November 2023 12:58:14 PM | root |         | first root subvolume        |         
2  | pre    |       | Wednesday 08 November 2023 01:13:40 PM | root | number  | /usr/bin/dnf install ps_mem |         
3- | post   |     2 | Wednesday 08 November 2023 01:13:41 PM | root | number  | /usr/bin/dnf install ps_mem |

As you can see from the output, snapshot #1 has a '+' symbol, indicating that it is the default subvolume, whereas snapshot #3 has a '-' symbol, indicating that it is the currently booted subvolume.

$ sudo snapper rollback
Ambit is classic.
Creating read-only snapshot of default subvolume. (Snapshot 4.)
Creating read-write snapshot of current subvolume. (Snapshot 5.)
Setting default subvolume to snapshot 5.

Now, reboot your system.

$ sudo reboot

The first thing you should do after a rollback is to update the grub.cfg file so that the GRUB menu snapshots are always in sync.

$ sudo grub2-mkconfig -o /boot/grub2/grub.cfg

Check the system once again.

$ sudo du -sch /boot /etc /usr
151M	/boot
33M	/etc
5.6G	/usr
5.8G	total

$ sudo btrfs property get -ts /
ro=false

$ snapper ls
 # | Type   | Pre # | Date                                   | User | Cleanup | Description                 | Userdata     
---+--------+-------+----------------------------------------+------+---------+-----------------------------+--------------
0  | single |       |                                        | root |         | current                     |              
1  | single |       | Wednesday 08 November 2023 12:58:14 PM | root | number  | first root subvolume        |              
2  | pre    |       | Wednesday 08 November 2023 01:13:40 PM | root | number  | /usr/bin/dnf install ps_mem |              
3  | post   |     2 | Wednesday 08 November 2023 01:13:41 PM | root | number  | /usr/bin/dnf install ps_mem |              
4  | single |       | Wednesday 08 November 2023 01:57:03 PM | root | number  | rollback backup of #1       | important=yes
5* | single |       | Wednesday 08 November 2023 01:57:03 PM | root |         | writable copy of #3         | 

$ sudo btrfs subvolume list /
ID 256 gen 311 top level 5 path home
ID 257 gen 55 top level 5 path opt
ID 258 gen 309 top level 5 path var/cache
ID 259 gen 137 top level 5 path var/crash
ID 260 gen 311 top level 5 path var/log
ID 261 gen 309 top level 5 path var/spool
ID 262 gen 311 top level 5 path var/tmp
ID 263 gen 137 top level 5 path var/www
ID 264 gen 137 top level 5 path var/lib/libvirt/images
ID 265 gen 198 top level 5 path var/lib/portables
ID 266 gen 198 top level 5 path var/lib/machines
ID 267 gen 309 top level 5 path var/lib/AccountsService
ID 268 gen 309 top level 5 path var/lib/gdm
ID 269 gen 127 top level 256 path home/madhu/.mozilla
ID 270 gen 311 top level 5 path .snapshots
ID 271 gen 293 top level 256 path home/.snapshots
ID 272 gen 304 top level 270 path .snapshots/1/snapshot
ID 273 gen 230 top level 270 path .snapshots/2/snapshot
ID 274 gen 305 top level 270 path .snapshots/3/snapshot
ID 275 gen 304 top level 270 path .snapshots/4/snapshot
ID 276 gen 311 top level 270 path .snapshots/5/snapshot

$ sudo btrfs subvolume get-default /
ID 276 gen 311 top level 270 path .snapshots/5/snapshot

You successfully restored the system with the latest working snapshot in read and write mode.

Test 4 is successful.

14. Make a Snapshot the New System Root

Now that you've tested the snapper undo and rollback features and are hopefully satisfied with the results, you might want to set one of the snapshots as the new default system root and resume normal operating system use.

But first, let me show you how to determine how much space each snapshot takes up on your disk.

$ sudo btrfs filesystem du -s --human-readable /.snapshots/*/snapshot
     Total   Exclusive  Set shared  Filename
  51.41MiB       0.00B    37.66MiB  /.snapshots/1/snapshot
   5.51GiB    32.00KiB     2.90GiB  /.snapshots/2/snapshot
   5.51GiB    52.00KiB     2.90GiB  /.snapshots/3/snapshot
  51.41MiB       0.00B    37.66MiB  /.snapshots/4/snapshot
   5.51GiB   248.00KiB     2.90GiB  /.snapshots/5/snapshot

As you can see from the output above, snapshot #1 has an exclusive size of 0 bytes. This is because, as you may recall, I deleted all of the files recursively. Snapshot #4 is also 0 bytes in size because it is a read-only duplicate of snapshot #1.

To find out how the 'Total' and 'Set shared' values are calculated, see the man page man btrfs-filesystem.

Now, let's return to making a snapshot the new system root.

$ snapper ls
 # | Type   | Pre # | Date                                   | User | Cleanup | Description                 | Userdata     
---+--------+-------+----------------------------------------+------+---------+-----------------------------+--------------
0  | single |       |                                        | root |         | current                     |              
1  | single |       | Wednesday 08 November 2023 12:58:14 PM | root | number  | first root subvolume        |              
2  | pre    |       | Wednesday 08 November 2023 01:13:40 PM | root | number  | /usr/bin/dnf install ps_mem |              
3  | post   |     2 | Wednesday 08 November 2023 01:13:41 PM | root | number  | /usr/bin/dnf install ps_mem |              
4  | single |       | Wednesday 08 November 2023 01:57:03 PM | root | number  | rollback backup of #1       | important=yes
5* | single |       | Wednesday 08 November 2023 01:57:03 PM | root |         | writable copy of #3         |

The output indicates that snapshot #5 is the default subvolume, and since it is operational, you can simply delete the remaining snapshots and move on.

However, I will use snapshot #2 as the default because it is a 'pre' snapshot that was created just before ps_mem was installed and is clean.

So, first, delete all of the snapshots except #2. You cannot delete snapshot #5 because it is the active one.

$ snapper delete 1
$ snapper delete 3-4

$ snapper ls
 # | Type   | Pre # | Date                                   | User | Cleanup | Description                 | Userdata
---+--------+-------+----------------------------------------+------+---------+-----------------------------+---------
0  | single |       |                                        | root |         | current                     |         
2  | pre    |       | Wednesday 08 November 2023 01:13:40 PM | root | number  | /usr/bin/dnf install ps_mem |         
5* | single |       | Wednesday 08 November 2023 01:57:03 PM | root |         | writable copy of #3         | 

Create a directory named '1' in the /.snapshots directory.

$ sudo mkdir -v /.snapshots/1

Copy the info.xml file from /.snapshots/2/ to /.snapshots/1/.

$ sudo cp -v /.snapshots/2/info.xml /.snapshots/1/

Edit the /.snapshots/1/info.xml file and change the content from this...

$ sudo cat /.snapshots/1/info.xml
<?xml version="1.0"?>
<snapshot>
  <type>pre</type>
  <num>2</num>
  <date>2023-11-08 07:43:40</date>
  <description>/usr/bin/dnf install ps_mem</description>
  <cleanup>number</cleanup>
</snapshot>

...to this. Changes are in amber.

$ sudo cat /.snapshots/1/info.xml
<?xml version="1.0"?>
<snapshot>
  <type>single</type>
  <num>1</num>
  <date>2023-11-08 07:43:40</date>
  <description>new root subvolume</description>
</snapshot>

Create a read-write subvolume snapshot of snapshot #2 in the /.snapshots/1/ directory.

$ sudo btrfs subvolume snapshot /.snapshots/2/snapshot /.snapshots/1/snapshot

Get the subvolid of the /.snapshots/1/snapshot subvolume.

$ sudo btrfs inspect-internal rootid /.snapshots/1/snapshot
277

Using subvolid 277, set the /.snapshots/1/snapshot subvolume as the default subvolume for the root (/) filesystem.

$ sudo btrfs subvolume set-default 277 /

Then reboot.

$ sudo reboot

After rebooting, confirm that the /.snapshots/1/snapshot subvolume is indeed the default for the / filesystem.

$ sudo btrfs subvolume get-default /
ID 277 gen 338 top level 270 path .snapshots/1/snapshot

And is writable.

$ sudo btrfs property get -ts /
ro=false

Take a look at the snapper now.

$ snapper ls
 # | Type   | Pre # | Date                                   | User | Cleanup | Description                 | Userdata
---+--------+-------+----------------------------------------+------+---------+-----------------------------+---------
0  | single |       |                                        | root |         | current                     |         
1* | single |       | Wednesday 08 November 2023 01:13:40 PM | root |         | new root subvolume          |         
2  | pre    |       | Wednesday 08 November 2023 01:13:40 PM | root | number  | /usr/bin/dnf install ps_mem |         
5  | single |       | Wednesday 08 November 2023 01:57:03 PM | root |         | writable copy of #3         |

As you can see, snapshot #1 is the default. You can now delete the remaining snapshots.

$ snapper delete 2-5

$ snapper ls
 # | Type   | Pre # | Date                                   | User | Cleanup | Description        | Userdata
---+--------+-------+----------------------------------------+------+---------+--------------------+---------
0  | single |       |                                        | root |         | current            |         
1* | single |       | Wednesday 08 November 2023 01:13:40 PM | root |         | new root subvolume |

$ sudo btrfs filesystem du -s --human-readable /.snapshots/*/snapshot
     Total   Exclusive  Set shared  Filename
   5.51GiB   312.00KiB     2.90GiB  /.snapshots/1/snapshot

You're done.

15. Enable Automatic Timeline Snapshots

Now that you've finished everything, you can enable automatic timeline snapshots. When the timeline is enabled, a snapshot is created once every hour. Once per day, the timeline cleanup algorithm cleans up the snapshots.

It is enabled by default in both the root and home configurations. Enable it only for the system root and disable it for the home. See the Arch Wiki page on 'Automatic timeline snapshots' for more information.

$ sudo snapper -c home set-config TIMELINE_CREATE=no
$ sudo systemctl enable --now snapper-timeline.timer
$ sudo systemctl enable --now snapper-cleanup.timer

That's all. Every hour from now on, a 'single' snapshot will be created and cleaned up every other day.

$ snapper ls
 # | Type   | Pre # | Date                                   | User | Cleanup  | Description        | Userdata
---+--------+-------+----------------------------------------+------+----------+--------------------+---------
0  | single |       |                                        | root |          | current            |         
1* | single |       | Wednesday 08 November 2023 01:13:40 PM | root |          | new root subvolume |
2  | single |       | Wednesday 08 November 2023 02:00:04 PM | root | timeline | timeline           |

To stop timeline snapshots, disable the snapper timers.

$ sudo systemctl disable --now snapper-timeline.timer
$ sudo systemctl disable --now snapper-cleanup.timer

The installation of Fedora 38 with Full Disk Encryption, Snapshot and Rollback Support is now complete.

16. Issues and Possible Solutions

Issue: This usually occurs when a kernel update has just been released and all of the kernel's supporting files have not yet been propagated to a repository mirror near you.

This is caused by the kernel parameter '{extra_cmdline}'. The '{extra_cmdline}' parameter is added to the kernel when you add the 'SUSE_BTRFS_SNAPSHOT_BOOTING=true' key to the /etc/default/grub file.

Solution: From the GRUB menu, select the kernel version you want to boot, and then press 'e' to modify the command.

Go to the line that starts with the word 'linux', and move the parameter '{extra_cmdline}' to the end of the line. The parameter '{extra_cmdline}' should always be at the end of the line.

From this:

Install Fedora 38/39 with Full Disk Encryption, Snapshot and Rollback Support - Issue-1-1

To this:

Install Fedora 38/39 with Full Disk Encryption, Snapshot and Rollback Support - Solution1-1

Then, on your keyboard, press Ctrl+x. You will be successfully booted into the operating system. Next, launch the terminal and execute the following command.

$ sudo grub2-mkconfig -o /boot/grub2/grub.cfg

Reboot the computer to ensure the problem has been resolved.

Issue: The problem appears to be that GRUB does not support TPM 2.0 very well when enabled in UEFI System Settings.

Solution: I looked into it, and it appears that this solution works perfectly. All credit goes to Eric Renfro.

Create a script named 02_tpm in the /etc/grub.d/ directory with the following contents.

# vim /etc/grub.d/02_tpm
#!/usr/bin/sh -e
echo "rmmod tpm"

Set the execute permission on a file.

# chmod +x /etc/grub.d/02_tpm

Update the grub.cfg file.

# grub2-mkconfig -o /boot/grub2/grub.cfg

This issue should now be resolved.

17. Upgrade Fedora 38 to Fedora 39

If you have already followed an earlier version of this tutorial and installed Fedora 38 and are interested in upgrading to Fedora 39, this section is for you.

Update the local DNF metadata cache.

$ sudo dnf makecache

Update your Fedora 38 release. This is important. Do not skip this step.

$ sudo dnf upgrade --refresh

After the updates have been installed, reboot your computer.

$ sudo reboot

After rebooting, open the terminal and run the following command to upgrade your Fedora 38 operating system to the most recent Fedora 39 version.

$ sudo dnf system-upgrade download --releasever=39

Once the upgrades have been downloaded, trigger the upgrade process. This will immediately reboot your computer, with no countdown or confirmation. So, before issuing the following command, close all other programs and save your work.

$ sudo dnf system-upgrade reboot

Once the upgrade process completes, your system will reboot again into the updated release version of Fedora 39.

If you want to learn more about the upgrade process, check out this link.

18. Watch on YouTube

The video was made for Fedora 38, but it is also applicable to Fedora 39. Nothing has changed between Fedora 38 and Fedora 39 in terms of btrfs snapshot and rollback support.

Thank you for engaging with this content.

If you like my work and want to thank me or encourage me to do more, you can buy me a coffee! The coffee will give me the "kick" I need to work even harder to bring you even more interesting Linux guides and articles.

Comments

83 responses to “How to Install Fedora 38/39 with Full Disk Encryption, Snapshot and Rollback Support”

  1. F38 Avatar
    F38

    Hi Madhu,

    I don't understand. It's a Fedora 38 installation where I have all of this in /var/ as subvolumes

    ll /var
    drwxr-xr-x. 1 root root 278 Nov 15 20:46 cache
    drwxr-xr-x. 1 root root 0 Nov 15 20:46 crash
    drwxr-xr-x. 1 root root 1158 Nov 15 20:39 lib
    drwxr-xr-x. 1 root root 954 Nov 16 00:00 log
    drwxr-xr-x. 1 root root 130 Nov 15 20:51 spool
    drwxrwxrwt. 1 root root 2170 Nov 16 10:23 tmp
    drwxr-xr-x. 1 root root 22 Nov 15 20:52 www

    btrfs subvolume list / |egrep "(318|257)"
    ID 257 gen 31084 top level 5 path root
    ID 258 gen 31045 top level 257 path var/lib/machines
    ID 259 gen 31084 top level 257 path .snapshots
    ID 260 gen 31083 top level 318 path home/.snapshots
    ID 308 gen 31077 top level 257 path var/cache
    ID 309 gen 30610 top level 257 path var/crash
    ID 310 gen 31084 top level 257 path var/log
    ID 311 gen 31075 top level 257 path var/spool
    ID 312 gen 31075 top level 257 path var/tmp
    ID 313 gen 31046 top level 257 path var/www
    ID 314 gen 31045 top level 257 path var/lib/AccountsService
    ID 315 gen 31045 top level 257 path var/lib/gdm
    ID 316 gen 31045 top level 257 path var/lib/libvirt/images
    ID 318 gen 31084 top level 5 path home
    ID 325 gen 31084 top level 318 path home/shizuma/.mozilla
    ID 331 gen 31044 top level 257 path opt

    Some subvolumes are mounted fine.

    mount|grep -v snapd | grep /dev/mapper/luks-0140d69f-4781-4439-9339-94a101794e2e
    /dev/mapper/luks-0140d69f-4781-4439-9339-94a101794e2e on / type btrfs (rw,relatime,seclabel,compress=zstd:1,ssd,discard=async,space_cache=v2,commit=300,subvolid=257,subvol=/root)
    /dev/mapper/luks-0140d69f-4781-4439-9339-94a101794e2e on /home type btrfs (rw,relatime,seclabel,compress=zstd:1,ssd,discard=async,space_cache=v2,commit=300,subvolid=318,subvol=/home)
    /dev/mapper/luks-0140d69f-4781-4439-9339-94a101794e2e on /home/shizuma/.mozilla type btrfs (rw,relatime,seclabel,compress=zstd:1,ssd,discard=async,space_cache=v2,commit=300,subvolid=325,subvol=/home/shizuma/.mozilla)

    All others just don't want to be mounted. One example below. Others are failing similarly.

    mount -v -t btrfs -o subvol=var/www,compress=zstd:1,commit=300,x-systemd.device-timeout=0 UUID=974a92ad-75ce-4957-9258-975411396cab /var/www
    mount: /var/www: mount(2) system call failed: No such file or directory.

    Part of my fstab for the subvolumes already mounted:

    UUID=974a92ad-75ce-4957-9258-975411396cab / btrfs subvol=root,compress=zstd:1,commit=300,x-systemd.device-timeout=0 0 0
    UUID=8424fe94-203a-4c47-88d6-969b7c50661f /boot ext4 defaults 1 2
    UUID=974a92ad-75ce-4957-9258-975411396cab /home btrfs subvol=home,compress=zstd:1,commit=300,x-systemd.device-timeout=0 0 0
    UUID=974a92ad-75ce-4957-9258-975411396cab /home/shizuma/.mozilla btrfs subvol=home/shizuma/.mozilla,compress=zstd:1,commit=300,x-systemd.device-timeout=0 0 0
    #UUID=974a92ad-75ce-4957-9258-975411396cab /opt btrfs subvol=opt,compress=zstd:1,commit=300,x-systemd.device-timeout=0 0 0
    #UUID=974a92ad-75ce-4957-9258-975411396cab /var/cache btrfs subvol=var/cache,compress=zstd:1,commit=300,x-systemd.device-timeout=0 0 0
    #UUID=974a92ad-75ce-4957-9258-975411396cab /var/crash btrfs subvol=var/crash,compress=zstd:1,commit=300,x-systemd.device-timeout=0 0 0
    #UUID=974a92ad-75ce-4957-9258-975411396cab /var/log btrfs subvol=var/log,compress=zstd:1,commit=300,x-systemd.device-timeout=0 0 0
    #UUID=974a92ad-75ce-4957-9258-975411396cab /var/spool btrfs subvol=var/spool,compress=zstd:1,commit=300,x-systemd.device-timeout=0 0 0
    #UUID=974a92ad-75ce-4957-9258-975411396cab /var/tmp btrfs subvol=var/tmp,compress=zstd:1,commit=300,x-systemd.device-timeout=0 0 0
    #UUID=974a92ad-75ce-4957-9258-975411396cab /var/www btrfs subvol=var/www,compress=zstd:1,commit=300,x-systemd.device-timeout=0 0 0
    #UUID=974a92ad-75ce-4957-9258-975411396cab /var/lib/AccountsService btrfs subvol=var/lib/AccountsService,compress=zstd:1,commit=300,x-systemd.device-timeout=0 0 0
    #UUID=974a92ad-75ce-4957-9258-975411396cab /var/lib/gdm btrfs subvol=var/lib/gdm,compress=zstd:1,commit=300,x-systemd.device-timeout=0 0 0
    #UUID=974a92ad-75ce-4957-9258-975411396cab /var/lib/libvirt/images btrfs subvol=var/lib/libvirt/images,compress=zstd:1,commit=300,x-systemd.device-timeout=0 0 0

    If I uncomment the unmountable partitions, the system can't boot. Root locked.

    Any idea?

    Excuse me if it's a newbie question, but I have a hard time grasping the internals of btrfs. Thanks for yout tutorial and your help. Very much appreciated.

    1. Madhu Desai Avatar

      You overlooked two critical points in the tutorial. First, you made a separate /boot partition with an ext4 file system.

      UUID=8424fe94-203a-4c47-88d6-969b7c50661f /boot ext4 defaults 1 2

      This guide assumes that you will not create a separate partition for /boot and will instead keep it in the main root file system.

      Second, all of your subvolumes are incorrect. You have two subvolumes with id=5 created.

      ID 257 gen 31084 top level 5 path root
      ID 318 gen 31084 top level 5 path home

      The remaining subvolumes are children of the first two. This is not how it should work. All subvolumes should have id=5. Subvolumes within your home directory and subvolume snapshots are the only exceptions.

      ID 258 gen 31045 top level 257 path var/lib/machines
      ID 259 gen 31084 top level 257 path .snapshots
      ID 260 gen 31083 top level 318 path home/.snapshots
      ID 308 gen 31077 top level 257 path var/cache
      ID 309 gen 30610 top level 257 path var/crash
      ...

      Subvolumes should be something like this, with id=5:

      ID 256 gen 126 top level 5 path home
      ID 257 gen 55 top level 5 path opt
      ID 258 gen 121 top level 5 path var/cache
      ID 259 gen 111 top level 5 path var/crash
      ID 260 gen 132 top level 5 path var/log
      ID 261 gen 119 top level 5 path var/spool
      ID 262 gen 120 top level 5 path var/tmp
      ID 263 gen 107 top level 5 path var/www
      ID 264 gen 111 top level 5 path var/lib/libvirt/images
      ID 265 gen 119 top level 5 path var/lib/portables
      ID 266 gen 119 top level 5 path var/lib/machines
      ID 267 gen 124 top level 5 path var/lib/AccountsService
      ID 268 gen 126 top level 5 path var/lib/gdm
      ID 269 gen 127 top level 256 path home/madhu/.mozilla

      1. F38 Avatar
        F38

        I see. I did not follow all the tutorial. I already had a F38 installation made my the F38 installer. This is the default install with luks encryption to part 3. The home and root were created like this. What I did is try to add more subvolumes because I like your idea to exclude some paths from snapshots. Thanks a lot fot the heads-up!

        Just wondering if it's fixable...

        I created this setup with this script:

        #!/bin/bash

        # Liste des répertoires à transformer en sous-volumes
        dirs=("/opt "/var/cache" "/var/crash" "/var/log" "/var/spool" "/var/tmp" "/var/www" "/var/lib/AccountsService" "/var/lib/gdm" "/var/lib/libvirt/images")

        # Boucle sur chaque répertoire
        for dir in "${dirs[@]}"; do
        # Si le répertoire existe
        if [ -d "$dir" ]; then
        # Déplacer les données existantes vers un autre emplacement temporaire
        mkdir "${dir}-old"
        mv -v "$dir" "${dir}-old"

        # Créer le nouveau sous-volume Btrfs
        sudo btrfs subvolume create "$dir"

        # Copier les données de retour dans le nouveau sous-volume
        cp -arv "${dir}-old/." "${dir}/"

        # Si SELinux est activé, restaurer les contextes de sécurité SELinux pour le nouveau sous-volume
        if [ -x /usr/sbin/restorecon ]; then
        restorecon -RFv "$dir"
        fi

        # Supprimer le répertoire temporaire contenant les données d'origine
        rm -rfv "${dir}-old"

        echo "UUID=974a92ad-75ce-4957-9258-975411396cab ${dir} btrfs subvol=${dir},compress=zstd:1,commit=300,x-systemd.device-timeout=0 0 0" >> /etc/fstab

        else
        echo "Le répertoire $dir n'existe pas."
        fi
        done
        chmod 1777 /var/tmp
        chmod 1770 /var/lib/gdm
        chmod 0711 /var/lib/libvirt/images
        chown -R gdm:gdm /var/lib/gdm
        chown -R shizuma:shizuma /home/shizuma/.mozilla

        systemctl daemon-reload

        mount -va

        1. Madhu Desai Avatar

          The script looks good to me. The command 'mkdir "${dir}-old"' seems unnecessary, though.

        2. Madhu Desai Avatar

          However, you cannot change the kernel path in the GRUB BLS using this script. This is how the kernel and initrd paths should look. I'm guessing you'll have to reinstall with the correct subvolumes defined.

          $ sudo grubby --info=DEFAULT
          index=0
          kernel="/boot/vmlinuz-6.5.9-300.fc39.x86_64"
          args="ro rd.luks.uuid=luks-adcf2b8d-4884-4627-9964-ad790471eb13 rhgb quiet rd.luks.options=tpm2-device=/dev/tpmrm0 ${extra_cmdline}"
          root="UUID=b481869f-2320-4d0a-8073-30d6c6f1cc81"
          initrd="/boot/initramfs-6.5.9-300.fc39.x86_64.img"
          title="Fedora Linux (6.5.9-300.fc39.x86_64) 39 (Thirty Nine)"
          id="7615546df2f845a38fa3f1a06a5f127d-6.5.9-300.fc39.x86_64"

  2. Oleksandr Avatar
    Oleksandr

    Hi, Madhu! Thanks for the exellent guide!
    I have questions about the desktop environment.
    If I use Gnome desktop, then I need to create subvolumes for the directories /var/lib/AccountsService and /var/lib/gdm.
    What if I want to install KDE desktop, what special subvolumes shoud I need to create in this case?
    Thank you very much for answer!

    1. Madhu Desai Avatar

      For KDE, it is /var/lib/AccountsService and /var/lib/sddm

      1. Oleksandr Avatar
        Oleksandr

        Thanks a lot!

  3. sherif Avatar
    sherif

    Hello @Madhu Desai

    I really appreciate your Work Great work acutely and i wish u do a same Tutorial like Fedora 38 with LUKS Full Disk Encryption, Snapshot and Rollback Support for Arch Linux ...

    Thank you so much ..

    1. Madhu Desai Avatar

      Thank you for your appreciation. Sure, I'll try on Arch.

  4. bot-mrty Avatar
    bot-mrty

    *x509
    # btrfs subvolume list /

    ID 256 gen 542 top level 5 path home

    ID 257 gen 48 top level 5 path opt

    ID 258 gen 539 top level 5 path var/cache

    ID 259 gen 48 top level 5 path var/crash

    ID 260 gen 541 top level 5 path var/log

    ID 261 gen 381 top level 5 path var/spool

    ID 262 gen 507 top level 5 path var/tmp

    ID 263 gen 122 top level 5 path var/www

    ID 264 gen 122 top level 5 path var/lib/libvirt/images

    ID 265 gen 122 top level 5 path var/lib/portables

    ID 266 gen 122 top level 5 path var/lib/machines

    ID 267 gen 187 top level 5 path var/lib/AccountsService

    ID 268 gen 473 top level 5 path var/lib/gdm

    ID 269 gen 542 top level 256 path home/mrty/.mozilla

    ID 270 gen 524 top level 5 path .snapshots

    ID 271 gen 204 top level 256 path home/.snapshots

    ## that is the subvolume list. last post was hard to read, so hopefully this one will be more visable.

    ## Is it okay to use the same Secure Boot keys from one install to the next?
    ## That's about the only idea I have as to why its not updating.

    1. Madhu Desai Avatar

      I'm not sure why you can't update. Try the commands 'sudo dnf clean all' and 'sudo dnf makecache' to see if they resolve the problem.

      Yes, you can use Secure Boot keys on the next install as long as they are registered in the UEFI firmware.

      1. bot-mrty Avatar
        bot-mrty

        Thanks for the quick reply. I ended up doing it again and this time it worked out. I did try those commands you mentioned with the same issue. I can only assume it was something I missed the first time or signing the boot binaries on the second. Cheers bro.

        1. Madhu Desai Avatar

          I'm glad everything worked out in the end.

          1. bot-mrty Avatar
            bot-mrty

            Yes everything did work out thankfully. Thanks for posting these guides, I for one really appreciate it.

  5. Ciril Avatar
    Ciril

    Hello,

    I cant boot from snapshots after i select snapshot from which i wanna bot i get:
    error: ../../grub-core/commands/efi/tpm.c:150:unknown TPM error.

    I try also other snapshots and result is the same.

    Best regards,

    1. Madhu Desai Avatar

      Disable TPM in the UEFI Firmware settings, boot to a snapshot, and then rollback.

      1. Ciril Avatar
        Ciril

        Hello

        It works.

        Thanks

        1. Madhu Desai Avatar

          I'm glad it worked. I was also looking for other solutions because it seems to happen quite frequently. One solution I discovered during my research is as follows. This method worked for me. You can also try.

          Create the file /etc/grub.d/02_tpm and add the following content to it:
          #!/usr/bin/sh -e
          echo "rmmod tpm"

          Make it executable:
          chmod +x /etc/grub.d/02_tpm

          Update the GRUB:
          grub2-mkconfig -o /boot/grub2/grub.cfg

          And then reboot. You should no longer receive the TPM error, at least according to the solution I found here.

  6. Anton K Avatar
    Anton K

    Hi. Thank you for your guide.

    To be able load in to snapshot from Grub I had to turn off Secure Boot and TPM previously.

    I believe I did everything according to 8.2 instruction, but still have to enter password twice. Any suggestions?

    Is there a chance you will do similar instruction for NixOS?

    1. Madhu Desai Avatar

      According to my understanding, the rEFInd boot loader does not honor secure boot by default. TPM requires Secure Boot to be enabled in order to function. I believe you have two choices: sign your rEFInd boot loader with your own signature or use a key file instead to enter the password only once.

      If you prefer to create your own custom keys for Secure Boot, see my other guide 'Enable Fedora UEFI Secure Boot with Custom Keys and Self-Signed Bootloader, Kernel, and Modules'. You can also use MOK (Machine Owner Key) to sign the rEFInd boot loader. I haven't written a guide for this one. But if you Google it, you'll find plenty of articles.

      As for the NixOS, it is based on the concept called 'generations'. In NixOS, you don't need snapper or grub-btrfs for snapshots and rollbacks. However, it is a fascinating operating system that is gaining popularity. As a result, I intend to write articles about NixOS as well.

      1. Anton K Avatar
        Anton K

        I've generated own signature, added it with MOK manager to TPM some time ago. Also I have signed shimx64.efi, grubx64.efi and few other *.efi files in EFI/(fedora|ubuntu|refind) folders. But it seems it requires me to sign every vmlinuz files as well. Probably I am doing something wrong cause as far as I remember it should be enough to sign only one file that eventually will load grub or directly kernel file. I definitely need to read again about this topic.

        But the issue wasn't with loading rEFInd or grubx64.efi. Actually there was 2 issues. First is that when I choose a snapshot there was empty list of available kernel files. If I hit enter it shows some "unknown TPM error". It was fixed by switching in UEFI settings TPM from Active to Hidden.

        After that kernels showed up, but after trying to load them appears message that loader isn't valid and system will be halted. It felt like kernel files from snapshot loose signature. So I have to turn off Secure Boot in UEFI settings, login to Fedora snapshot, rollback, reboot, login and sign kernel files again. And after that switching back TPM and Secure Boot doesn't stop loading.

        Generations are a snapshots of only that one main config file, right? But most probably you still would want to make from time to time `/home` snapshots. So snapper and grub-btrfs can be useful in NixOS.

  7. Anton K Avatar
    Anton K

    Hi. Thank you for your guide. I've successfully completed 9th point of plan. Not from the first attempt due to different small mistakes and overall unexperience.

    I don't encrypt /boot partition, so I decided to use argon2id for encryption of root partition. Later I realized that I want to use snapshots in Grub and thus I need to use compatible pbkdf. This also resolves issue with getting to grub shell? after reboot with out understanding what to do next to Fedora up and running. Probably encryption options in grub config where useless and harmful in conjunction with argon2id encryption.

    Currently I am struggling to reduce need of entering LUKS password by use of TPM (point 8). I've checked a few times all settings, configs. Everything is set exactly as it is shown in your article. But it doesn't work for some reason.

    I have two ssd. One holds ESP, Windows and Ubuntu, other holds Fedora. I have multiboot rEFInd boot loader. Fedora `/boot` is unencrypted ext4 partition. In rEFInd I've set Fedora to be loaded by `/boot/efi/EFI/fedora/shimx64.efi` file. So there is no visible difference in loading Fedora from rEFInd boot menu or from System Boot Menu.

    ```
    cat /etc/fstab
    UUID=e92dbc28-3d55-4a81-9fe7-5fcf18bc6898 / btrfs defaults,compress=zstd:1,x-systemd.device-timeout=0 0 0
    UUID=c71d0d68-5d10-4c79-bbd2-b3e234dc0068 /boot ext4 defaults 1 2
    UUID=C67A-5155 /boot/efi vfat umask=0077,shortname=winnt 0 0
    UUID=e92dbc28-3d55-4a81-9fe7-5fcf18bc6898 /home btrfs subvol=home,compress=zstd:1,x-systemd.device-timeout=0 0 0
    UUID=e92dbc28-3d55-4a81-9fe7-5fcf18bc6898 /opt btrfs subvol=opt,compress=zstd:1,x-systemd.device-timeout=0 0 0
    UUID=e92dbc28-3d55-4a81-9fe7-5fcf18bc6898 /var/cache btrfs subvol=var/cache,compress=zstd:1,x-systemd.device-timeout=0 0 0
    UUID=e92dbc28-3d55-4a81-9fe7-5fcf18bc6898 /var/crash btrfs subvol=var/crash,compress=zstd:1,x-systemd.device-timeout=0 0 0
    UUID=e92dbc28-3d55-4a81-9fe7-5fcf18bc6898 /var/log btrfs subvol=var/log,compress=zstd:1,x-systemd.device-timeout=0 0 0
    UUID=e92dbc28-3d55-4a81-9fe7-5fcf18bc6898 /var/spool btrfs subvol=var/spool,compress=zstd:1,x-systemd.device-timeout=0 0 0
    UUID=e92dbc28-3d55-4a81-9fe7-5fcf18bc6898 /var/tmp btrfs subvol=var/tmp,compress=zstd:1,x-systemd.device-timeout=0 0 0
    UUID=e92dbc28-3d55-4a81-9fe7-5fcf18bc6898 /var/www btrfs subvol=var/www,compress=zstd:1,x-systemd.device-timeout=0 0 0
    UUID=e92dbc28-3d55-4a81-9fe7-5fcf18bc6898 /var/lib/libvirt/images btrfs subvol=var/lib/libvirt/images,compress=zstd:1,x-systemd.device-timeout=0 0 0
    UUID=e92dbc28-3d55-4a81-9fe7-5fcf18bc6898 /var/lib/AccountsService btrfs subvol=var/lib/AccountsService,compress=zstd:1,x-systemd.device-timeout=0 0 0
    UUID=e92dbc28-3d55-4a81-9fe7-5fcf18bc6898 /var/lib/gdm btrfs subvol=var/lib/gdm,compress=zstd:1,x-systemd.device-timeout=0 0 0
    UUID=e92dbc28-3d55-4a81-9fe7-5fcf18bc6898 /home/anton/.mozilla btrfs subvol=home/anton/.mozilla,compress=zstd:1,x-systemd.device-timeout=0 0 0
    ```

    ```
    cat /etc/default/grub
    GRUB_TIMEOUT=5
    GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
    GRUB_DEFAULT=saved
    GRUB_DISABLE_SUBMENU=true
    GRUB_TERMINAL_OUTPUT="console"
    GRUB_CMDLINE_LINUX="rd.luks.uuid=luks-d569a5ef-8996-4c42-ab0a-aab25e712dfd rhgb quiet rd.luks.options=tpm2-device=/dev/tpmrm0"
    GRUB_DISABLE_RECOVERY="true"
    GRUB_ENABLE_BLSCFG=true
    GRUB_ENABLE_CRYPTODISK=y
    SUSE_BTRFS_SNAPSHOT_BOOTING="true"
    ```

    ```
    cat /boot/efi/EFI/fedora/grub.cfg
    set btrfs_relative_path="yes"
    cryptomount -u d569a5ef89964c42ab0aaab25e712dfd
    search --no-floppy --fs-uuid --set=dev c71d0d68-5d10-4c79-bbd2-b3e234dc0068
    set prefix=($dev)/grub2
    export $prefix
    configfile $prefix/grub.cfg
    ```

    ```
    grubby --info=DEFAULT
    index=0
    kernel="/boot/vmlinuz-6.4.14-200.fc38.x86_64"
    args="ro rd.luks.uuid=luks-d569a5ef-8996-4c42-ab0a-aab25e712dfd rhgb quiet rd.luks.options=tpm2-device=/dev/tpmrm0 ${extra_cmdline}"
    root="UUID=e92dbc28-3d55-4a81-9fe7-5fcf18bc6898"
    initrd="/boot/initramfs-6.4.14-200.fc38.x86_64.img"
    title="Fedora Linux (6.4.14-200.fc38.x86_64) 38 (Thirty Eight)"
    id="e3e7fa9d3c354fa5b5fe540ab01d2f8b-6.4.14-200.fc38.x86_64"
    ```

    ```
    cat /etc/crypttab
    luks-d569a5ef-8996-4c42-ab0a-aab25e712dfd UUID=d569a5ef-8996-4c42-ab0a-aab25e712dfd - tpm2-device=auto,discard
    ```

    I've tried to disable TPM which had almost no effect, except some warning about TPM when I loges in to my Fedora account.

    I will appreciate any suggestions, ideas how to figure out and resolve it. Thank you.

    1. Madhu Desai Avatar

      For Snapper and Grub-Btrfs to work properly and be able to boot to system root (/) snapshots, you don't need the pbkdf algorithm. Argon2id is just fine. You only need the pbkdf algorithm if you also want to encrypt /boot. The only difference is that when a system root is rolled back, the contents of the /boot partition are not rolled back because the /boot partition is not part of the system root.

      As you did not encrypt the /boot partition, the LUKS passphrase will be asked only once, so decrypting using TPM is not necessary.

      I tested and wrote this guide while keeping in mind that /boot is a part of the system root and the system root is LUKS encrypted. Any other layout needs to be evaluated differently as the Grub-Btrfs package does not natively support Fedora.

      1. Anton K Avatar
        Anton K

        It seems I was loading cached version of the page and haven't seen my comment and your answer. Thought there was some error during post request and I posted short kind of duplicate comment. Sorry

        Eventually I came up to idea that I have no reason to leave /boot unencrypted and moved it to LUKS. Generally it makes sense for rEFInd boot loader which scans for vmlinuz files adding them as boot suboptions for each Linux. But it can't load shanpshots, so for Fedora I anyway load Grub, by manual setup.

  8. Max J. Avatar
    Max J.

    Dear Madhu, great job.
    in Chap. 9, there is a screen, titled "Check your subvolumes" where var/lib/portables and /machines appear. what about these subvolumes? thank you!

    1. Madhu Desai Avatar

      In Fedora Workstation, systemd creates the /var/lib/machines subvolume implicitly for systemd-nspawn containers. The /var/lib/portables subvolume is for portable services, which is also related to it.

      Check out the following links for more information:
      https://docs.fedoraproject.org/en-US/fedora-server/containerization/systemd-nspawn-setup/
      https://systemd.io/PORTABLE_SERVICES/
      https://0pointer.net/blog/walkthrough-for-portable-services.html

  9. Ciril Avatar
    Ciril

    Hello,
    Thanks for very good guide. I have question about section "In the user's home directory, create a subvolume called .mozilla."

    Is possible to create subvolume for domain user? when i join PC to domain and login with domain user i get aswell folder /home/domainuser_folder
    Thanks for answer

    1. Madhu Desai Avatar

      I haven't tried it with a domain login. But I believe you can if you've set up a snapper config 'home' for the Btrfs volume at /home.

      Check to see if the user id (UID) for the regular login user and the domain login user is the same or different. If it's the same, that's fine. If they differ, I believe you should set the user's permissions on the '/home/domainuser_folder' directory.

      Try this and see if it works. I haven't tested it, but it should work.

      Set the permissions for both users. For this, I'll use the usernames bob and alice.
      # snapper -c root set-config ALLOW_USERS="bob alice" SYNC_ACL=yes
      # snapper -c home set-config ALLOW_USERS="bob alice" SYNC_ACL=yes

      Also, add the subvolume to the /etc/fstab file.

      1. Ciril Avatar
        Ciril

        i added volume to /etc/fstab, but when i try to mount i get error:
        mount: /home/domain_user/.mozilla: wrong fs type, bad option, bad superblock on /dev/mapper/luks-fbf41e21-1a6c-46ac-8415-8b406b1305ca, missing codepage or helper program, or other error.
        dmesg(1) may have more information after failed mount system call.

        1. Madhu Desai Avatar

          Is the directory '/home/domain_user/.mozilla' part of the same btrfs volume? If this is the case, have you created a subvolume for that directory?

          If the directory is not part of the same btrfs volume and is mounted after you log in as a domain user, simply ignore it. It will not be part of the snapshot regime, and if you rollback snapshots, it will not be affected.

  10. User Avatar
    User

    Thank you so much! This guide is almost perfect for me. IMHO full disk encryption and snapshots have to be enabled by default in Fedora Linux. Please consider installing only minimal Gnome environment:

    sudo dnf install --setopt=install_weak_deps=FALSE @critical-path-gnome
    
  11. Serge Avatar
    Serge

    Hi Madhu!
    When first loading the minimum
    Fedora after entering the first passphrase, an error appears:
    Slot "0" opened
    ...
    error: ../../grub-core/commands/loadenv.c:216: sparse file not allowed
    ...
    Then a second passphrase is requested and the system boots further.

    Question: Is this error still related to the fact that /boot is in the root of the btrfs file system, or should this error not exist?
    I did two installations: I typed commands in full and in Copy-Paste mode from the web manual

    1. Madhu Desai Avatar

      The error occurs because the /boot directory is in the btrfs filesystem. Unlike ext4, the GRUB btrfs.mod driver is read-only. To fix this, run the following command.
      sudo grub2-editenv - unset menu_auto_hide

  12. Julien Avatar
    Julien

    Hello,

    I would very much like to have a keymap in French ("fr" keymap) before loading grub and in grub but I have absolutely no idea how to proceed and I would like to know if you could help me in this direction, not having as much experience as you do in the Linux world 🙂

    Thank you in advance for your reply.

    1. Madhu Desai Avatar

      I updated section 4 of the tutorial on keymaps. Did you give it a shot? Is this having no effect on the French language?

      I tried Fedora, as well as openSuse and Manjaro in French. However, none appears to display the GRUB menu in French. Are you aware of any distribution that displays the GRUB menu in French?

  13. Timo Avatar
    Timo

    I'm having some issues. I just updated Fedora and after the update the screen was flickering, so I did undochange to the last snapshot, but it's not booting anymore. So tried to boot into a snapshot, but I only get "unknown TPM error" (for all snapshots, can't boot anything).
    Yesterday all the tests on this page worked, so I guess the update messed up Grub?

    1. Madhu Desai Avatar

      Go to UEFI firmware and disable TPM first. Then boot to the snapshot you believe is the best, and if it is the one you want, rollback to that snapshot. If everything is fine, update the grub and re-enable TPM.

      1. Timo Avatar
        Timo

        Thanks a lot for the quick help, it worked. Good to know that TPM is optional.
        Although the flickering is back, it seems like it has nothing to do with the update but it appears randomly if the screen is empty. Seems like I only noticed it because I didn't instantly open anything after rebooting.
        Edit: After nightmode finished transitioning it's gone. Maybe a bug with nightmode and an empty screen. Or it's random.

  14. Timo Avatar
    Timo

    Thanks for the amazing Tutorial

    1. Madhu Desai Avatar

      You’re most welcome. I’m so glad it was helpful!

  15. Julien Avatar
    Julien

    Hello,

    Following your guide, I found myself after the reboot at the end of part 9 with a standard qwerty keyboard on the login screen and to avoid this problem recurring I had to open a terminal and type the command line $ sudo localectl set-keymap fr (following my location). When I typed $ localectl status just before this command line, I noticed that the X11 Layout had not been defined and I thought that this was certainly the problem, which turned out to be the case. Consequently, in your guide, for your own location, you should add the command line # localectl set-keymap en-in at the beginning of part 9 (where you forgot to start it with the command line $ sudo -i). I also wanted to point out that you should indicate at the end of part 7 of your guide that the keyboard is a standard qwerty keyboard in the first LUKS prompt.

    1. Madhu Desai Avatar

      Thank you for bringing the issue to my attention. I've updated section 4, and the keyboard setting should be fixed now.

  16. Julien Avatar
    Julien

    Hello,

    I'd like to point out that you need to change a few things in part 8.2 of your guide: move the command line # LUKS_DEV_UUID="$(cryptsetup luksUUID /dev/vda2)" after # systemd-cryptenroll --tpm2-device=list and replace # systemd-cryptenroll /dev/vda2 --tpm2-device=/dev/tpmrm0 with # systemd-cryptenroll /dev/disk/by-uuid/${LUKS_DEV_UUID} --tpm2-device=/dev/tpmrm0. Indeed, if the disk is an NVMe, as is my case, this syntax is mandatory (https://www.reddit.com/r/archlinux/comments/12s5so5/cryptsetup_device_devnvme1n1p3_is_not_a_valid) for the systemd-cryptenroll command to work. You should also add the command line # sudo -i at the beginning of part 8 of your guide, which you forgot. I'd also advise you to replace the # ls /usr/share/zoneinfo command line in part 4 of your guide with # timedatectl list-timezones in the same way as the list-locales and list-keymaps options in the localectl command you use immediately afterwards.

    1. Madhu Desai Avatar

      Thank you for your suggestions. I've made the necessary changes.

  17. Julien Avatar
    Julien

    Hello!

    Fantastic this guide for Fedora 38, they get better and better with each new version of the distribution!

    I plan to install Fedora 38 in Dual Boot with Windows 11 on my computer composed of a single 1TB NVMe. Do you think everything will work properly if after installing Fedora 38 following your guide and reducing the space occupied by the Linux system to 256 GB I install Windows 11 on the space thus freed up? Concerning the timeline cleanup algorithm, does it concern single snapshots and pre/post snapshot pairs? I'd also like to know how to save all the snapshots on an external backup location. Do you have any idea of how to do this, as I'm a bit lost?

    1. Madhu Desai Avatar

      Of course, you can install both Windows 11 and Fedora 38 on a single 1 TB disk and dual boot them without issue.

      If you haven't already done so, I recommend installing Windows 11 first, followed by Fedora 38. Tasks will be simpler this way.

      In regard to snapshot cleanup, snapshots will be cleaned up as long as they are marked for cleanup. To mark a snapshot for cleanup, select one of the these cleanup algorithms: number, timeline, or empty-pre-post.

      For example, for pre-post snapshots, you can use the following:
      $ snapper -c root create -t pre -c timeline -d 'some description'
      $ snapper -c root create -t post --pre-number 1 -c timeline -d 'some description'

      For more information, go to 'man snapper' and look for the 'Cleanup Algorithms' section. Also, take a look at this link: openSUSE:Snapper Tutorial

      When you say "save all the snapshots on an external backup location," I believe you mean the location where snapshots are saved. No, snapshots cannot be saved to another location. If you want to take a snapshot of a specific subvolume, the snapshots directory must be located only within that subvolume. It has been hard coded. I remember reading it somewhere, but I can't remember where.

      If you're talking about regular backing up snapshots, check out this link. Incremental backup to external drive

      1. Julien Avatar
        Julien

        Hello,

        Thanks for the information! I was actually talking about being able to make a regular backup of the snapshots present in /.snapshots and /home/.snapshots made with Snapper, whatever their type, and reading the content of the second link you sent me, I intend to use the Snapsync utility (https://github.com/doudou/snapsync) to do this but I can't figure out how it works and how to use it. Can you help me with this, as it's the only thing I need to sort out to have a clear conscience about a possible crash of my computer's NVMe?

        1. Madhu Desai Avatar

          I did some research and this is what I found. In Fedora Copr, there is already a tool called snap-sync that is similar to snapsync.

          (1) Install it:
          sudo dnf copr enable peoinas/snap-sync && sudo dnf install snap-sync

          (2) Mount or connect your external backup. It must be formatted using the btrfs file system.

          (3) Run the command:
          sudo snap-sync

          Choose your external drive from the list of options.

          (4) Provide the name of the subvolume where backups for 'root' will be stored, for example, 'mysnaps'. Repeat the process for 'home' as well. Use the same name 'mysnaps' for this as well. Your snapshots will be backed up to an external drive.

          For more information, look up 'man snap-sync'. For other options or run this program automatically, go to the bottom of the manual page for more information. You can also refer this page:
          https://www.jwillikers.com/backup-snapper-snapshots-with-snap-sync

  18. snoopy Avatar
    snoopy

    if doing a fresh install what would be best way to set this up as a dualboot with win11 (bitlocker) and F38luks/snapper. install linux or windows first? can't test on vm, so wanted to know if there are any issues with grub / luks / partitions etc i should look out for. also, my laptop has x2 SSDs - can I have each OS on diff drives or do they both need to be on same ssd as grub?

    1. Madhu Desai Avatar

      You must first install Windows 11. Windows setup creates an EFI partition. After that, install Fedora. You do not need to create or format the EFI partition. Simply mount the EFI partition at /mnt/boot/efi.

      You can install each operating system on separate disks, but the EFI partition should only be one. Because you'll be installing Windows 11 first, use that EFI partition for Fedora as well, and use the other disk's entire disk as the btrfs system root.

  19. Philipp Avatar
    Philipp

    Hey,
    Thanks for the tutorial. I tried my best and followed it twice (for testing in QEMU/KVM virtual machine with EFI).
    Unfortunately, in "Step 7. Enable Crypto Disk and Snapshot Booting" I am unable to execute the sed commands because the /boot/efi/EFI/fedora/grub.cfg file does not exist (the directory with some other files is there tough).
    Leaving out this step and continuing leave me with a system which does not boot. Any help on what the problem could be would be highly appreciated. Thank you!
    Best,
    Philipp

    1. Madhu Desai Avatar

      The grub.cfg configuration file should be present. I'm not sure why it isn't in your setup. Anyway, create this file manually and then use sed.

      search --no-floppy --fs-uuid --set=dev [add your luks mapped btrfs volume uuid here]
      set prefix=($dev)/boot/grub2
      export $prefix
      configfile $prefix/grub.cfg

  20. Ciril Avatar
    Ciril

    Hello,
    This works perfect. But i have some questions... At step 8 (8. Bypass the Additional Passphrase Prompt)
    I chose TPM2 method to avoid additional password.

    1st Question: after i update my Fedora (bios update) i must repeat procedure becouse again got 2x to enter password.

    2nd Question: Is there a way, to make backdoor (which unlock the device, additional password or something like that) that allows access to device if user forget his password or hes not employed anymore.
    In short way, is possible to set 2 different passwords to unlock device.

    Best regards,
    Ciril

    1. Madhu Desai Avatar

      1) Remove old TPM2 key...
      systemd-cryptenroll /dev/vda2 --wipe-slot=tpm2

      ...and enroll again. Use the same passphrase.
      systemd-cryptenroll /dev/vda2 --tpm2-device=/dev/tpmrm0

      (Replace device /dev/vda2 and tpm node path /dev/tpmrm0 with your own.)

      Verify that the "tpm2" has been added to the encrypted volume:
      systemd-cryptenroll /dev/vda2
      or
      cryptsetup luksDump /dev/vda2

      Reboot, and it should only ask for the passphrase once.

      2) Of course, you can set additional passphrases. If I'm not mistaken, LUKS2 allows for up to 32 (0 to 31) key slots.

      You can use the following command to set a different passphrase on the device's available key slot.
      cryptsetup luksAddKey --type luks2 --pbkdf pbkdf2 --pbkdf-force-iterations 500000 /dev/vda2

      You will be asked for the passphrase you have previously set. Once verified, you can add another passphrase on another key slot. The encrypted device can then be unlocked using both passphrases.

      You can verify the key slots by using the command
      systemd-cryptenroll /dev/vda2
      or
      cryptsetup luksDump /dev/vda2

  21. osss Avatar
    osss

    Hi Madhu,
    I'm encountering a few problems with this setup and I'm not 100% sure what the root cause is (probably user error).
    1) when trying to boot into a previous snapshot via GRUB menu, an error is popping up 5x in a row, after which it jumps back into the menu:

    error: ../..grub-core/commands/efi/tpm.c:150:unknown TPM error.
    

    I've used the "8.1 Using a Key File" method for bypassing the additional passphrase prompt.
    2) when booting normally into fedora 38, for a split second an error appears after which the system boots normally into the GNOME DE:

    [FAILED] Failed to start systemd-vc[]rvice - Setup Virtual Console.
    

    where the [] whithin vc[]rvice is a solid cube-shaped character.
    Any idea how to solve this, especially 1) ?

    All the best
    Olaf

    1. Madhu Desai Avatar

      1) If you have TPM enabled in your UEFI settings, try disabling it to see if the error persists.

      2) What is your keyboard language? What does the /etc/vconsole.conf output show?
      Set the correct language for the "KEYMAP=" option in the /etc/vconsole.conf file. It is "KEYMAP=us" if you use a US keyboard. Check out this page for more information: Linux console/Keyboard configuration.

      I'm using India English, and this is what the /etc/vconsole.conf file looks like:
      cat /etc/vconsole.conf
      KEYMAP="in-eng"
      FONT="eurlatgr"

      If you use US English, probably it will be like
      cat /etc/vconsole.conf
      KEYMAP="us"
      FONT="eurlatgr"

      1. osss Avatar
        osss

        Hi Madhu,
        thanks for your advise! Disabling the TPM did the trick, booting into snapshots now works flawlessly.

        Regarding 2) the output of /etc/vconsole.conf is

        KEYMAP=de-de
        

        (I'm located in Germany) I guess the correct form would be just

         KEYMAP="de"
        

        correct? Thing is, I can't edit the conf file, as it is read only. Even sudo does nothing. How can I edit this file?

        Thanks in advance!

      2. osss Avatar
        osss

        nevermind my previous comment.. I was booted into a snapshot but haven't properly rolled back to it so the / fs was still read-only.
        I now edited the /etc/vconsole.conf file to
        KEYMAP="de"
        FONT="eurlatgr"

        but the [FAILED] Failed to start systemd-vc[]rvice - Setup Virtual Console.
        message still persists on boot.

        1. Madhu Desai Avatar

          After updating the /etc/vconsole.conf file, run the following command to see if it resolves the issue.
          sudo dracut -vf

          1. osss Avatar
            osss

            that did the trick, thank you very much!

        2. Madhu Desai Avatar

          According to 'man 5 vconsole.conf', the correct keyword for German keyboard is
          KEYMAP=de-latin1
          FONT=eurlatgr

  22. Nico Avatar
    Nico

    Dear Madhu,
    Thank you very much for your tutorial. It works out great!
    Just for my curiosity: would it be possible for you to make a similar guide with btrfs, full disk encryption and timeshift (including grub-btrfs) for backups?
    I have tried to follow your howto with some adaptions for timeshift, but I am always ending up in booting to emergency mode after enabling grub-btrfs due to a root-switch failure.
    Thanks and best regards!

    1. Madhu Desai Avatar

      I've never tried timeshift before. However, I'll give it a shot and see if I can successfully create and roll back a snapshot using timeshift. If it's a success, I'll definitely write an article about it.

      1. Nico Avatar
        Nico

        Hi Madhu,
        Did you make any approaches on timeshift?
        I have reproduced my failure with a non-bootable system several times now and it must go wrong somewhere after recreating the grub-config following the timeshift installation and enabling snapshot-booting as well as disabling the menu-auto-hide function.
        The snapshots from timeshift are shown in grub and it is possible to boot into the snapshot - only the main system ist not bootable anymore running in this initrd failure (root-switch).
        All the workarounds, which I have found, are useless so I am a little bit lost with this!

        1. Madhu Desai Avatar

          No, not yet. I'm currently working on editing a YouTube video for this guide. I'll test as soon as I finish this.

  23. Gerd Avatar
    Gerd

    Dear Madhu.
    I face big issues for chapter 8.1, I could not luksAdd the *key.d file. Still after reboot twice times password needed.

    The most problematic item I have is chapter 9. Not able to resolve the names server. Resolver.conf is empty, nmcli does show only lo and loopback as active. No WiFi nor eth0 appeared.
    Do you have solution.
    All other steps worked fine, all volumes and subvolumes available

    1. Madhu Desai Avatar

      Did you follow section 8.1 exactly as written or did you make any changes?

      Is the encrypted partition's UUID identical to that in the key file? For instance, the UUID in this sample should match.

      Assuming the LUKS partition is /dev/vda2,
      # lsblk -dno uuid /dev/vda2
      6e6c2ee3-852a-4efb-9801-8277dccf0af1

      # ls /etc/cryptsetup-keys.d/
      luks-6e6c2ee3-852a-4efb-9801-8277dccf0af1.key

      Also, in the /etc/dracut.conf.d/cryptodisk.conf file, make sure there is space on either side of double quotes.
      # cat /etc/dracut.conf.d/cryptodisk.conf
      install_items+=" /etc/cryptsetup-keys.d/* "

      Rebuild the initramfs image again.
      # dracut --verbose --force

      Reboot and check again.

      Regarding the network configuration, did you forget to delete /mnt/etc/resolv.conf and copy /etc/resolv.conf to /mnt/etc/ before chrooting?

      What does file /run/systemd/resolve/stub-resolv.conf output show? Link the file to /etc/resolv.conf file, reboot and check again.
      # ln -s /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf

  24. illucere Avatar
    illucere

    Thanks, awesome guide, i like its complexity and versatility. Forward thinking before installation. What will happen after the release of the next Fedora version / how to upgrade it? Will it be a smooth upgrade? Some extra subvolumes?

    1. Madhu Desai Avatar

      Thanks.

      You should have no trouble upgrading to the next version. You do not need to make any changes.

      Unless these two things happen:

      (1) The dnf is upgraded to version 5 (dnf5) in Fedora 39 (likely) or 40. Then I'll see how dnf5 interacts with snapper. I may need to make changes at that point. However, the subvolumes layout will remain the same.

      (2) The dnf database is relocated from /var/lib/dnf to somewhere in /usr. This can happen in Fedora 39 or 40 (most likely). Then you won't have to keep multiple subvolumes within /var, such as /var/cache, /var/tmp, and so on. I'll then merge all subvolumes into a single /var subvolume. However, you do not have to reinstall Fedora. Subvolumes can be easily converted into directories.

  25. briggs Avatar
    briggs

    At Section 2, when i use the command "sgdisk -n 1::+512M -t 1:ef00 -c 1:'EFI' /dev/vda". It shows the message "Could not create partition 1 from 3906250008 to 3907298583".
    What should i do?

    1. Madhu Desai Avatar

      Hello, Briggs. What is the name of your device? This command returns the device name.
      lsblk -pd

  26. Frank Avatar
    Frank

    Great guide!
    However, I managed to destroy Grub, the drive does not boot anymore.
    I installed Fedy and played around. There was an option for Grub customization - I guess this a bad idea ....
    Do you have any suggestion how to re-install grub ?

    1. Madhu Desai Avatar

      You can try this:

      In the grub prompt, enter this:
      grub> ls

      Then look for the grub.cfg file. For me it is at:
      grub> ls (hd0,gpt2)/boot/grub2/

      Then launch the grub.cfg:
      grub> configfile (hd0,gpt2)/boot/grub2/grub.cfg

      You should be booted into Fedora. Then follow this guide to reinstall grub:
      Bootloading with GRUB2

      Or search google on how to reinstall grub2 on Fedora.

      1. Frank Avatar
        Frank

        Wow, you are quick ! Thanks so much !!
        I'm not prompted for the password (as it usually happened earlier), I directly see Grub menu with just a single entry: UEFI Firmware Settings
        I guess therefore I'm facing the following error:

        grub> ls (hd0,gpt2)
        (hd0,gpt2): Filesystem is unknown.
        
        1. Madhu Desai Avatar

          I'm online right now, working on my website 😁. I forgot it was for the LUKS version. For LUKS it is something (crypto0) I think...

          Try
          grub> ls (crypto0)/

          and then
          grub> configfile (crypt0)/boot/grub2/grub.cfg

          1. Frank Avatar
            Frank

            You saved my day!

            cryptomount (hd1,gpt2)
            configfile(crypto0)/boot/grub2/grub.cfg
            

            brought back my Grub menu entries and I was able to boot my Fedora.
            I guess the Fedy 'Grub2 configuration' option re-generated /boot/efi/EFI/fedora/grub.cfg and removed the 'cryptomount -u ....' option I inserted when following your guide. I had to insert them again.
            However, the file header also says:

            # DO NOT EDIT THIS FILE
            #
            # It is automatically generated by grub2-mkconfig using templates
            # from /etc/grub.d and settings from /etc/default/grub
            

            So could this happen with other usual Grub2 operations, or did that Fedy script something unusual ?

          2. Madhu Desai Avatar

            I believe it is a Fedy script. This error has never occurred to me.

        2. Madhu Desai Avatar

          OK, the steps are as follows:

          grub> cryptomount (hd0,gpt2)

          Enter your LUKS password. Then

          grub> configfile (crypto0)/boot/grub2/grub.cfg

  27. Mars Avatar
    Mars

    Thanks for the amazing guide! Saved me reinstalling the OS a couple of times while experimenting with things 🙂
    One question, in the other guide (How to Install Fedora 38 with Snapshot and Rollback Support) you mention the error:
    "error: ../../grub-core/commands/loadenv.c:216:sparse file not allowed."This can be solved by running:sudo grub2-editenv - unset menu_auto_hide
    You mention this is being caused because a separate ext4 /boot partition doesn't exists. With this guide a separate ext4 /boot partition is also absent. Shouldn't the above error and solution also be in this guide?

    1. Madhu Desai Avatar

      When you install Fedora using the default Anaconda Installer, the menu auto hide feature is enabled by default. You can learn more about it by clicking here. However, in the LUKS version, I do not use the Anaconda Installer and instead install Fedora manually. As a result, the menu auto-hide feature is disabled. There is no need to explicitly mention it because it is already disabled by default.

  28. Jonas Avatar
    Jonas

    Thanks for the updated guide! Worked like a charm.
    I installed the DE before bypassing the additional passphrase prompt, so I could continue copy and edit your code and didn't have to type so much myself.
    Cool, that you implemented the donate button. Will give you a beer/coffee right now. To all you guys reading this - consider also donating if this tutorial helped you 😉
    #Edit: I couldn't donate (I'm from Germany). I am getting this error message on BuyMeACoffee from Stripe:

    This account isn't enabled to make cross border transactions. You can enable your account at https://dashboard.stripe.com/settings/update

    1. Madhu Desai Avatar

      I'm glad it worked out so well for you. Thank you for the coffee as well. It turns out that I cannot receive international payments because I chose the 'Individual' option. To receive money from overseas, I need to obtain a GST number. This is a 15-20 day process. So I just applied. I'll wait 15 days to see what happens.

      Anyway, thank you.

Leave a Reply

Your email address will not be published. Required fields are marked *