How to Install Fedora 38 with Snapshot and Rollback Support

How to Install Fedora 38 with Snapshot and Rollback Support Feature Image

Fedora Linux 38 is now available! This release includes the latest GNOME 44 desktop as well as other user-experience enhancements.

I’ve already written an article on how to install Fedora 37 with snapshot and rollback support. When it comes to btrfs snapshot and rollback support, nothing has changed in Fedora 38. The DNF database is still in /var/lib/dnf and has not been moved to /usr.

In this updated guide on how to Install Fedora 38 with snapshot and rollback support, I’ve made some changes. The changes are as follows:

  1. Created new subvolumes on the system root to keep some directories out of root file system snapshots. Some of these directories contain temporary files and caches, others contain data that you do not want to lose if you roll back the system root, and some should be in Read-Write mode when booting into a Read-only snapshot.
  2. Created one subvolume in the user home for the Firefox browser. This prevents you from losing bookmarks, passwords, and other user data when you undo a change to the user’s home.
  3. Turned on automatic timeline snapshots for the system root in snapper. You can, however, turn off the timeline snapshots.
  4. Moved grub-btrfs from the GitHub archived ‘Add-systemd-volatile’ branch to the active master branch.
  5. Created a snapshot of the system root and set it as the default root file system. This makes managing snapshots and rollbacks a lot easier.

If you want to install Fedora 38 with LUKS Full Disk Encryption, Snapshot and Rollback Support, please see my other article, ‘How to Install Fedora 38 with Full Disk Encryption, Snapshot and Rollback Support‘.

So let’s get started.

Table of Contents

1. Disk and Subvolumes Layout for Fedora 38

I’ll be using a hard disk with a capacity of 100 GiB. I’ll create one 512 MiB EFI partition and use the rest of the disk space to create a btrfs volume. There is no need for a separate swap partition because Fedora creates a SwapOnZRAM during boot.

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 btrfs main volume (/dev/vda2). I’ll then create the following subvolumes on the system root to keep them out of root file system snapshots.

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 information as well as Gnome display information. These directories must always be writable. When you attempt 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 my previous guides, I enabled the ‘systemd.volatile=state‘ kernel parameter, which should have solved this problem, but some of my readers reported that they couldn’t log in. As a result, I created subvolumes for these two directories so that they are always writable and thus permanently solve this problem.

If you are using a display manager other than Gnome, you must create a directory specific to that display manager. For XFCE, it might be /var/lib/lightdm. I haven’t tested.

/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. So, 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.

As a result, I created a separate subvolume for the ‘.mozilla‘ directory, keeping it separate from the /home subvolume and avoiding data loss during any undo changes.

Create a subvolume for the ‘/home/<USER>/.config/google-chrome‘ directory if you use the Chrome web browser.

2. Install Fedora 38 Workstation

Boot your system using the Fedora 38 Workstation installer in UEFI mode. On the welcome screen, select the Install to Hard Drive option. Next, select your LanguageKeyboard, and configure Time & Date. Following that, from the INSTALLATION SUMMARY screen, select Installation Destination.

You should now be on the INSTALLATION DESTINATION screen. To proceed, pick the Advanced Custom (Blivet-GUI) radio button and then hit the Done button.

On the BLIVET GUI PARTITIONING screen, create the partitions, file systems, and btrfs subvolumes necessary to install Fedora 38 Workstation.

How to Install Fedora 38 with Snapshot and Rollback Support Blivet

First, you need to create and mount the EFI partition. Select the free space and click the + sign to create a partition.

Set the partition Size to 512 MiB, the Filesystem to EFI System Partition, and the Mountpoint to /boot/efi.

How to Install Fedora 38 with Snapshot and Rollback Support EFI Partition

Then, you need to create a btrfs volume where you can create all the subvolumes needed to install Fedora 38 Workstation.

Select the free space again and click on the + sign to create a Btrfs volume. Set the Filesystem to btrfs and the Mountpoint to /. I used the entire remaining space. However, you can specify the size you want for the btrfs volume.

How to Install Fedora 38 with Snapshot and Rollback Support Btrfs root Partition

Next, you must create a home subvolume. (1) Select the Btrfs Volume from the left panel, and (2) click on the + sign on the right panel.

How to Install Fedora 38 with Snapshot and Rollback Support Create Subvolumes

Create a home subvolume. Enter the Name as home and Mountpoint as /home. Click OK to finish.

How to Install Fedora 38 with Snapshot and Rollback Support home Subvolume

I will create the remaining subvolumes when the installation is finished. This is because the Anaconda installer does not allow you to create subvolumes with slashes (/) in their paths, such as var/log.

For now, click Done to finish creating subvolumes.

On the SUMMARY OF CHANGES screen, double-check that everything is properly defined. To finalize the changes, click the Accept Changes button.

How to Install Fedora 38 with Snapshot and Rollback Support Summary of Changes

You will be returned to the INSTALLATION SUMMARY screen. Press the Begin Installation button to start the installation process. The installation process will start. Just sit back and relax.

How to Install Fedora 38 with Snapshot and Rollback Support Installation

When the installation is finished, click the Finish Installation button and restart the system.

The last phase of the installation process will start. Click the Start Setup button to complete the remaining customization steps, such as setting a new login, password, and so on.

You will then be logged into the Fedora 38 Workstation with the all-new Gnome 44 desktop interface.

How to Install Fedora 38 with Snapshot and Rollback Support GNOME 44

Now, open the Gnome terminal.

When booting your system, you may have noticed the following error message.

error: ../../grub-core/commands/loadenv.c:216:sparse file not allowed.

This is because you did not create a separate ext4 /boot partition and instead included it in the btrfs system root. GRUB preboot writes to /boot/grub2/grubenv if the boot was successful. This error occurs because of the GRUB btrfs.mod driver, unlike ext4, is read-only. To resolve this, execute the following command.

$ sudo grub2-editenv - unset menu_auto_hide

Set the btrfs volume label. I named the btrfs volume FEDORA, but you may name it whatever you want.

$ sudo btrfs filesystem label / FEDORA

$ sudo btrfs filesystem show /
Label: 'FEDORA'  uuid: 2990369d-fdc3-4c1a-b8a8-313e010434e1
	Total devices 1 FS bytes used 5.93GiB
	devid    1 size 99.50GiB used 8.02GiB path /dev/vda2

Your setup should look something like this.

$ lsblk -p
NAME        MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
/dev/zram0  251:0    0  3.8G  0 disk [SWAP]
/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 /home
                                     /

And the subvolumes will look like this.

$ sudo btrfs subvolume list /
ID 256 gen 41 top level 5 path home
ID 257 gen 33 top level 5 path var/lib/machines

The var/lib/machines subvolume is created by systemd implicitly in Fedora 38 Workstation for systemd-nspawn containers.

Enable the fastest mirrors to speed up package downloads. Copy the command from sudo to EOF, paste it into your terminal, and hit <Enter>.

$ sudo bash -c 'cat >> /etc/dnf/dnf.conf' <<EOF
defaultyes=True
fastestmirror=True
max_parallel_downloads=10
EOF

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

$ sudo dnf clean all
$ sudo dnf makecache

Install the packages listed below.

$ sudo dnf install vim inotify-tools make

Now, update your operating system.

$ sudo dnf update

And reboot your system.

$ sudo reboot

3. Create the Additional Subvolumes

I’ll now proceed to create the remaining subvolumes on the system root. 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.

Instead of manually creating subvolumes, I use the bash for loop. If you want to add or remove subvolumes, change the variable declaration.

#### Get the UUID of your btrfs system root.
$ ROOT_UUID="$(sudo grub2-probe --target=fs_uuid /)"

#### Get the btrfs subvolume mount options from your fstab.
$ OPTIONS="$(grep '/home' /etc/fstab | awk '{print $4}' | cut -d, -f2-)"

#### Create a directory path. Only for other DEs; not required for Fedora Workstation.
$ sudo mkdir -vp /var/lib/libvirt

#### Declare rest of the subvolumes you want to create in the array.
#### Copy from 'SUBVOLUMES' to ')', paste it in terminal, and hit <Enter>.
$ SUBVOLUMES=(
    "opt"
    "var/cache"
    "var/crash"
    "var/log"
    "var/spool"
    "var/tmp"
    "var/www"
    "var/lib/AccountsService"
    "var/lib/gdm"
    "var/lib/libvirt/images"
    "home/$USER/.mozilla"
)

#### Run the for loop to create the subvolumes.
#### Copy from 'for' to 'done', paste it in terminal, and hit <Enter>.
$ for dir in "${SUBVOLUMES[@]}" ; do
    if [[ -d "/${dir}" ]] ; then
        sudo mv -v "/${dir}" "/${dir}-old"
        sudo btrfs subvolume create "/${dir}"
        sudo cp -ar "/${dir}-old/." "/${dir}/"
    else
        sudo btrfs subvolume create "/${dir}"
    fi
    sudo restorecon -RF "/${dir}"
    printf "%-41s %-24s %-5s %-s %-s\n" \
        "UUID=${ROOT_UUID}" \
        "/${dir}" \
        "btrfs" \
        "subvol=${dir},${OPTIONS}" \
        "0 0" | \
        sudo tee -a /etc/fstab
done

You must change the permissions of some of the directories.

$ sudo chmod 1777 /var/tmp
$ sudo chmod 1770 /var/lib/gdm
$ sudo chown -R $USER: /home/$USER/.mozilla

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

$ cat /etc/fstab
...
UUID=2990369d-fdc3-4c1a-b8a8-313e010434e1 /                        btrfs defaults        0 0
UUID=D17B-4753                            /boot/efi                vfat  umask=0077,shortname=winnt 0 2
UUID=2990369d-fdc3-4c1a-b8a8-313e010434e1 /home                    btrfs subvol=home,compress=zstd:1 0 0
UUID=2990369d-fdc3-4c1a-b8a8-313e010434e1 /opt                     btrfs subvol=opt,compress=zstd:1 0 0 
UUID=2990369d-fdc3-4c1a-b8a8-313e010434e1 /var/cache               btrfs subvol=var/cache,compress=zstd:1 0 0 
UUID=2990369d-fdc3-4c1a-b8a8-313e010434e1 /var/crash               btrfs subvol=var/crash,compress=zstd:1 0 0 
UUID=2990369d-fdc3-4c1a-b8a8-313e010434e1 /var/log                 btrfs subvol=var/log,compress=zstd:1 0 0 
UUID=2990369d-fdc3-4c1a-b8a8-313e010434e1 /var/spool               btrfs subvol=var/spool,compress=zstd:1 0 0 
UUID=2990369d-fdc3-4c1a-b8a8-313e010434e1 /var/tmp                 btrfs subvol=var/tmp,compress=zstd:1 0 0 
UUID=2990369d-fdc3-4c1a-b8a8-313e010434e1 /var/www                 btrfs subvol=var/www,compress=zstd:1 0 0 
UUID=2990369d-fdc3-4c1a-b8a8-313e010434e1 /var/lib/AccountsService btrfs subvol=var/lib/AccountsService,compress=zstd:1 0 0 
UUID=2990369d-fdc3-4c1a-b8a8-313e010434e1 /var/lib/gdm             btrfs subvol=var/lib/gdm,compress=zstd:1 0 0 
UUID=2990369d-fdc3-4c1a-b8a8-313e010434e1 /var/lib/libvirt/images  btrfs subvol=var/lib/libvirt/images,compress=zstd:1 0 0 
UUID=2990369d-fdc3-4c1a-b8a8-313e010434e1 /home/madhu/.mozilla     btrfs subvol=home/madhu/.mozilla,compress=zstd:1 0 0

Reload /etc/fstab to mount all the subvolumes.

$ sudo systemctl daemon-reload

$ sudo mount -va
/                        : ignored
/boot/efi                : already mounted
/home                    : already 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/AccountsService : successfully mounted
/var/lib/gdm             : successfully mounted
/var/lib/libvirt/images  : successfully mounted
/home/madhu/.mozilla     : successfully mounted

Check your subvolumes.

$ sudo btrfs subvolume list /
ID 256 gen 123 top level 5 path home
ID 257 gen 123 top level 5 path var/lib/machines
ID 258 gen 104 top level 5 path opt
ID 259 gen 123 top level 5 path var/cache
ID 260 gen 106 top level 5 path var/crash
ID 261 gen 123 top level 5 path var/log
ID 262 gen 123 top level 5 path var/spool
ID 263 gen 123 top level 5 path var/tmp
ID 264 gen 110 top level 5 path var/www
ID 265 gen 123 top level 5 path var/lib/AccountsService
ID 266 gen 123 top level 5 path var/lib/gdm
ID 267 gen 123 top level 5 path var/lib/libvirt/images
ID 268 gen 123 top level 256 path home/madhu/.mozilla

Your setup should now look somewhat like this.

$ lsblk -p
NAME        MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
/dev/zram0  251:0    0  3.8G  0 disk [SWAP]
/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 /home/madhu/.mozilla
                                     /var/lib/libvirt/images
                                     /var/lib/gdm
                                     /var/lib/AccountsService
                                     /var/www
                                     /var/tmp
                                     /var/spool
                                     /var/log
                                     /var/crash
                                     /var/cache
                                     /opt
                                     /home
                                     /

Now that everything appears to be in order, you can delete the old directories. Copy from ‘for’ to ‘done’, paste it into the terminal, and hit <Enter>.

$ for dir in "${SUBVOLUMES[@]}" ; do
    if [[ -d "/${dir}-old" ]] ; then
        sudo rm -rf "/${dir}-old"
    fi
done

All subvolumes have now been created.

4. 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

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=2990369d-fdc3-4c1a-b8a8-313e010434e1 /home/madhu/.mozilla     btrfs subvol=home/madhu/.mozilla,compress=zstd:1 0 0 
UUID=2990369d-fdc3-4c1a-b8a8-313e010434e1 /.snapshots              btrfs subvol=.snapshots,compress=zstd:1 0 0
UUID=2990369d-fdc3-4c1a-b8a8-313e010434e1 /home/.snapshots         btrfs subvol=home/.snapshots,compress=zstd:1 0 0

Reload the /etc/fstab file.

$ sudo systemctl daemon-reload
$ sudo mount -va

Your setup should look something 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 /home/.snapshots
                                     /.snapshots
                                     /home/madhu/.mozilla
                                     /var/www
                                     /var/spool
                                     /var/tmp
                                     /var/log
                                     /var/lib/libvirt/images
                                     /var/lib/gdm
                                     /var/lib/AccountsService
                                     /var/crash
                                     /var/cache
                                     /opt
                                     /home
                                     /

And your subvolumes will look like this.

$ sudo btrfs subvolume list /
ID 256 gen 129 top level 5 path home
ID 257 gen 123 top level 5 path var/lib/machines
ID 258 gen 104 top level 5 path opt
ID 259 gen 127 top level 5 path var/cache
ID 260 gen 106 top level 5 path var/crash
ID 261 gen 131 top level 5 path var/log
ID 262 gen 123 top level 5 path var/spool
ID 263 gen 126 top level 5 path var/tmp
ID 264 gen 110 top level 5 path var/www
ID 265 gen 123 top level 5 path var/lib/AccountsService
ID 266 gen 123 top level 5 path var/lib/gdm
ID 267 gen 123 top level 5 path var/lib/libvirt/images
ID 268 gen 123 top level 256 path home/madhu/.mozilla
ID 269 gen 129 top level 5 path .snapshots
ID 270 gen 129 top level 256 path home/.snapshots

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

Enable snapshot booting by appending the SUSE_BTRFS_SNAPSHOT_BOOTING="true" option to the /etc/default/grub file.

$ echo 'SUSE_BTRFS_SNAPSHOT_BOOTING="true"' | sudo tee -a /etc/default/grub

You must also make changes to the /boot/efi/EFI/fedora/grub.cfg file now that snapshot booting is enabled.

$ sudo sed -i '1i set btrfs_relative_path="yes"' /boot/efi/EFI/fedora/grub.cfg

Finally, update the grub.cfg file.

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

Later, I’ll enable snapper timeline snapshots. For now, the snapper configuration is complete.

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.

5. 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

6. 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 create a snapshot of the system root and make it the default. This makes it much easier to manage snapshots and rollbacks.

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

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
271

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

$ sudo btrfs subvolume set-default 271 /

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 271 gen 170 top level 269 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 |       | Friday 28 April 2023 05:49:29 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.

7. 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 +  13.5 KiB = 161.5 KiB	fusermount3
196.0 KiB +  13.5 KiB = 209.5 KiB	inotifywait
296.0 KiB +  15.5 KiB = 311.5 KiB	mcelog
...
 51.4 MiB +   3.5 MiB =  54.9 MiB	python3.11
204.2 MiB +  23.5 MiB = 227.6 MiB	gnome-shell
268.7 MiB +   2.0 MiB = 270.7 MiB	packagekitd
---------------------------------
                          1.2 GiB
=================================

Check the snapper for snapshots.

$ snapper ls
 # | Type   | Pre # | Date                             | User | Cleanup | Description                 | Userdata
---+--------+-------+----------------------------------+------+---------+-----------------------------+---------
0  | single |       |                                  | root |         | current                     |         
1* | single |       | Friday 28 April 2023 05:49:29 PM | root |         | first root subvolume        |         
2  | pre    |       | Friday 28 April 2023 06:50:21 PM | root | number  | /usr/bin/dnf install ps_mem |         
3  | post   |     2 | Friday 28 April 2023 06:50:23 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 +  13.5 KiB = 161.5 KiB	fusermount3
196.0 KiB +  13.5 KiB = 209.5 KiB	inotifywait
296.0 KiB +  15.5 KiB = 311.5 KiB	mcelog
...
 51.4 MiB +   3.5 MiB =  54.9 MiB	python3.11
204.2 MiB +  23.5 MiB = 227.6 MiB	gnome-shell
268.7 MiB +   2.0 MiB = 270.7 MiB	packagekitd
---------------------------------
                          1.2 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	2022-11-27 20:56:24.000000000 +0530
+++ /etc/hosts	2023-04-28 21:14:25.578325998 +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

In the output, 0 represents the current snapshot. 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 snapper and man diff.

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 |       | Friday 28 April 2023 05:49:29 PM | root  |         | first root subvolume        |         
2  | pre    |       | Friday 28 April 2023 06:50:21 PM | root  | number  | /usr/bin/dnf install ps_mem |         
3  | post   |     2 | Friday 28 April 2023 06:50:23 PM | root  | number  | /usr/bin/dnf install ps_mem |         
4  | pre    |       | Friday 28 April 2023 07:00:51 PM | madhu | number  | Pre Color Picker            |         

$ snapper -c home ls
 # | Type   | Pre # | Date                             | User  | Cleanup | Description      | Userdata
---+--------+-------+----------------------------------+-------+---------+------------------+---------
0  | single |       |                                  | root  |         | current          |         
1  | pre    |       | Friday 28 April 2023 07:01:05 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.

How to Install Fedora 38 with 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 |       | Friday 28 April 2023 05:49:29 PM | root  |         | first root subvolume                                                                   |         
2  | pre    |       | Friday 28 April 2023 06:50:21 PM | root  | number  | /usr/bin/dnf install ps_mem                                                            |         
3  | post   |     2 | Friday 28 April 2023 06:50:23 PM | root  | number  | /usr/bin/dnf install ps_mem                                                            |         
4  | pre    |       | Friday 28 April 2023 07:00:51 PM | madhu | number  | Pre Color Picker                                                                       |         
5  | pre    |       | Friday 28 April 2023 07:05:52 PM | root  | number  | /usr/bin/dnf install meson gcc-c++ libhandy-devel libportal-devel libportal-gtk3-devel |         
6  | post   |     5 | Friday 28 April 2023 07:06:27 PM | root  | number  | /usr/bin/dnf install meson gcc-c++ libhandy-devel libportal-devel libportal-gtk3-devel |         
7  | post   |     4 | Friday 28 April 2023 07:27:26 PM | madhu | number  | Post Color Picker

$ snapper -c home ls
 # | Type   | Pre # | Date                             | User  | Cleanup | Description       | Userdata
---+--------+-------+----------------------------------+-------+---------+-------------------+---------
0  | single |       |                                  | root  |         | current           |         
1  | pre    |       | Friday 28 April 2023 07:01:05 PM | madhu | number  | Pre Color Picker  |         
2  | post   |     1 | Friday 28 April 2023 07:27:13 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
+..... /home/madhu/.config/gcolor3
+..... /home/madhu/.config/gcolor3/config.ini
+..... /home/madhu/gcolor3
+..... /home/madhu/gcolor3/build
+..... /home/madhu/gcolor3/build/build.ninja
...
+..... /home/madhu/.local/share/gnome-shell/application_state
c..... /home/madhu/.local/share/gvfs-metadata/root
-..... /home/madhu/.local/share/gvfs-metadata/root-3616f454.log
+..... /home/madhu/.local/share/gvfs-metadata/root-54385136.log

$ snapper -c root status 4..7
c..... /boot/grub2/grub-btrfs.cfg
c..... /boot/grub2/grub.cfg
+..... /etc/alternatives/ld
c..... /etc/ld.so.cache
+..... /usr/bin/addr2line
...
+..... /usr/share/xml/dbus-1/catalog.xml
+..... /usr/share/xml/dbus-1/introspect.dtd
+..... /usr/share/zsh/site-functions/_meson
+..... /usr/share/zsh/site-functions/_ninja
+..... /var/lib/alternatives/ld
c..... /var/lib/dnf/history.sqlite
c..... /var/lib/dnf/history.sqlite-shm
c..... /var/lib/dnf/history.sqlite-wal

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

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

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

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

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

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

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
249M	/boot
32M	/etc
5.8G	/usr
6.1G	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.

How to Install Fedora 38 with Snapshot and Rollback Support Boot Error

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

How to Install Fedora 38 with Snapshot and Rollback Support Snapshots Menu
How to Install Fedora 38 with Snapshot and Rollback Support Snapshot No 3
How to Install Fedora 38 with Snapshot and Rollback Support 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 |       | Friday 28 April 2023 05:49:29 PM | root |         | first root subvolume        |         
2  | pre    |       | Friday 28 April 2023 06:50:21 PM | root | number  | /usr/bin/dnf install ps_mem |         
3- | post   |     2 | Friday 28 April 2023 06:50:23 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
249M    /boot
32M     /etc
5.8G    /usr
6.1G    total

$ sudo btrfs property get -ts /
ro=false

$ snapper ls
 # | Type   | Pre # | Date                             | User | Cleanup | Description                 | Userdata     
---+--------+-------+----------------------------------+------+---------+-----------------------------+--------------
0  | single |       |                                  | root |         | current                     |              
1  | single |       | Friday 28 April 2023 05:49:29 PM | root | number  | first root subvolume        |              
2  | pre    |       | Friday 28 April 2023 06:50:21 PM | root | number  | /usr/bin/dnf install ps_mem |              
3  | post   |     2 | Friday 28 April 2023 06:50:23 PM | root | number  | /usr/bin/dnf install ps_mem |              
4  | single |       | Friday 28 April 2023 08:21:39 PM | root | number  | rollback backup of #1       | important=yes
5* | single |       | Friday 28 April 2023 08:21:39 PM | root |         | writable copy of #3         |

$ sudo btrfs subvolume list /
ID 256 gen 348 top level 5 path home
ID 257 gen 159 top level 5 path var/lib/machines
ID 258 gen 104 top level 5 path opt
ID 259 gen 340 top level 5 path var/cache
ID 260 gen 106 top level 5 path var/crash
ID 261 gen 351 top level 5 path var/log
ID 262 gen 340 top level 5 path var/spool
ID 263 gen 346 top level 5 path var/tmp
ID 264 gen 110 top level 5 path var/www
ID 265 gen 340 top level 5 path var/lib/AccountsService
ID 266 gen 340 top level 5 path var/lib/gdm
ID 267 gen 123 top level 5 path var/lib/libvirt/images
ID 268 gen 123 top level 256 path home/madhu/.mozilla
ID 269 gen 351 top level 5 path .snapshots
ID 270 gen 301 top level 256 path home/.snapshots
ID 271 gen 332 top level 269 path .snapshots/1/snapshot
ID 272 gen 181 top level 269 path .snapshots/2/snapshot
ID 273 gen 333 top level 269 path .snapshots/3/snapshot
ID 274 gen 332 top level 269 path .snapshots/4/snapshot
ID 275 gen 349 top level 269 path .snapshots/5/snapshot

$ sudo btrfs subvolume get-default /
ID 275 gen 349 top level 269 path .snapshots/5/snapshot

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

Test 4 is successful.

8. 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
  79.53MiB       0.00B    79.53MiB  /.snapshots/1/snapshot
   5.84GiB    36.00KiB     5.78GiB  /.snapshots/2/snapshot
   5.84GiB    52.00KiB     5.78GiB  /.snapshots/3/snapshot
  79.53MiB       0.00B    79.53MiB  /.snapshots/4/snapshot
   5.84GiB   228.00KiB     5.78GiB  /.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 |       | Friday 28 April 2023 05:49:29 PM | root | number  | first root subvolume        |              
2  | pre    |       | Friday 28 April 2023 06:50:21 PM | root | number  | /usr/bin/dnf install ps_mem |              
3  | post   |     2 | Friday 28 April 2023 06:50:23 PM | root | number  | /usr/bin/dnf install ps_mem |              
4  | single |       | Friday 28 April 2023 08:21:39 PM | root | number  | rollback backup of #1       | important=yes
5* | single |       | Friday 28 April 2023 08:21:39 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    |       | Friday 28 April 2023 06:50:21 PM | root | number  | /usr/bin/dnf install ps_mem |         
5* | single |       | Friday 28 April 2023 08:21:39 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-04-28 13:20:21</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-04-28 13:20:21</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
276

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

$ sudo btrfs subvolume set-default 276 /

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 276 gen 418 top level 269 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 |       | Friday 28 April 2023 06:50:21 PM | root |         | new root subvolume          |         
2  | pre    |       | Friday 28 April 2023 06:50:21 PM | root | number  | /usr/bin/dnf install ps_mem |         
5  | single |       | Friday 28 April 2023 08:21:39 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 |       | Friday 28 April 2023 06:50:21 PM | root |         | new root subvolume |

$ sudo btrfs filesystem du -s --human-readable /.snapshots/*/snapshot
     Total   Exclusive  Set shared  Filename
   5.84GiB     7.59MiB     5.78GiB  /.snapshots/1/snapshot

You’re done.

9. 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 |       | Friday 28 April 2023 06:50:21 PM | root |          | new root subvolume |         
2  | single |       | Friday 28 April 2023 10:00:53 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 snapshot and rollback support is now complete.

Watch on YouTube

Comments

52 responses to “How to Install Fedora 38 with Snapshot and Rollback Support”

  1. Michael Sharp Avatar

    Sir, it appears you are total Fedora guru!
    The only part of this install that was not identical was my fstab did not contain the UUIDs of the newly created subvolumes, so I just copied them in and of course it worked.
    Thank you.

  2. Konstantin Avatar
    Konstantin

    I am facing a bit of a problem: I broke something when trying to enable hibernate according to this guide, and the system would refuse to boot, so I booted into the last working snapshot and did a snapper rollback. Then I tried following section 8 of the article, but when I ran

    snapper delete 1
    

    I got this error:

    Deleting snapshot failed.
    

    So my system is working just fine, but my default subvolume is now .snapshots/728/snapshot. I’d like to set my default subvolume to .snapshots/1/snapshot like it was previously. How can I do that without risking to delete my actual root directory?

    1. Madhu Desai Avatar

      Is there an asterisk symbol (*) in the output of the ‘snapper ls‘ command for snapshot #728? If so, try deleting the snapshot 1 with the sudo prefix. Permission issues can arise at times.

      Examine the /var/log/snapper.log log file as well. It’ll give you a hint.

  3. Max J. Avatar
    Max J.

    Hello Madhu, thanks for your awesome work! I made it to work on Debian using lots of this content you have provided. Could you elaborate a bit on part 6. and 8., test 4? I don’t quite really get what I’m donig when I follow your instructions about setting default btrfs subvolume snapshots… thanks a lot!

    1. Madhu Desai Avatar

      You don’t have to create the default subvolume. By default, no btrfs subvolume is set as the default (btrfs subvolume get-default /). When you rollback a snapshot in snapper, that subvolume then becomes the default. By manually creating a first snapshot of the main volume and making it the default, you can rollback without having to specify the snapshot number and the ambit during the rollback process.

      Section 8 is also the same. I simply made one of the snapshots the new default and the first one, and deleted the remaining snapshots.

      In test 4, I deliberately broke the system and rolled back to a previous working snapshot.

      1. Max J. Avatar
        Max J.

        thank you!

  4. fuzz Avatar
    fuzz

    hello, i folllow your tutorial and success, then im trying to change my display manager (im using sddm before) to lightdm and greetd, i follow tutorial number 3 to create another subvolume, change the SUBVOLUMES variable to “/var/lib/lightdm” and “/var/lib/greetd”. it can create the subvolume and add that to /etc/fstab, but i got this error when trying to mount
    /                       : 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/AccountsService : already mounted
    /var/lib/sddm           : already mounted
    /var/lib/libvirt/images : already mounted
    /home/fuzz/.mozilla     : already mounted
    /.snapshots             : already mounted
    /home/.snapshots        : already mounted
    mount: /var/lib/greetd: mount(2) system call failed: No such file or directory.
          dmesg(1) may have more information after failed mount system call.
    mount: /var/lib/lightdm: mount(2) system call failed: No such file or directory.
          dmesg(1) may have more information after failed mount system call.
    am i doing it wrong?

    1. Madhu Desai Avatar

      What is the output of the command?
      btrfs subvolume list /

      Do the subvolumes appear in the output?

      1. fuzz Avatar
        fuzz

        yes, the subvolumes do appear, here the ouput
        https://pastebin.com/wVgP3KC9

        1. Madhu Desai Avatar

          The output indicates that the two subvolumes are not top-level (ID=5).

          First, rename or delete the two subvolumes.

          Assuming that the btrfs partition is /dev/vda2, mount the btrfs volume with id=5 option.
          sudo mount -o subvolid=5 /dev/vda2 /mnt

          After that, create the two subvolumes.
          sudo btrfs subvolume create /mnt/var/lib/greetd
          sudo btrfs subvolume create /mnt/var/lib/lightdm

          Un mount the btrfs volume
          sudo umount /mnt

          Check the subvolumes once more. The two subvolumes must be visible with level 5. Then, update the /etc/fstab file. It should work fine.

  5. Mukund Avatar
    Mukund

    Thanks for the guide, tests for undoing changes on dnf work well.
    But, while trying to make changes to individual files and testing snapper, I am getting the following permission denied error. snapper diff 4..0 /etc/hosts IO Error (open failed path://.snapshots/4/snapshot/root/.cache/keyring-X95291/control errno:13 (Permission denied))

    1. Madhu Desai Avatar

      It appears that the problem is unrelated to snapper. Can you restart the system and check again to see if the problem has been resolved?

  6. rsza Avatar
    rsza

    I just want to say this is one of the best guides I have seen out there for implementing something in linux overall , super well done ! and your youtube video is really good too . Great job

    1. Madhu Desai Avatar

      Thank you so much. I’m so glad that you liked it.

      1. rsza Avatar
        rsza

        wondering if you could help , im right at the end of part 6 but snapper is not playing ball .

        [user@fedora ~]$ sudo mkdir -v /.snapshots/1
        mkdir: created directory ‘/.snapshots/1’
        [user@fedora ~]$ sudo nano /.snapshots/1/info.xml
        cat /.snapshots/1/info.xml
        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
        [user@fedora ~]$ sudo btrfs subvolume snapshot / /.snapshots/1/snapshot
        Create a snapshot of ‘/’ in ‘/.snapshots/1/snapshot’
        [user@fedora ~]$ sudo btrfs inspect-internal rootid /.snapshots/1/snapshot
        271
        [user@fedora ~]$ sudo btrfs subvolume set-default 271 /
        [user@fedora ~]$ **sudo reboot**

        sudo btrfs subvolume get-default /
        ID 271 gen 430 top level 269 path .snapshots/1/snapshot

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

        I tried to start the service but it ended up creating “2” and still ignoring “1” , should I just mv 2 to 1 ?

      2. rsza Avatar
        rsza

        no worries I realized I skimmed at an important part and messed up info.xml ! lol thanks man

        snapper ls
         # | Type  | Pre # | Date                    | User | Cleanup | Description         | Userdata
        —+——–+——-+————————–+——+———-+———————-+———
        0 | single |      |                         | root |         | current             |        
        1* | single |      | Wed 30 Aug 2023 11:59:57 | root |         | first root subvolume |        
        2 | single |      | Wed 30 Aug 2023 11:18:52 | root | timeline | timeline            |        

  7. cris Avatar
    cris

    Could you make a tuto but for debian.
    I can not make the default snapshot be booted by default.

    1. cris Avatar
      cris

      Made it, Also in debian is super more simple.

      vim /etc/default/grub
      GRUB_CMDLINE_LINUX_DEFAULT="quiet rootflags=noatime"
      
      
      
  8. Konstantin Avatar
    Konstantin

    sorry… regarding my previous comment, I made a mistake and psd didn’t actually pick up the directory correctly. It seems psd doesn’t support flatpak’s sandbox system since flatpak firefox shows a “profile not accessible” error when enabling psd with the correct configuration.

  9. Konstantin Avatar
    Konstantin

    If you use any browsers as flatpak:

    1. quit any open browser
    2. install Flatseal
    3. add “home:rw” entry in the filesystem section
    4. copy ~/.var/app/[flatpak_id]/[profile_dir] to ~/ (optional: delete the original profile folder)
    5. open the browser (it should open your profile as usual)
    6. go to about:profiles and open your profile dir: it should work now
    7. follow section 3 of the article, replacing the SUBVOLUMES array with the new profile directory; before reloading systemctl, open /etc/fstab and check if everything looks right
    8. profit!

    I would also recommend checking out profile-sync-daemon, you should be able to use just fine now. Check out https://wiki.archlinux.org/title/Firefox/Tweaks for more info on how to optimize Firefox and its derivates further.

  10. Josh Avatar
    Josh

    Hello, if I remember correctly, you planned to write the article about proper dualboot with Windows on a single disk. Any updates on that? Thanks.

    1. Madhu Desai Avatar

      Yes, I remember it really well. In fact, I attempted to set up snapper and grub-btrfs for proper rollback on Ubuntu. But I failed miserably because the Ubuntu installation is stubborn. I tried every method available to me (Using GUI installer and chroot) to install Ubuntu system root (/) as the btrfs main volume, but they all failed miserably. In Ubuntu, the system root has to be a subvolume.

      Disappointed, I returned to work on a YouTube video for Fedora 38 LUKS. I’ll upload the video to YouTube tomorrow and return to the dualboot as soon as I can.

      Whatever the outcome is, I’ll let you know by the weekend. Sorry about that, and thank you for your patience.

    2. Madhu Desai Avatar

      I’m working hard to get Ubuntu to rollback from a snapshot. However, it is taking longer than I anticipated. I’m stuck with grub-btrfs. I’m not very familiar with Ubuntu, so it’s quite difficult for me. Hopefully, I’ll be successful in the end and be able to publish the article. You’ll have to wait a little longer, I suppose. If I don’t succeed, I plan to use the manual rollback method. So, let’s see what happens. I apologize for the bad news.

  11. Juan Manuel Lobos Avatar
    Juan Manuel Lobos

    Same as Kronik, I had a fedora 38 with LUKS automatically unlocked by TPM, and after install and make grub-btrfs changes, Grub gone fubar, no boot at all.

     lsblk -p /dev/nvme0n1
    NAME                           MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
    /dev/nvme0n1                       259:0  0 476,9G 0 disk  
    ├─/dev/nvme0n1p1                     259:1  0   2G 0 part /boot/efi
    ├─/dev/nvme0n1p2                     259:2  0   2G 0 part /boot
    ├─/dev/nvme0n1p3                     259:3  0 456,9G 0 part  
    │ └─/dev/mapper/luks-d0f1fb6d-f3c6-4cd7-a4ed-f2b3f18b8444 253:1  0 456,9G 0 crypt /var
    │                                          /home
    │                                          /
    └─/dev/nvme0n1p4                     259:4  0  16G 0 part  
     └─/dev/mapper/luks-12e0f0bc-7ef5-4de5-91ac-1b467b946868 253:0  0  16G 0 crypt [SWAP]
    (I did not create any additionals subvols, I wanted to test with full root )
    btrfs subvolume list /
    ID 256 gen 10259 top level 5 path var
    ID 257 gen 10259 top level 5 path home
    ID 258 gen 10259 top level 5 path root
    ID 259 gen 10083 top level 256 path var/lib/machines

    grubby –info=DEFAULT
    index=0
    kernel=”/boot/vmlinuz-6.3.8-200.fc38.x86_64″
    args=”ro rootflags=subvol=root rd.driver.blacklist=nouveau modprobe.blacklist=nouveau resume=/dev/mapper/luks-12e0f0bc-7ef5-4de5-91ac-1b467b946868 rd.luks.uuid=luks-d0f1fb6d-f3c6-4cd7-a4ed-f2b3f18b8444 rd.luks.uuid=luks-12e0f0bc-7ef5-4de5-91ac-1b467b946868 rd.luks.options=tpm2-device=auto rhgb quiet nvidia-drm.modeset=1″
    root=”UUID=feb1d19f-eb14-489d-8bd5-71a35af29c4f”
    initrd=”/boot/initramfs-6.3.8-200.fc38.x86_64.img”
    title=”Fedora Linux (6.3.8-200.fc38.x86_64) 38 (Workstation Edition)”
    id=”4a94a83fdcd2489684c3afb8f39acd03-6.3.8-200.fc38.x86_64″

    1. Madhu Desai Avatar

      From what I see in the outputs, you have created a separate /boot partition (/dev/nvme0n1p2). In this tutorial, I deliberately did not create a separate /boot partition and instead included boot files in the main system root. You are experiencing this issue as a result of your separate /boot partition.

      You also do not need to create a separate swap partition (/dev/nvme0n1p4). Fedora creates a swap on zram on boot, which is better to a swap within a partition.

      1. Juan Manuel Lobos Avatar
        Juan Manuel Lobos

        Allright. It’s just this wasn’t an installation from scratch but a recent installation either way. I did that on purpose to encrypt the swap partition as well, I’ll be considering turning it off and use zram instead.
        So basically if I manage to put the grub partition inside the root / it’ll all work out fine (?)
        Thanks for your time and replying so soon.

  12. KronikPillow Avatar
    KronikPillow

    Following the guide, after first boot and running sudo dnf update, after the restart im unable to boot

    1. Madhu Desai Avatar

      What is the error message you’re getting?

      1. KronikPillow Avatar
        KronikPillow

        That the kernel is not found … Thats, fresh install, configure dnf, update, reboot and gone … Followed exact steps of guide, didnt get to creating extra subvolumes

        1. Madhu Desai Avatar

          Can you share the output of the following commands? Replace /dev/vda with your disk.

          lsblk -p /dev/vda
          btrfs subvolume list /
          grubby --info=DEFAULT
          cat /boot/efi/EFI/fedora/grub.cfg

          1. KronikPillow Avatar
            KronikPillow

            lsblk -p /dev/sda
            btrfs subvolume list /
            grubby --info=DEFAULT
            cat /boot/efi/EFI/fedora/grub.cfg

            NAME       MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
            /dev/sda     8:0   0 232.9G 0 disk
            ├─/dev/sda1  8:1   0  512M 0 part /boot/efi
            └─/dev/sda2  8:2   0 232.4G 0 part /home
                                                 /

            ID 256 gen 34 top level 5 path home
            ID 257 gen 25 top level 5 path var/lib/machines

            index=0
            kernel="/boot/vmlinuz-6.2.9-300.fc38.x86_64"
            args="ro rhgb quiet"
            root="UUID=ce6aa617-c626-4561-9417-e127083bdeaf"
            initrd="/boot/initramfs-6.2.9-300.fc38.x86_64.img"
            title="Fedora Linux (6.2.9-300.fc38.x86_64) 38 (Workstation Edition)"
            id="bd70c7f84b654b0e9a1d2347be1d8358-6.2.9-300.fc38.x86_64"

            search --no-floppy --fs-uuid --set=dev ce6aa617-c626-4561-9417-e127083bdeaf
            set prefix=($dev)/boot/grub2

            export $prefix
            configfile $prefix/grub.cfg

          2. Madhu Desai Avatar

            It seems like everything is fine. I ran another test in virtualization. Everything went perfectly on my end.

            Your kernel, as I can see, is 6.2.9-300. It is currently 6.3.5-200. It’s possible that the mirrors closest to you weren’t fully updated. Please check after the system has been updated once more.

            From the GRUB menu, on the kernel line. press ‘c
            In the grub prompt, enter the following:
            grub> chainloader (hd0,gpt1)/efi/fedora/grubx64.efi
            grub> boot

            Update the system one more time. Then, update the grub.cfg.
            grub2-mkconfig -o /boot/grub2/grub.cfg

            Reboot the computer. Hopefully, everything will go smoothly this time.

  13. KronikPillow Avatar
    KronikPillow

    wouldn’t excluding /boot/grub directory solve the grub problem? also, could you elaborate the why the systemd.volatile=state is necessary? Cuz I didn’t have to do this on Arch Linux at all (now im switching to fedora to test your guide, and to try out Fedora 38) …
    here is my Arch install script, maybe you can help me understand what volatile is and why it’s needed on Fedora, and not needed on Arch?
    btw, here is my OpenSuse like btrfs style layout for Arch Linux, with full snapper-rollback without the need to use –ambit classic or anything else, it works exactly the same like on https://github.com/kronikpillow/arch-install/tree/main …. check the 100-pre-user-subvolume.sh, and the other scripts …
    also, I wouldn’t chattr +C anything, the files in libvirt/images get automatically created with chattr +C by default, even when chattr +C is not enabled on the directory itself because it’s handled by qemu/kvm/virt-manager

    1. Madhu Desai Avatar

      I checked your subvolume layout, and it looks great. You probably can’t create such a layout in Fedora using the default Anaconda installer. I’ll have to try installing Fedora using the ‘dnf --installroot‘ command, as I did in my other blog ‘How to Install Fedora 38 with Full Disk Encryption, Snapshot and Rollback Support‘, and see how it goes.

      I notice that your scripts do not mention installing the GNOME graphical desktop environment. Fedora, too, will have no trouble booting into a read-only snapshot without a graphical desktop. However, a problem arises, particularly when you install the GNOME desktop. I have not tested for other DEs. You cannot boot into a read-only snapshot with “gdm” set as a graphical login in Fedora. I’m not sure how it works in Arch Linux.

      So, I set the kernel parameter ‘systemd.volatile=state‘. It causes the system to boot with the root filesystem as read-only and /var mounted as a writable tempfs ram-disk. In simple terms, the system will behave similarly to a Live Linux media without persistence.

      It would be ideal when you want to rollback a snapshot and only want to ensure that everything is as it should be in that snapshot without attempting to modify anything in the system root.

      It worked perfectly. But, even with ‘systemd.volatile=state‘ set, some of my readers reported that they couldn’t boot into a ready-only snapshot. As a result, I had to create two separate subvolumes from the system root snapshot regime: ‘/var/lib/AccountsService‘ and ‘/var/lib/gdm‘.

      About chattr, yes, chattr +C is automatically set for the image directory. So I guess I’ll have to get rid of that part. However, resetting will not cause any harm.

      Thank you for bringing it to my attention.

      1. KronikPillow Avatar
        KronikPillow

        Yes my script still is not converted to Fedora, and no display manager in my script as I don’t use one on Arch as usually I only have 1 Window Manager installed, so my base system is setup via posted scripts, and then my post base system install script varies depending on what I want to use in the current install.
        Although when I used SDDM as a login manager I didn’t have a problem booting into Arch from a read-only snapshot…

        You are right, you can not create such a layout with Anaconda, plus Anaconda sucks, I do not understand why Fedora keeps pushing the distro with it, everytime I want to create a subvolume with it Anaconsa freezes and asks me to wait or kill it … I never did a chroot install of Fedora, tried to grasp the approach with your guide with encryption, but couldn’t figure it out, and didn’t have enough time to keep tinkering yet and figure it out, so if doing a guide of a chroot install, with a layout I suggested without encryption it would be awesome. … I did fail at 1 part in my script, I tried to make /home/kronikpillow rollback possible same like it is on @, but failed … Now I’m gonna try the same with @/home if it fails, I’ll just move my 150-pre-user-subvolume into 100-pre-user-subvolume and make my home layout part of the root subvolume… I’ll post an update once I find out as I’m in active testing …

        Regarding other users who couldn’t boot, I noticed in your guide that you only chown & chmod 2 directories, while multiple directory permissions in your /var subvolumes are set incorrectly, for example, gdm should be owned by gdm:gdm, there are others that you set incorrectly but can’t remember which one as I’m on mobile while writing this reply, but I will post my findings about it later today as well, I know this because I compared the permissions of the default install vs the permissions of the subvolumes in their place … Maybe setting correct user and group and chmod permissions will solve the problem

        1. KronikPillow Avatar
          KronikPillow

          another thing that came to my mind is that grub-btrfs now has a kernel flag called grub-btrfs-overlay-fs that allows you to boot a read only var … which could completely solve the users not being able to boot, and the need for /var/lib/AccountService and /var/lib/gdm
          on the other hand, going back to your approach
          you should also chmod 1770 /var/lib/gdm and chown /var/lib/gdm gdm:gdm

    2. Madhu Desai Avatar

      Oh, I forgot about the grub. I’m assuming you’re referring to the ‘sparse file not allowed’ error message. The grub menu auto hide feature is enabled by default in Fedora, and you must disable it anyway so that the grub menu is always visible and you can boot into snapshots at any time.

  14. Vikramaditya Avatar
    Vikramaditya

    Could you please make one guide with snapshot and rollback-support for Fedora’s default (automatic) partition layout i.e root and home as subvolumes of main btrfs volume? Thanks 🙂

    1. Madhu Desai Avatar

      I tried this setup several times. Trust me, I tried at least 20-30 times. But every time I rolled back, I couldn’t mount other subvolumes. It’s most likely related to the ‘SUSE_BTRFS_SNAPSHOT_BOOTING’ option. I’m not sure. But I will try again and see if I missed anything. If I come up with something useful, I’ll definitely write a guide for that setup as well.

      1. Vikramaditya Avatar
        Vikramaditya

        Thanks. I tried twice but couldn’t make it work either. Snapshot booting is not visible under grub although I set it to TRUE by following your guide. I will wait for your updated guide. 🙂

  15. alon Avatar
    alon

    I have solved it via chatgpt’s help 😀
    sudo mkdir /var/lib/libvirt
    then

    #!/bin/bash

    # Get the UUID of your btrfs system root.
    ROOT_UUID=”$(sudo grub2-probe –target=fs_uuid /)”

    # Get the btrfs subvolume mount options from your fstab.
    OPTIONS=”$(grep ‘/var/lib/libvirt/images’ /etc/fstab | awk ‘{print $4}’ | cut -d, -f2-)”

    # Create the subvolume for /var/lib/libvirt/images
    if [[ -d “/var/lib/libvirt/images” ]] ; then
       sudo mv -v “/var/lib/libvirt/images” “/var/lib/libvirt/images-old”
       sudo btrfs subvolume create “/var/lib/libvirt/images”
       sudo cp -ar “/var/lib/libvirt/images-old/.” “/var/lib/libvirt/images/”
    else
       sudo btrfs subvolume create “/var/lib/libvirt/images”
    fi
    sudo restorecon -RF “/var/lib/libvirt/images”
    printf “%-41s %-24s %-5s %-s %-s\n” \
       “UUID=${ROOT_UUID}” \
       “/var/lib/libvirt/images” \
       “btrfs” \
       “subvol=/var/lib/libvirt/images,${OPTIONS}” \
       “0 0” | \
       sudo tee -a /etc/fstab

    1. Madhu Desai Avatar

      I had no idea ChatGPT could do this as well. 😲😲

  16. alon Avatar
    alon

    also;

    sudo btrfs subvolume list /
    no any /var/lib/libvirt/images
    your script cannot create the sv for my side, others okay but this one.

    sudo chattr -R +C /var/lib/libvirt/images
    chattr: No such file or directory while trying to stat /var/lib/libvirt/images

    1. Madhu Desai Avatar

      I believe the directory /var/lib/libvirt/images is only created when ‘Fedora Workstation’ with GNOME is installed. So, before running the script, you should first create a directory:
      # mkdir -vp /var/lib/libvirt

  17. alon Avatar
    alon

    which partr differs for KDE? And I mostly use Brave + Vivaldi browsers which part should change?

    1. Madhu Desai Avatar

      For Brave:
      /home/$USER/.cache/BraveSoftware
      /home/$USER/.config/BraveSoftware

      For Vivaldi:
      /home/$USER/.config/vivaldi

      GNOME uses gdm (/var/lib/gdm). It’s most likely sddm (/var/lib/sddm) for KDE. But I’m not certain. Please double-check.

  18. babs Avatar
    babs

    Why not enable timeline for home?

    1. Madhu Desai Avatar

      You certainly can. However, it is unnecessary. The idea is to always have a working snapshot available in case you mess up with the operating system (/), allowing you to roll back anytime. The /home directory, on the other hand, usually contains large files that take up a lot of space in snapshots. It is not advisable.

  19. Davide Avatar
    Davide

    When will you be able to publish the Fedora 38 with Snapshot and Rollback Support YouTube video?
    Thank you

    1. Madhu Desai Avatar

      I will in the next 2-3 days.

  20. Jonas Avatar
    Jonas

    Thanks a lot for your updated guide! The one with Luks also enabled is still coming?

    Thank you for your work!

    1. Madhu Desai Avatar

      Yes. I’ll most likely post tomorrow. I’ve already completed the testing. Rather than using the Anaconda installer, this one will be installed in the terminal with ‘dnf –installroot’.

Leave a Reply

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