Introduction
The Btrfsfilesystem is believed by some to be the next default filesystem for Linux, replacing the current
de-facto standard filesystem, ext4, used by default in most distributions. It has many advanced features
which are not available in the current standard filesystem, such as copy-on-write capability which maintains a
version of a file at each modification. This allows individual files to be rolled back to previous versions and even
the entire system to be snapshotted and rolled back to a previous state from a snapshot. Also, among other features
that make it increasingly in demand by data centers, it is fault tolerant -- not only at the device level but to an
individual file level, able te repair corrupted files -- as long as the required number of redundant storage devices
are available and configured appropriately.
Ubuntu offers the ZFS filesystem as an option, which has similar fault tolerant features as Btrfs, but
does not have the file level self healing features of Btrfs. While ZFS is an option at installation,
the default filesystem on Ubuntu installations is ext4. Users who want the advanced features of Btrfs
but originally installed with the default ext4 filesystem can easily convert the ext4 filesystem of
the original installation to Btrfs. And if they want the simple system snapshot and rollback management by
Snapper, which can incorporate automatic periodic snapshot creation and cleanup, automatic snapshot creation
at boot, and automatic pre and post snapshots during APT package management transactions, as well as automatic
mounting of the correct subvolume that contains the filesystem hierarchy root because the default Btrfs
subvolume is set by Snapper, a little more effort will yield such as system.
The process, similar to the one described in A Fedora Installation with an openSUSE Style BtrfsSubvolume Layout and Snapper
Intergration for System Snapshots and Rollbacks, involves using btrfs-convert, part of the set of
Btrfs utility progras usually packaged as btrfs-progs, to convert the
ext4 filesystem while offline from either a live USB or another installation on the same computer. The
external Linux used in performing the process for this article was an Arch Linux installation which was installed on
Btrfs with an oenSUSE layout and Snapper integration following the process described in An Arch Linux Installation on a BtrfsFilesystem with Snapper for System Snapshots and
Rollbacks. Because this external Linux was Btrfs based, the btrfs-progs package was already available. If the external Linux is not Btrfs
based, the package must be installed before performing the filesystem conversion.
After the conversion the openSUSE style subvolume layout was created by mounting the converted filesystem from the
external system, moving the directories and files in the filesystem hierarchy root, except those parts of the
hierarchy to be excluded from system snapshots (/opt, /root, /var/cache, etc.) to the desired subvolume. Other
tasks were also necessary to properly configure the system, including setting the default btrfs subvolume,
editing the /etc/fstab file to include the subvolumes containing filesystem hierarchy
paths to be excluded from system snapshots, editing GRUB scripts in /etc/grub.d for
compatibility with automatic mounting of the subvolume containing the filesystem hierarchy root by /etc/fstab without explicitly specifying the subvolume containing the filesystem
hierarchy root as a mount option.
The following graphic helps to illustrates the process and the desired configuration. The right part depicts the
final subvolume configuration, including aspects of the configuration such as the subvolume used as the filesystem
hierarchy root, how this subvolume is mounted, the changes in the subvolume layout as new snapshots are created, and
the effect of rollbacks to the subvolume layout. The left part depicts intermediate states of the system at various
stages in the process.
Figure 1: The Intermediate State of the Subvolume Layout and the Final State of the Subvolume Layout
The process is summarized below, before the full process found later in this article:
-
Part 1: Prepare the Ext4 Filesystem to Be Converted to Btrfs
There must be an adequate amount of free space on the filesystem. If there is not, enlarge the partition, if
possible, or delete package caches or other unnecessary files to create free space. Check for filesystem
fragmentation, as pre-conversion fragmentation will be carried over to the converted filesystem, and defragment
if necessary. Also, the filesystem must also be free of errors, so a filesystem check and repair -- if necessary
-- is required before the conversion.
-
Part 2: Convert the Ext 4 Partition to Btrfs
Use the btrfs-convert program to convert the Filesystem containing the
root of the Ubuntu installation filesystem hierarchy to Btrfs. Then mount the converted filesystem in the
external Linux to view the characteristics of the converted filesystem and to delete the backup subvolume
containing a copy of the preconversion image created by the conversion program.
-
Part 3: Create the Subvolumes for the Desired Subvolume Layout
While the converted Btrfs partition is still mounted from the previous part, create the subvolume to
contain all other subvolumes immediately under the automatically created top-level subvolume, at subvolume path
/@. Also, create the subvolumes to contain filesystem hierarchy paths to be
excluded from system snapshots at subvolume paths /@/@opt, /@/@root, /@/srv, /@/@usrlocal, /@/@varcache, /@/@varlog and, /@/@vartmp. These will eventually
contain, respectively, the filesystem hierarchy paths: /opt, /root, /srv, /usr/local, /var/cache, /var/log and, /var/tmp.
-
Part 4: Move Files from the Top Level Btrfs Subvolume (subvolume path /, subvolume ID 5) to the Newly Created Subvolumes
Move the contents of the top-level subvolume created by the btrfs-convert
command, which also places the root of the filesystem hierarchy and all existing files and directories in this
subvolume to the appropriate subvolumes created in the previous Part. First we move the filesystem hierarchy
paths to be excluded from the system snapshots their respective subvolumes, i.e., /@/@opt, /@/@root, /@/srv, /@/@usrlocal, /@/@varcache, /@/@varlog and, /@/@vartmp. Then move the remaining files, temporarily to the subvolume created to
contain all other subvolumes, subvolume path /@, subvolume ID 257.
-
Part 5: Install Snapper and Create Initial Snapshot Subvolume
Next, chroot into the Ubuntu system and install Snapper. Before the chroot we mount the /@ subvolume to be the root of the choot environment. We also mount the subvolumes
under the chroot root mountpoint, as well as the pseudo filesystems. After the Snapper installation, we
initialize a Snapper configuration, which also automatically creates a subvolume for snapshots under the
subvolume currently mounted as the root of the filesystem (subvolume path /@),
and finally create the initial snapshot subvolume which will contain the root of the filesystem hierarchy at the
end of the process, and until a rollback is performed. Exit the chroot at the end of this step.
-
Part 6: Move Files from Subvolume Path /@ to Subvolume Path /@/.snapshots/1/snapshot
After existing the chroot at the end of the previous step, while the mounts created for the chroot are still
active, move the remaining -- after the move in Part 4 -- files and directories from subvolume path /@ to the initial snapshot subvolume, subvolume path /@/.snapshots/1/snapshot. After this step, our configuration of the subvolume layout
will be complete and as illustrated in the right pane of the figure at the top of the article.
-
Part 7: Modify /etc/fstab to Reflect New Btrfs Filesystem and
Subvolume Layout
Access the Ubuntu installation's /etc/fstab, now in its final home under the
initial snapshot subvolume, from the external Linux through the mount point at /mnt/ubuntu-root/.snapshots/1/snapshot/etc/fstab and modify the mount for the root
filesystem hierarchy. Also, add mountpoints for the snapshots subvolume (at subvoume path /@/.snapshots) as well as mountpoints for the subvolumes used to contain the
filesystem hierarchy paths that are to be excluded from system snapshots.
-
Part 8: Modify GRUB Scripts in /etc/grub.d
Simiar to the above step with respect to the /etc/fstab,
access the GRUB scripts /etc/grub/grub.cfg/10_linux and /etc/grub/grub.cfg/20_linux_xen for compatibility with automatic mounting of the
current snapshot subvolume to the mountpoint of the filesystem hierarchy root through the Btrfs default
subvolume feature.
-
Part 9: Make Directory to Be Used as a Mountpoint for the .snapshots
Subvolume in the Initial Snapshot Subvolume
Make a directory under the initial snapshot subvolume to be used as a mountpoint for the snapshots
subvolume. This directory will correspond to the mountpoint we have already specified for the .snapshots subvolume when we edited the Ubuntu installation's etc/fstab in Part 7.
-
Part 10: Change the Default BtrfsSubvolume from /, Subvolume ID 5 to
the Initial Snapshot Subvolume /@/.snapshots/1/snapshot
Set the Btrfs default subvolume to the initial snapshot subvolume. This will ensure that it is
mounted automatically at / without mount options that explicitly specify the
subvolume. When a rollback is performed with Snapper, it will change the default subvolume to the one it
creates to be used as the new system root, so that it will be mounted automatically.
-
Part 11: Chroot to the Installed System and Reinstall GRUB Firmware, Update GRUB, and Regenerate
Initramfs Reinstall the GRUB firmware to avoid being placed in a GRUB shell when rebooting to the
Ubuntu system at the end of the process. Also, update GRUB so that its configuration reflects the new kernel
image and initial RAM filesystem paths in the initial snapshot subvolume mounted as the root of the filesystem
hierarchy. The initial RAM filesystem must also be regenerated.
-
Part 12: Reboot Into Converted System with BtrfsSubvolume Layout and Working Snapper Configuration
and Make Final Adjustments to System Configuration
Finally, reboot into the Ubuntu system and make final adjustments to the system, such as adjusting the
frequency of and conditions for automatic snapshot creation and cleanup, as well as other related parameters.
Part 1: Prepare
the Ext4 Filesystem to Be converted to Btrfs
Before using the btrfs-convert command, the ext4 filesystem must be in a
suitable state for conversion. The filesystem must be error free; it is recommended to perform a a check and, if
necessary, a repair of the ext4 filesystem with e2fsck command typically
available from a package named e2fsprogs. The filesystem must also have adequate
free space to perform the conversion; btrfs-convert(8) states that although the
necessary free space can not be predicted before the conversion is performed, several GB of free space may be
required per 100GB of filesystem size. It may be helpful to delete unnecessary files, check for fragmentation and
defragment if necessary with the e4defrag command, also available from the e2fsprogs package.
The last requirement is that the filesystem block size must be one that is supported by btrfs-convert, which is the same as a valid value for the mkfs.btrfs --sectorsize
option. The btrfs-convert man page states that this "is typically the system page size (4KiB on
x86_64 machines)", which in my case is the same as the value reported by the tune2fs command.(See Reference 6.)
-
Determine the kernel block device name of the partition to be converted as this will be used as an argument to
the btrfs-convert and any utilities used to prepare the filesystem.
-
Check the filesystem level block size of the ext4 partition to be converted.
tune2fs -l /dev/nvme1n1p7
-
Delete unnecessary files if there isn't an adequate amount of free space on the partition.
-
Determine the level of fragmentation of the ext4 partition to be converted with e4defrag. If so, defragment the filesystem with the same tool. (See Reference 3)
-
Unmount the ext4 filesystem to be converted, if it is mounted, and check the filesystem and repair with
the e2fsck command. (See Reference )
Part 2: Convert the ext4
Root Partition to Btrfs
The actual Ubuntu root ext4 filesystem conversion is very simple and only requires executing the btrfs-convert command from the external Linux while the Ubuntu root partition is
unmounted. The command has numerous options that allow specifying the characteristics of the converted
Btrfs filesystem but can be used without any options to use default options. It only takes one argument
which specifies the block device identification of the partition to be converted.
-
Execute the btrfs-convert command in the external Linux.
100% 18:18:15 USER: brook HOST: ARCH-16ITH6
~ ❯$ sudo btrfs-convert /dev/nvme1n1p7
The output from this command is shown in the left pane of the terminal in the first two images of the following
set of images, the first taken while the command is still running, and the second after the command has
completed.
-
Mount the converted filesystem.
100% 18:40:30 USER: brook HOST: ARCH-16ITH6
~ ❯$ sudo mount /dev/nvme1n1p7 /mnt/ubuntu-root
-
Verify the mount.
100% 18:40:55 USER: brook HOST: ARCH-16ITH6
~ ❯$ mount | grep /mnt
dev/nvme1n1p7 on /mnt/ubuntu-root type btrfs (rw,relatime,ssd,discard=async,space_cache=v2,subvolid=5,subvol=/)
-
View the statistics of the newly converted filesystem with the commands:
btrfs filesystem show
as shown in the following listing
100% 18:42:20 USER: brook HOST: ARCH-16ITH6
~ ❯$ sudo btrfs filesystem show /mnt/ubuntu-root/
Label: 'UBUNTU_ROOT' uuid: 72aaa46b-9109-4c3d-9b63-8c8e3cc7fd43
Total devices 1 FS bytes used 30.72GiB
devid 1 size 72.50GiB used 52.75GiB path /dev/nvme1n1p7
and
btrfs subvolume list
as shown in the following listing
100% 18:42:31 USER: brook HOST: ARCH-16ITH6
~ ❯$ sudo btrfs subvolume list /mnt/ubuntu-root/
ID 256 gen 3 top level 5 path ext2_saved
The contents of the filesystem can be viewed with the ls
command with the mountpoint as an
argument.
The left pane of the terminal displayed in the third image of the following set shows the output of the above
Btrfs commands as well as the directory listing.
-
Delete the backup of the original filesystem image saved in a subvolume named ext2_saved created by btrfs-convert.
100% 18:51:55 USER: brook HOST: ARCH-16ITH6
~ ❯$ sudo btrfs subvolume delete /mnt/ubuntu-root/ext2_saved
[sudo] password for brook:
Delete subvolume 256 (no-commit): '/mnt/ubuntu-root/ext2_saved'
Figures 2a, 2b, and 2c: Converting the Ubuntu Installation's Ext4 Filesystem Hierarchy Root Partition to
Btrfs
The conversion is performed with the btrfs-convert command with an argument identifying the
partition (unmounted) to be converted.
Click on any of the thumbnails to view a larger image.
Part 3: Create the Subvolumes for the Desired Subvolume Layout
In Part 2, after converting the ext4 filesystem to Btrfs, we mounted the partition, specifically the
top level subvolume -- the only subvolume at this point, and viewed the filesystem statistics. We continue working
on the filesystem from our external Linux installation or live ISO.
-
Create a the subvolume that will contain all other subvolumes (subvolume path /@).
100% 18:56:42 USER: brook HOST: ARCH-16ITH6
~ ❯$ sudo btrfs subvolume create -p /mnt/ubuntu-root/@
Create subvolume '/mnt/ubuntu-root/@'
-
Create subvolumes under subvolume path /@ for the filesystem hierarchy paths that
are to be excluded from system snapshots.
100% 18:59:55 USER: brook HOST: ARCH-16ITH6
~ ❯$ sudo btrfs subvolume create -p /mnt/ubuntu-root/@/@opt
Create subvolume '/mnt/ubuntu-root/@/@opt'
100% 19:01:31 USER: brook HOST: ARCH-16ITH6
~ ❯$ sudo btrfs subvolume create -p /mnt/ubuntu-root/@/@root
Create subvolume '/mnt/ubuntu-root/@/@root'
100% 19:01:40 USER: brook HOST: ARCH-16ITH6
~ ❯$ sudo btrfs subvolume create -p /mnt/ubuntu-root/@/@srv
Create subvolume '/mnt/ubuntu-root/@/@srv'
100% 19:01:47 USER: brook HOST: ARCH-16ITH6
~ ❯$ sudo btrfs subvolume create -p /mnt/ubuntu-root/@/@usrlocal
Create subvolume '/mnt/ubuntu-root/@/@usrlocal'
100% 19:01:58 USER: brook HOST: ARCH-16ITH6
~ ❯$ sudo btrfs subvolume create -p /mnt/ubuntu-root/@/@varcache
Create subvolume '/mnt/ubuntu-root/@/@varcache'
100% 19:02:09 USER: brook HOST: ARCH-16ITH6
~ ❯$ sudo btrfs subvolume create -p /mnt/ubuntu-root/@/@varlog
Create subvolume '/mnt/ubuntu-root/@/@varlog'
100% 19:02:16 USER: brook HOST: ARCH-16ITH6
~ ❯$ sudo btrfs subvolume create -p /mnt/ubuntu-root/@/@vartmp
Create subvolume '/mnt/ubuntu-root/@/@vartmp'
-
List the subvolumes.
100% 19:02:24 USER: brook HOST: ARCH-16ITH6
~ ❯$ sudo btrfs subvolume list /mnt/ubuntu-root/
ID 257 gen 1168 top level 5 path @
ID 258 gen 1167 top level 257 path @/@opt
ID 259 gen 1167 top level 257 path @/@root
ID 260 gen 1167 top level 257 path @/@srv
ID 261 gen 1167 top level 257 path @/@usrlocal
ID 262 gen 1168 top level 257 path @/@varcache
ID 263 gen 1168 top level 257 path @/@varlog
ID 264 gen 1168 top level 257 path @/@vartmp
-
View the directory listing of the Ubuntu root partition mounted in the external Linux. Because it is a
filesystem the mount is of a specific subvolume, in this case the top-level subvolume automatically created at
filesystem creation or conversion to Btrfs.
100% 19:06:54 USER: brook HOST: ARCH-16ITH6
~ ❯$ ls -la /mnt/ubuntu-root
total 32
drwxr-xr-x 1 root root 238 Oct 11 18:59 ./
drwxr-xr-x 1 root root 22 Oct 10 17:16 ../
drwxr-xr-x 1 root root 90 Oct 11 19:02 '@'/
lrwxrwxrwx 1 root root 7 May 27 2022 bin -> usr/bin/
drwxr-xr-x 1 root root 492 Oct 10 19:20 boot/
drwxr-xr-x 1 root root 0 May 27 2022 cdrom/
drwxr-xr-x 1 root root 128 Apr 19 2022 dev/
drwxr-xr-x 1 root root 5084 Oct 10 19:20 etc/
drwxr-xr-x 1 root root 20 Oct 10 18:21 home/
-rw------- 1 root root 64 Oct 10 19:08 i7lp616G-el
lrwxrwxrwx 1 root root 7 May 27 2022 lib -> usr/lib/
lrwxrwxrwx 1 root root 9 Oct 3 17:54 lib32 -> usr/lib32/
lrwxrwxrwx 1 root root 9 May 27 2022 lib64 -> usr/lib64/
lrwxrwxrwx 1 root root 10 May 27 2022 libx32 -> usr/libx32/
drwx------ 1 root root 0 May 27 2022 lost+found/
drwxr-xr-x 1 root root 44 Jul 10 2023 media/
drwxr-xr-x 1 root root 42 Nov 24 2023 mnt/
drwxr-xr-x 1 root root 106 Oct 3 18:32 opt/
drwxr-xr-x 1 root root 0 Apr 18 2022 proc/
drwx------ 1 root root 256 Oct 11 18:03 root/
drwxr-xr-x 1 root root 284 May 27 2022 run/
lrwxrwxrwx 1 root root 8 May 27 2022 sbin -> usr/sbin/
drwxr-xr-x 1 root root 18 May 26 2023 snap/
drwxr-xr-x 1 root root 0 Apr 19 2022 srv/
drwxr-xr-x 1 root root 0 Apr 18 2022 sys/
drwxrwxrwt 1 root root 384 Oct 10 19:20 tmp/
drwxr-xr-x 1 root root 116 Dec 2 2023 usr/
drwxr-xr-x 1 root root 130 Oct 3 18:18 var/
-rw------- 1 root root 64 Oct 3 18:13 zNUV1bYp-el
Note the @/ directory which allows us to access the newly created /@ subvolume.
-
We can view the contents of this directory.
100% 19:12:52 USER: brook HOST: ARCH-16ITH6
~ ❯$ ls -la /mnt/ubuntu-root/@
total 0
drwxr-xr-x 1 root root 90 Oct 11 19:02 ./
drwxr-xr-x 1 root root 238 Oct 11 18:59 ../
drwxr-xr-x 1 root root 0 Oct 11 19:01 '@opt'/
drwxr-xr-x 1 root root 0 Oct 11 19:01 '@root'/
drwxr-xr-x 1 root root 0 Oct 11 19:01 '@srv'/
drwxr-xr-x 1 root root 0 Oct 11 19:01 '@usrlocal'/
drwxr-xr-x 1 root root 0 Oct 11 19:02 '@varcache'/
drwxr-xr-x 1 root root 0 Oct 11 19:02 '@varlog'/
drwxr-xr-x 1 root root 0 Oct 11 19:02 '@vartmp'/
As of now, these directories (and their corresponding subvolumes) are empty. In the next part, we will move the
contents of the respective filesystem hierarchy paths to the subvolumes.
Part 4: Move Files from the Top Level BtrfsSubvolume (subvolume path
/, subvolume ID 5) to the Newly Created Subvolumes
In this part, we will move the contents of the filesystem hierarchy paths /opt,
/root, /srv, /usr/local, /var/cache, /var/log and, /var/tmp to the respective subvolumes
created in the last part to contain them, respectively, /@/@opt, /@/@root, /@/srv, /@/@usrlocal, /@/@varcache, /@/@varlog and, /@/@vartmp. The files and directories
under these paths will be excluded from system snapshots and remain in these subvolumes in the final system.
We will then move the remaining contents of the top-level subvolume (subvolume path /, subvolume ID 5) to the other subvolume created in the previous step (subvolume path
/@, subvolume ID 257). This is an intermediate step before moving these files and
directories to their final destination in the initial snapshot subvolume in Part 6, after creating the subvolume
for the initial snapshot in Part 5.
-
It was necessary to switch to root when performing this process at this point
with the external Linux used in this process.
100% 19:15:00 USER: brook HOST: ARCH-16ITH6
PCD: 12s ~ ❯$ su
Password:
-
Move the contents of filesystem hierarchy path /opt, currently at subvolume path
/ in the external Linux path /mnt/ubuntu-root/opt
to the @opt subvolume, which in the external Linux is at path /mnt/ubuntu-root/@/@opt/.
[root@ARCH-16ITH6 brook]# mv -v /mnt/ubuntu-root/opt/* /mnt/ubuntu-root/@/@opt/
created directory '/mnt/ubuntu-root/@/@opt/firefox-beta'
copied '/mnt/ubuntu-root/opt/firefox-beta/application.ini' -> '/mnt/ubuntu-root/@/@opt/firefox-beta/application.ini'
copied '/mnt/ubuntu-root/opt/firefox-beta/libnss3.so' -> '/mnt/ubuntu-root/@/@opt/firefox-beta/libnss3.so'
copied '/mnt/ubuntu-root/opt/firefox-beta/update-settings.ini' -> '/mnt/ubuntu-root/@/@opt/firefox-beta/update-settings.ini'
... truncated ...
-
Move the contents of filesystem hierarchy path /root, currently at subvolume path
/ in the external Linux path /mnt/ubuntu-root/root
to the @root subvolume, which in the external Linux is at path /mnt/ubuntu-root/@/@opt/.
[root@ARCH-16ITH6 brook]# mv -v /mnt/ubuntu-root/root/* /mnt/ubuntu-root/@/@root/
... truncated ...
We can confirm all files were moved from /mnt/ubuntu-root/root to /mnt/ubuntu-root/@/@root (from within subvolume path
to subvolume /@/@root in terms of the Ubuntu's new Btrfs partition):
[root@ARCH-16ITH6 brook]# ls -la /mnt/ubuntu-root/@/@root
total 36
drwxr-xr-x 1 root root 256 Oct 11 19:19 .
drwxr-xr-x 1 root root 90 Oct 11 19:02 ..
-rw------- 1 root root 1181 Oct 11 18:06 .bash_history
-rw-r--r-- 1 root root 3106 Oct 15 2021 .bashrc
drwx------ 1 root root 238 Nov 23 2023 .cache
drwx------ 1 root root 18 Mar 14 2023 .config
drwx------ 1 root root 22 Feb 25 2023 .dbus
drwx------ 1 root root 34 May 24 2022 .launchpadlib
-rw------- 1 root root 44 Oct 11 18:03 .lesshst
drwxr-xr-x 1 root root 20 Nov 27 2023 .local
-rw-r--r-- 1 root root 161 Jul 9 2019 .profile
drwx------ 1 root root 84 May 27 2022 snap
drwx------ 1 root root 0 May 26 2023 .ssh
-rw-r--r-- 1 root root 0 Mar 8 2023 .sudo_as_admin_successful
drwxr-xr-x 1 root root 20 Dec 2 2023 .vim
-rw------- 1 root root 13339 Dec 2 2023 .viminfo
-rw-r--r-- 1 root root 165 Nov 24 2023 .wget-hsts
Note that in this case all files, including hidden files, have been moved, However, depending on the shell and
the external Linux's shell configuration, hidden files may not be moved when using mv
with the
*
glob. (See Reference 7.)
-
Move the contents of filesystem hierarchy path /usr/local, currently at subvolume
path / in the external Linux path /mnt/ubuntu-root/usr/local to the @usrlocal subvolume,
which in the external Linux is at path /mnt/ubuntu-root/@/@usrlocal/.
[root@ARCH-16ITH6 brook]# mv -v /mnt/ubuntu-root/usr/local/* /mnt/ubuntu-root/@/@usrlocal/
... truncated ...
-
Move the contents of filesystem hierarchy path /var/cache, currently at subvolume
path / in the external Linux path /mnt/ubuntu-root/var/cache to the @varcache subvolume,
which in the external Linux is at path /mnt/ubuntu-root/@/@varcache/.
[root@ARCH-16ITH6 brook]# mv -v /mnt/ubuntu-root/var/cache/* /mnt/ubuntu-root/@/@varcache/
... truncated ...
-
Move the contents of filesystem hierarchy path /var/log, currently at subvolume
path / in the external Linux path /mnt/ubuntu-root/var/log to the @varlog subvolume,
which in the external Linux is at path /mnt/ubuntu-root/@/@varlog/.
[root@ARCH-16ITH6 brook]# mv -v /mnt/ubuntu-root/var/log/* /mnt/ubuntu-root/@/@varlog/
... truncated ...
-
Move the contents of filesystem hierarchy path /var/tmp, currently at subvolume
path / in the external Linux path /mnt/ubuntu-root/var/tmp to the @vartmp subvolume,
which in the external Linux is at path /mnt/ubuntu-root/@/@vartmp/.
[root@ARCH-16ITH6 brook]# mv -v /mnt/ubuntu-root/var/tmp/* /mnt/ubuntu-root/@/@vartmp/
... truncated ...
-
List the contents of the top-level subvolume, subvolume path / currently mounted
in the external Linux at /mnt/ubuntu-root
[root@ARCH-16ITH6 brook]# ls -la /mnt/ubuntu-root/
total 32
drwxr-xr-x 1 root root 238 Oct 11 18:59 .
drwxr-xr-x 1 root root 22 Oct 10 17:16 ..
drwxr-xr-x 1 root root 90 Oct 11 19:02 @
lrwxrwxrwx 1 root root 7 May 27 2022 bin -> usr/bin
drwxr-xr-x 1 root root 492 Oct 10 19:20 boot
drwxr-xr-x 1 root root 0 May 27 2022 cdrom
drwxr-xr-x 1 root root 128 Apr 19 2022 dev
drwxr-xr-x 1 root root 5084 Oct 10 19:20 etc
drwxr-xr-x 1 root root 20 Oct 10 18:21 home
-rw------- 1 root root 64 Oct 10 19:08 i7lp616G-el
lrwxrwxrwx 1 root root 7 May 27 2022 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Oct 3 17:54 lib32 -> usr/lib32
lrwxrwxrwx 1 root root 9 May 27 2022 lib64 -> usr/lib64
lrwxrwxrwx 1 root root 10 May 27 2022 libx32 -> usr/libx32
drwx------ 1 root root 0 May 27 2022 lost+found
drwxr-xr-x 1 root root 44 Jul 10 2023 media
drwxr-xr-x 1 root root 42 Nov 24 2023 mnt
drwxr-xr-x 1 root root 0 Oct 11 19:16 opt
drwxr-xr-x 1 root root 0 Apr 18 2022 proc
drwx------ 1 root root 0 Oct 11 19:19 root
drwxr-xr-x 1 root root 284 May 27 2022 run
lrwxrwxrwx 1 root root 8 May 27 2022 sbin -> usr/sbin
drwxr-xr-x 1 root root 18 May 26 2023 snap
drwxr-xr-x 1 root root 0 Apr 19 2022 srv
drwxr-xr-x 1 root root 0 Apr 18 2022 sys
drwxrwxrwt 1 root root 384 Oct 10 19:20 tmp
drwxr-xr-x 1 root root 116 Dec 2 2023 usr
drwxr-xr-x 1 root root 130 Oct 3 18:18 var
-rw------- 1 root root 64 Oct 3 18:13 zNUV1bYp-el
-
Remove the directories at filesystem paths that are to be excluded from the system snapshots. Since we moved
them in Steps 2 - 7, above, they are now empty. This is evident in the above listing for /opt and /root.
[root@ARCH-16ITH6 brook]# rm -r /mnt/ubuntu-root/{opt,root,srv,usr/local,var/cache,var/log,var/tmp}
-
For comparison with the state after the next step, list the contents of the /@
subvolume in the Ubuntu Btrfsfilesystem, currently accessible in the external Linux at /mnt/ubuntu-root/@
[root@ARCH-16ITH6 brook]# ls -la /mnt/ubuntu-root/@
total 0
drwxr-xr-x 1 root root 90 Oct 11 19:02 .
drwxr-xr-x 1 root root 218 Oct 11 19:36 ..
drwxr-xr-x 1 root root 106 Oct 11 19:16 @opt
drwxr-xr-x 1 root root 256 Oct 11 19:19 @root
drwxr-xr-x 1 root root 0 Oct 11 19:01 @srv
drwxr-xr-x 1 root root 86 Oct 11 19:20 @usrlocal
drwxr-xr-x 1 root root 306 Oct 11 19:23 @varcache
drwxr-xr-x 1 root root 2808 Oct 11 19:24 @varlog
drwxr-xr-x 1 root root 0 Oct 11 19:02 @vartmp
Note that it is empty of actual files and directories. The output shows the subvolumes represented as
directories since the top level subvolume, subvolume / is mounted in the external
Linux at /mnt/ubuntu-root.
-
Move the remaining contents of top level subvolume (subvolume path /) to
subvolume path /@.
[root@ARCH-16ITH6 brook]# mv /mnt/ubuntu-root/* /mnt/ubuntu-root/@/
mv: cannot move '/mnt/ubuntu-root/@' to a subdirectory of itself, '/mnt/ubuntu-root/@/@'
The error displayed does not matter; the remaining contents of /mnt/ubuntu-root
have been moved to /mnt/ubuntu-root/@ in terms of the external Linux filesystem
hierarchy, and in terms of the Btrfssubvolumes on the Ubuntu partition, /
to /@. The following listing confirms this.
[root@ARCH-16ITH6 brook]# ls -la /mnt/ubuntu-root/@
total 32
drwxr-xr-x 1 root root 306 Oct 11 19:41 .
drwxr-xr-x 1 root root 2 Oct 11 19:41 ..
lrwxrwxrwx 1 root root 7 May 27 2022 bin -> usr/bin
drwxr-xr-x 1 root root 492 Oct 10 19:20 boot
drwxr-xr-x 1 root root 0 May 27 2022 cdrom
drwxr-xr-x 1 root root 128 Apr 19 2022 dev
drwxr-xr-x 1 root root 5084 Oct 10 19:20 etc
drwxr-xr-x 1 root root 20 Oct 10 18:21 home
-rw------- 1 root root 64 Oct 10 19:08 i7lp616G-el
lrwxrwxrwx 1 root root 7 May 27 2022 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Oct 3 17:54 lib32 -> usr/lib32
lrwxrwxrwx 1 root root 9 May 27 2022 lib64 -> usr/lib64
lrwxrwxrwx 1 root root 10 May 27 2022 libx32 -> usr/libx32
drwx------ 1 root root 0 May 27 2022 lost+found
drwxr-xr-x 1 root root 44 Jul 10 2023 media
drwxr-xr-x 1 root root 42 Nov 24 2023 mnt
drwxr-xr-x 1 root root 106 Oct 11 19:16 @opt
drwxr-xr-x 1 root root 0 Apr 18 2022 proc
drwxr-xr-x 1 root root 256 Oct 11 19:19 @root
drwxr-xr-x 1 root root 284 May 27 2022 run
lrwxrwxrwx 1 root root 8 May 27 2022 sbin -> usr/sbin
drwxr-xr-x 1 root root 18 May 26 2023 snap
drwxr-xr-x 1 root root 0 Oct 11 19:01 @srv
drwxr-xr-x 1 root root 0 Apr 18 2022 sys
drwxrwxrwt 1 root root 384 Oct 10 19:20 tmp
drwxr-xr-x 1 root root 106 Oct 11 19:36 usr
drwxr-xr-x 1 root root 86 Oct 11 19:20 @usrlocal
drwxr-xr-x 1 root root 108 Oct 11 19:36 var
drwxr-xr-x 1 root root 306 Oct 11 19:23 @varcache
drwxr-xr-x 1 root root 2808 Oct 11 19:24 @varlog
drwxr-xr-x 1 root root 0 Oct 11 19:02 @vartmp
-rw------- 1 root root 64 Oct 3 18:13 zNUV1bYp-el
-
Unmount the Ubuntu partition.
[root@ARCH-16ITH6 brook]# umount --recursive /mnt/ubuntu-root
Part 5: Install Snapper and Create Initial Snapshot Subvolume
In this part, we will install Snapper and initialize its configuration, which will automatically create a
subvolume for snapshots named .snapshots directly under the subvolume mounted at
the filesystem hierarchy root when the initialization command is executed; the subvolume path of this subvolume
will be at /@/.snapshots. Then we will create the initial snapshot subvolume at
subvolume path /@/.snapshots/1/snapshot, which at the end of the process will
contain the Ubuntu installation's filesystem hierarchy root, except the paths that are excluded from system
snapshots which will be in their own respective subvolumes, e.g., /opt at /@/@opt, /root at /@/@root, etc.
To do this we will chroot into the installed Ubuntu system, mounting the /@
subvolume -- which currently contains the filesystem hierarchy root of the Ubuntu installation after the actions
in Part 4 -- at /mnt/ubuntu-root and the other subvolumes at appropriate
mountpoints, e.g., /@/@opt at /mnt/ubuntu-root/opt.
-
Mount the new /@ subvolume, the other new subvolumes created for filesystem
hieraarchy paths to be excluded from snapshots, the EFI System Partition and all of the pseudo filesystems
needed for the chroot.
[root@ARCH-16ITH6 brook]# mount UUID="72aaa46b-9109-4c3d-9b63-8c8e3cc7fd43" /mnt/ubuntu-root -o subvol=/@
[root@ARCH-16ITH6 brook]# mount UUID="dbe875a9-94a3-4831-8697-0e869ec4a65f" /mnt/ubuntu-root/home
[root@ARCH-16ITH6 brook]# mount UUID="CEFD-1322" /mnt/ubuntu-root/boot/efi
[root@ARCH-16ITH6 brook]# mount -t proc /proc /mnt/ubuntu-root/proc/
[root@ARCH-16ITH6 brook]# mount -t sysfs /sys /mnt/ubuntu-root/sys/
[root@ARCH-16ITH6 brook]# mount -o bind /dev /mnt/ubuntu-root/dev/
[root@ARCH-16ITH6 brook]# mount -o bind /dev/pts /mnt/ubuntu-root/dev/pts/
[root@ARCH-16ITH6 brook]# mount -o bind /run /mnt/ubuntu-root/run/
[root@ARCH-16ITH6 brook]# mount -o bind /sys/firmware/efi/efivars /mnt/ubuntu-root/sys/firmware/efi/efivars/
[root@ARCH-16ITH6 brook]# mkdir /mnt/ubuntu-root/{opt,root,srv,usr/local,var/cache,var/log,var/tmp}
[root@ARCH-16ITH6 brook]# mount UUID="72aaa46b-9109-4c3d-9b63-8c8e3cc7fd43" /mnt/ubuntu-root/opt -o subvol=/@/@opt
[root@ARCH-16ITH6 brook]# mount UUID="72aaa46b-9109-4c3d-9b63-8c8e3cc7fd43" /mnt/ubuntu-root/root -o subvol=/@/@root
[root@ARCH-16ITH6 brook]# mount UUID="72aaa46b-9109-4c3d-9b63-8c8e3cc7fd43" /mnt/ubuntu-root/srv -o subvol=/@/@srv
[root@ARCH-16ITH6 brook]# mount UUID="72aaa46b-9109-4c3d-9b63-8c8e3cc7fd43" /mnt/ubuntu-root/var/cache -o subvol=/@/@varcache
[root@ARCH-16ITH6 brook]# mount UUID="72aaa46b-9109-4c3d-9b63-8c8e3cc7fd43" /mnt/ubuntu-root/var/log -o subvol=/@/@varlog
[root@ARCH-16ITH6 brook]# mount UUID="72aaa46b-9109-4c3d-9b63-8c8e3cc7fd43" /mnt/ubuntu-root/var/tmp -o subvol=/@/@vartmp
[root@ARCH-16ITH6 brook]# mount UUID="72aaa46b-9109-4c3d-9b63-8c8e3cc7fd43" /mnt/ubuntu-root/usr/local -o subvol=/@/@usrlocal
-
Copy /etc/resolv.conf from the external Linux chroot host to the installed
Ubuntu, the installation into which we are chrooting.
[root@ARCH-16ITH6 brook]# cp /etc/resolv.conf /mnt/ubuntu-root/etc/resolv.conf
If the Ubuntu installation uses systemd-resolved service, /etc/resolv.conf will be a symbolic link to /run/systemd/resolv/stub-resolv.conf. It will be necessary to unlink the file with
unlink /mnt/ubuntu-root/etc/resolv.conf
-
Chroot into the installed Ubuntu system.
[root@ARCH-16ITH6 brook]# chroot /mnt/ubuntu-root /bin/bash
-
Verify the chroot by viewing the contents of /etc/os-release. The external Linux
used for this process was Arch, so the output in the following listing confirms the chroot is active.
root@ARCH-16ITH6:/# cat /etc/os-release
PRETTY_NAME="Ubuntu 24.10"
NAME="Ubuntu"
VERSION_ID="24.10"
VERSION="24.10 (Oracular Oriole)"
VERSION_CODENAME=oracular
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=oracular
LOGO=ubuntu-logo
-
Install Snapper.
root@ARCH-16ITH6:/# apt install snapper
The following package was automatically installed and is no longer required:
libiw30t64
Use 'apt autoremove' to remove it.
Installing:
snapper
Installing dependencies:
libbtrfs0t64 libsnapper7t64
Summary:
Upgrading: 0, Installing: 3, Removing: 0, Not Upgrading: 1
Download size: 761 kB
Space needed: 2,930 kB / 45.8 GB available
Continue? [Y/n]
Get:1 http://us.archive.ubuntu.com/ubuntu oracular/main amd64 libbtrfs0t64 amd64 6.6.3-1.2 [13.5 kB]
Get:2 http://us.archive.ubuntu.com/ubuntu oracular/universe amd64 libsnapper7t64 amd64 0.10.6-1.1build1 [307 kB]
Get:3 http://us.archive.ubuntu.com/ubuntu oracular/universe amd64 snapper amd64 0.10.6-1.1build1 [441 kB]
Fetched 761 kB in 1s (917 kB/s)
Selecting previously unselected package libbtrfs0t64:amd64.
(Reading database ... 426979 files and directories currently installed.)
Preparing to unpack .../libbtrfs0t64_6.6.3-1.2_amd64.deb ...
Unpacking libbtrfs0t64:amd64 (6.6.3-1.2) ...
Selecting previously unselected package libsnapper7t64:amd64.
Preparing to unpack .../libsnapper7t64_0.10.6-1.1build1_amd64.deb ...
Unpacking libsnapper7t64:amd64 (0.10.6-1.1build1) ...
Selecting previously unselected package snapper.
Preparing to unpack .../snapper_0.10.6-1.1build1_amd64.deb ...
Unpacking snapper (0.10.6-1.1build1) ...
Setting up libbtrfs0t64:amd64 (6.6.3-1.2) ...
Setting up libsnapper7t64:amd64 (0.10.6-1.1build1) ...
Setting up snapper (0.10.6-1.1build1) ...
Created symlink '/etc/systemd/system/timers.target.wants/snapper-boot.timer' →
'/usr/lib/systemd/system/snapper-boot.timer'.
Created symlink '/etc/systemd/system/timers.target.wants/snapper-cleanup.timer' →
'/usr/lib/systemd/system/snapper-cleanup.timer'.
Created symlink '/etc/systemd/system/timers.target.wants/snapper-timeline.timer' →
'/usr/lib/systemd/system/snapper-timeline.timer'.
Created symlink '/etc/systemd/system/sysinit.target.wants/snapperd.service' →
'/usr/lib/systemd/system/snapperd.service'.
Running in chroot, ignoring command 'daemon-reload'
Running in chroot, ignoring command 'is-active'
snapper-boot.service is a disabled or a static unit, not starting it.
Running in chroot, ignoring command 'is-active'
Running in chroot, ignoring command 'is-active'
snapper-cleanup.service is a disabled or a static unit, not starting it.
Running in chroot, ignoring command 'is-active'
Running in chroot, ignoring command 'is-active'
snapper-timeline.service is a disabled or a static unit, not starting it.
Running in chroot, ignoring command 'is-active'
Running in chroot, ignoring command 'is-active'
Running in chroot, ignoring command 'start'
Processing triggers for man-db (2.12.1-3) ...
Processing triggers for dbus (1.14.10-4ubuntu5) ...
Processing triggers for libc-bin (2.40-1ubuntu3) ...
-
List the subvolumes for comparison of the current state to the state after the next step.
root@ARCH-16ITH6:/# btrfs subvolume list /
ID 257 gen 1192 top level 5 path @
ID 258 gen 1171 top level 257 path @opt
ID 259 gen 1190 top level 257 path @root
ID 260 gen 1177 top level 257 path @srv
ID 261 gen 1192 top level 257 path @usrlocal
ID 262 gen 1193 top level 257 path @varcache
ID 263 gen 1192 top level 257 path @varlog
ID 264 gen 1179 top level 257 path @vartmp
-
Create the Snapper configuration for managing snapshots of the subvolume mounted at the filesystem
hierarchy root.
root@ARCH-16ITH6:/# snapper --no-dbus -c root create-config /
-
List the subvolumes to compare to the previous state. Now, after the Snapper configuration command, there
is a new subvolume called .snapshots under the /@
subvolume.
root@ARCH-16ITH6:/# btrfs subvolume list /
ID 257 gen 1192 top level 5 path @
ID 258 gen 1171 top level 257 path @opt
ID 259 gen 1190 top level 257 path @root
ID 260 gen 1177 top level 257 path @srv
ID 261 gen 1192 top level 257 path @usrlocal
ID 262 gen 1193 top level 257 path @varcache
ID 263 gen 1192 top level 257 path @varlog
ID 264 gen 1179 top level 257 path @vartmp
ID 265 gen 1194 top level 257 path .snapshots
-
Create initial snapshot subvolume under /@/.snapshots.
root@ARCH-16ITH6:/# btrfs subvolume create -p /.snapshots/1/snapshot
Create subvolume '/.snapshots/1/snapshot'
-
List the subvolumes. There is a new subvolume at subvolume path /@/.snapshots/1/snapshot.
root@ARCH-16ITH6:/# btrfs subvolume list /
ID 257 gen 1194 top level 5 path @
ID 258 gen 1171 top level 257 path @opt
ID 259 gen 1190 top level 257 path @root
ID 260 gen 1177 top level 257 path @srv
ID 261 gen 1192 top level 257 path @usrlocal
ID 262 gen 1193 top level 257 path @varcache
ID 263 gen 1192 top level 257 path @varlog
ID 264 gen 1179 top level 257 path @vartmp
ID 265 gen 1194 top level 257 path .snapshots
ID 266 gen 1195 top level 265 path .snapshots/1/snapshot
-
Exit the chroot.
root@ARCH-16ITH6:/# exit
exit
Part 6: Move Files from Subvolume Path /@ to
Subvolume Path /@/.snapshots/1/snapshot
At this point in the process, the contents of the paths /opt, /root, /usr/local, /var/cache, /var/log, and /var/tmp that were in the top-level subvolume immediately after the conversion have
been relocated to their respective subvolumes under subvolume path /@. The
remaining contents of the top-level subvolume were moved temporarily to /@. In this
part we move the contents of /@ to the initial snapshot subvolume, /@/.snapshots/1/snapshot, realizing the desired subvolume layout illustrated in the
right part of the image at the top of the article.
-
Move files from subvolume path /@ to subvolume path /@/.snapshots/1/snapshot. To avoid the errors shown in the output, first unmount the
EFI System Partition and the pseudo filesystems, mounted for the chroot.
[root@ARCH-16ITH6 brook]# mv /mnt/ubuntu-root/* /mnt/ubuntu-root/.snapshots/1/snapshot/
mv: cannot move '/mnt/ubuntu-root/boot/efi' to '/mnt/ubuntu-root/.snapshots/1/snapshot/boot/efi': Device or resource busy
mv: cannot move '/mnt/ubuntu-root/dev' to '/mnt/ubuntu-root/.snapshots/1/snapshot/dev': Device or resource busy
mv: cannot move '/mnt/ubuntu-root/proc' to '/mnt/ubuntu-root/.snapshots/1/snapshot/proc': Device or resource busy
mv: cannot move '/mnt/ubuntu-root/run' to '/mnt/ubuntu-root/.snapshots/1/snapshot/run': Device or resource busy
mv: cannot move '/mnt/ubuntu-root/sys' to '/mnt/ubuntu-root/.snapshots/1/snapshot/sys': Device or resource busy
[root@ARCH-16ITH6 brook]# ls -la /mnt/ubuntu-root /mnt/ubuntu-root/.snapshots/1/snapshot
/mnt/ubuntu-root:
total 0
drwxr-xr-x 1 root root 54 Oct 11 20:32 .
drwxr-xr-x 1 root root 22 Oct 10 17:16 ..
drwxr-xr-x 1 root root 492 Oct 10 19:20 boot
drwxr-xr-x 24 root root 5500 Oct 11 16:50 dev
dr-xr-xr-x 505 root root 0 Oct 11 19:51 proc
drwxr-xr-x 34 root root 960 Oct 11 18:50 run
drwxr-x--- 1 root root 2 Oct 11 20:08 .snapshots
dr-xr-xr-x 13 root root 0 Oct 11 20:14 sys
/mnt/ubuntu-root/.snapshots/1/snapshot:
total 32
drwxr-xr-x 1 root root 300 Oct 11 20:32 .
drwxr-xr-x 1 root root 16 Oct 11 20:08 ..
lrwxrwxrwx 1 root root 7 May 27 2022 bin -> usr/bin
drwxr-xr-x 1 root root 486 Oct 10 19:20 boot
drwxr-xr-x 1 root root 0 May 27 2022 cdrom
drwxr-xr-x 1 root root 5098 Oct 11 20:06 etc
drwxr-xr-x 1 root root 20 Oct 10 18:21 home
-rw------- 1 root root 64 Oct 10 19:08 i7lp616G-el
lrwxrwxrwx 1 root root 7 May 27 2022 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Oct 3 17:54 lib32 -> usr/lib32
lrwxrwxrwx 1 root root 9 May 27 2022 lib64 -> usr/lib64
lrwxrwxrwx 1 root root 10 May 27 2022 libx32 -> usr/libx32
drwx------ 1 root root 0 May 27 2022 lost+found
drwxr-xr-x 1 root root 44 Jul 10 2023 media
drwxr-xr-x 1 root root 42 Nov 24 2023 mnt
drwxr-xr-x 1 root root 106 Oct 11 19:16 @opt
drwxr-xr-x 1 root root 0 Oct 11 19:59 opt
drwxr-xr-x 1 root root 256 Oct 11 19:19 @root
drwxr-xr-x 1 root root 0 Oct 11 19:59 root
lrwxrwxrwx 1 root root 8 May 27 2022 sbin -> usr/sbin
drwxr-xr-x 1 root root 18 May 26 2023 snap
drwxr-xr-x 1 root root 0 Oct 11 19:01 @srv
drwxr-xr-x 1 root root 0 Oct 11 19:59 srv
drwxrwxrwt 1 root root 384 Oct 10 19:20 tmp
drwxr-xr-x 1 root root 116 Oct 11 19:59 usr
drwxr-xr-x 1 root root 86 Oct 11 19:20 @usrlocal
drwxr-xr-x 1 root root 130 Oct 11 19:59 var
drwxr-xr-x 1 root root 306 Oct 11 19:23 @varcache
drwxr-xr-x 1 root root 2808 Oct 11 19:24 @varlog
drwxr-xr-x 1 root root 0 Oct 11 19:02 @vartmp
-rw------- 1 root root 64 Oct 3 18:13 zNUV1bYp-el
[root@ARCH-16ITH6 brook]# ls -la /mnt/ubuntu-root/.* /mnt/ubuntu-root/.snapshots/1/snapshot
/mnt/ubuntu-root/.snapshots:
total 0
drwxr-x--- 1 root root 2 Oct 11 20:08 .
drwxr-xr-x 1 root root 54 Oct 11 20:32 ..
drwxr-xr-x 1 root root 16 Oct 11 20:08 1
/mnt/ubuntu-root/.snapshots/1/snapshot:
total 32
drwxr-xr-x 1 root root 300 Oct 11 20:32 .
drwxr-xr-x 1 root root 16 Oct 11 20:08 ..
lrwxrwxrwx 1 root root 7 May 27 2022 bin -> usr/bin
drwxr-xr-x 1 root root 486 Oct 10 19:20 boot
drwxr-xr-x 1 root root 0 May 27 2022 cdrom
drwxr-xr-x 1 root root 5098 Oct 11 20:06 etc
drwxr-xr-x 1 root root 20 Oct 10 18:21 home
-rw------- 1 root root 64 Oct 10 19:08 i7lp616G-el
lrwxrwxrwx 1 root root 7 May 27 2022 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Oct 3 17:54 lib32 -> usr/lib32
lrwxrwxrwx 1 root root 9 May 27 2022 lib64 -> usr/lib64
lrwxrwxrwx 1 root root 10 May 27 2022 libx32 -> usr/libx32
drwx------ 1 root root 0 May 27 2022 lost+found
drwxr-xr-x 1 root root 44 Jul 10 2023 media
drwxr-xr-x 1 root root 42 Nov 24 2023 mnt
drwxr-xr-x 1 root root 106 Oct 11 19:16 @opt
drwxr-xr-x 1 root root 0 Oct 11 19:59 opt
drwxr-xr-x 1 root root 256 Oct 11 19:19 @root
drwxr-xr-x 1 root root 0 Oct 11 19:59 root
lrwxrwxrwx 1 root root 8 May 27 2022 sbin -> usr/sbin
drwxr-xr-x 1 root root 18 May 26 2023 snap
drwxr-xr-x 1 root root 0 Oct 11 19:01 @srv
drwxr-xr-x 1 root root 0 Oct 11 19:59 srv
drwxrwxrwt 1 root root 384 Oct 10 19:20 tmp
drwxr-xr-x 1 root root 116 Oct 11 19:59 usr
drwxr-xr-x 1 root root 86 Oct 11 19:20 @usrlocal
drwxr-xr-x 1 root root 130 Oct 11 19:59 var
drwxr-xr-x 1 root root 306 Oct 11 19:23 @varcache
drwxr-xr-x 1 root root 2808 Oct 11 19:24 @varlog
drwxr-xr-x 1 root root 0 Oct 11 19:02 @vartmp
-rw------- 1 root root 64 Oct 3 18:13 zNUV1bYp-el
[root@ARCH-16ITH6 brook]# btrfs subvolume list /mnt/ubuntu-root
ID 257 gen 1209 top level 5 path @
ID 258 gen 1171 top level 266 path .snapshots/1/snapshot/@opt
ID 259 gen 1196 top level 266 path .snapshots/1/snapshot/@root
ID 260 gen 1177 top level 266 path .snapshots/1/snapshot/@srv
ID 261 gen 1192 top level 266 path .snapshots/1/snapshot/@usrlocal
ID 262 gen 1193 top level 266 path .snapshots/1/snapshot/@varcache
ID 263 gen 1192 top level 266 path .snapshots/1/snapshot/@varlog
ID 264 gen 1179 top level 266 path .snapshots/1/snapshot/@vartmp
ID 265 gen 1210 top level 257 path .snapshots
ID 266 gen 1211 top level 265 path .snapshots/1/snapshot
-
Correct the error in the previous step.
[root@ARCH-16ITH6 brook]# mv /mnt/ubuntu-root/.snapshots/1/snapshot/@opt /mnt/ubuntu-root/
[root@ARCH-16ITH6 brook]# mv /mnt/ubuntu-root/.snapshots/1/snapshot/@root /mnt/ubuntu-root/
[root@ARCH-16ITH6 brook]# mv /mnt/ubuntu-root/.snapshots/1/snapshot/@srv /mnt/ubuntu-root/
[root@ARCH-16ITH6 brook]# mv /mnt/ubuntu-root/.snapshots/1/snapshot/@usrlocal /mnt/ubuntu-root/
[root@ARCH-16ITH6 brook]# mv /mnt/ubuntu-root/.snapshots/1/snapshot/@varcache /mnt/ubuntu-root/
[root@ARCH-16ITH6 brook]# mv /mnt/ubuntu-root/.snapshots/1/snapshot/@vartmp /mnt/ubuntu-root/
[root@ARCH-16ITH6 brook]# mv /mnt/ubuntu-root/.snapshots/1/snapshot/@varlog /mnt/ubuntu-root/
[root@ARCH-16ITH6 brook]# btrfs subvolume list /mnt/ubuntu-root
ID 257 gen 1212 top level 5 path @
ID 258 gen 1171 top level 257 path @opt
ID 259 gen 1196 top level 257 path @root
ID 260 gen 1177 top level 257 path @srv
ID 261 gen 1192 top level 257 path @usrlocal
ID 262 gen 1193 top level 257 path @varcache
ID 263 gen 1192 top level 257 path @varlog
ID 264 gen 1179 top level 257 path @vartmp
ID 265 gen 1210 top level 257 path .snapshots
ID 266 gen 1212 top level 265 path .ssnapshots/1/snapshot
We can also verify that files that should be in the subvolume and not in the initial snapshot subvolume are
where they should be. For example the contents of what would normally in /var/cache are now in the @varcache subvolume. Later
we will mount this subvolume to /var/cache in /etc/fstab, along with the other subvolumes that should be excluded from the snapshot
subvolume.
[root@ARCH-16ITH6 brook]# ls -la /mnt/ubuntu-root/.snapshots/1/snapshot/var/cache /mnt/ubuntu-root/@varcache
/mnt/ubuntu-root/.snapshots/1/snapshot/var/cache:
total 0
drwxr-xr-x 1 root root 0 Oct 11 19:59 .
drwxr-xr-x 1 root root 130 Oct 11 19:59 ..
/mnt/ubuntu-root/@varcache:
total 0
drwxr-xr-x 1 root root 306 Oct 11 19:23 .
drwxr-xr-x 1 root root 144 Oct 11 20:45 ..
drwxr-xr-x 1 root root 0 May 17 2022 adduser
drwxr-xr-x 1 root root 160 Oct 3 18:18 apparmor
drwxr-xr-x 1 root root 8 Apr 19 2022 app-info
drwxr-xr-x 1 root root 70 Oct 11 20:06 apt
drwxr-xr-x 1 root root 120 Apr 19 2022 cracklib
drwxrwx--- 1 root 7 112 Oct 10 19:08 cups
drwxr-xr-x 1 132 122 0 May 26 2023 cups-browsed
drwxr-xr-x 1 root root 146 Oct 10 19:09 debconf
drwxr-xr-x 1 root root 310 Apr 19 2022 dictionaries-common
drwxr-xr-x 1 root root 695866 Oct 10 19:20 fontconfig
drwxr-xr-x 1 root root 0 Sep 4 2021 fonts
drwxr-xr-x 1 root root 98 Oct 3 18:11 fwupd
drwxr-xr-x 1 129 usbmux 0 Jun 29 2022 fwupdmgr
drwx------ 1 root root 18 Oct 11 20:06 ldconfig
drwxr-xr-x 1 root root 8 May 27 2022 lightdm
drwxr-xr-x 1 6 mail 304 Oct 11 20:06 man
drwxr-xr-x 1 root root 18 Apr 19 2022 PackageKit
drwx------ 1 root root 0 Feb 25 2023 private
drwxr-xr-x 1 root root 0 Mar 31 2023 samba
drwxr-xr-x 1 root root 10 Apr 19 2022 swcatalog
This is the case for the /root
[root@ARCH-16ITH6 brook]# ls -la /mnt/ubuntu-root/.snapshots/1/snapshot/root /mnt/ubuntu-root/@root
/mnt/ubuntu-root/@root:
total 36
drwxr-xr-x 1 root root 256 Oct 11 19:19 .
drwxr-xr-x 1 root root 144 Oct 11 20:45 ..
-rw------- 1 root root 1390 Oct 11 20:12 .bash_history
-rw-r--r-- 1 root root 3106 Oct 15 2021 .bashrc
drwx------ 1 root root 238 Nov 23 2023 .cache
drwx------ 1 root root 18 Mar 14 2023 .config
drwx------ 1 root root 22 Feb 25 2023 .dbus
drwx------ 1 root root 34 May 24 2022 .launchpadlib
-rw------- 1 root root 44 Oct 11 18:03 .lesshst
drwxr-xr-x 1 root root 20 Nov 27 2023 .local
-rw-r--r-- 1 root root 161 Jul 9 2019 .profile
drwx------ 1 root root 84 May 27 2022 snap
drwx------ 1 root root 0 May 26 2023 .ssh
-rw-r--r-- 1 root root 0 Mar 8 2023 .sudo_as_admin_successful
drwxr-xr-x 1 root root 20 Dec 2 2023 .vim
-rw------- 1 root root 13339 Dec 2 2023 .viminfo
-rw-r--r-- 1 root root 165 Nov 24 2023 .wget-hsts
/mnt/ubuntu-root/.snapshots/1/snapshot/root:
total 0
drwxr-xr-x 1 root root 0 Oct 11 19:59 .
drwxr-xr-x 1 root root 210 Oct 11 20:45 ..
The listings of the other excluded subvolumes are not shown, but they are like /var/cache and /root, in their respective subvolumes.
Part 7: Modify /etc/fstab to Reflect New
BtrfsFilesystem and Subvolume Layout
-
Edit the /etc/fstab file by accessing it in the mount at its new location under
the initial snapshot subvolume that will be the new filesystem hierarchy root.
[root@ARCH-16ITH6 brook]# vim /mnt/ubuntu-root/.snapshots/1/snapshot/etc/fstab
After the edit the file should look like the following listing (obtained after rebooting into the converted
Ubuntu system with the subvolume layout configuration completed).
╭─ user: brook // host: UBUNTU-16ITH6 in ~ as 🧙 took 5m4s
╰─λ cat /etc/fstab
# /etc/fstab: static file system information.
#
# Use 'blkid' to print the universally unique identifier for a
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).
#
#
# / was on /dev/nvme0n1p7 during installation
#UUID=be2c6775-9f46-4851-84da-74a979206977 / ext4 errors=remount-ro 0 1
# After conversion to Btrfs
UUID=72aaa46b-9109-4c3d-9b63-8c8e3cc7fd43 / btrfs compress=zstd:3 0 0
# /boot/efi was on /dev/nvme0n1p1 during installation
UUID=CEFD-1322 /boot/efi vfat umask=0077 0 1
# /home was on /dev/nvme1n1p4 during installation
UUID=dbe875a9-94a3-4831-8697-0e869ec4a65f /home ext4 defaults 0 2
# swap was on /dev/nvme1n1p1 during installation
UUID=980ddbbf-9b79-4390-be21-850e62b7ebb2 none swap sw 0 0
# After conversion to Btrfs. New .snapshots subvolume
UUID=72aaa46b-9109-4c3d-9b63-8c8e3cc7fd43 /.snapshots btrfs subvol=@/.snapshots,compress=zstd:3 0 0
# After conversion to Btrfs. New @opt subvolume
UUID=72aaa46b-9109-4c3d-9b63-8c8e3cc7fd43 /opt btrfs subvol=@/@opt,compress=zstd:3 0 0
# After conversion to Btrfs. New @root subvolume
UUID=72aaa46b-9109-4c3d-9b63-8c8e3cc7fd43 /root btrfs subvol=@/@root,compress=zstd:3 0 0
# After conversion to Btrfs. New @srv subvolume
UUID=72aaa46b-9109-4c3d-9b63-8c8e3cc7fd43 /srv btrfs subvol=@/@srv,compress=zstd:3 0 0
# After conversion to Btrfs. New @usrlocal subvolume
UUID=72aaa46b-9109-4c3d-9b63-8c8e3cc7fd43 /usr/local btrfs subvol=@/@usrlocal,compress=zstd:3 0 0
# After conversion to Btrfs. New @varcache subvolume
UUID=72aaa46b-9109-4c3d-9b63-8c8e3cc7fd43 /var/cache btrfs subvol=@/@varcache,compress=zstd:3 0 0
# After conversion to Btrfs. New @varlog subvolume
UUID=72aaa46b-9109-4c3d-9b63-8c8e3cc7fd43 /var/log btrfs subvol=@/@varlog,compress=zstd:3 0 0
# After conversion to Btrfs. New @vartmp subvolume
UUID=72aaa46b-9109-4c3d-9b63-8c8e3cc7fd43 /var/tmp btrfs subvol=@/@vartmp,compress=zstd:3 0 0
############################################################################################################
UUID=4ad30c04-8dc6-4a6b-9052-315a1d22a48f /home/brook/DataEXT4-16ITH6 ext4 defaults 0 2
UUID=3AC1235B3FBAFA8C /home/brook/DataNTFS-16ITH6 ntfs3 uid=1000,gid=100,dmask=022,fmask=133,discard 0 2
UUID=bb03c8fc-c6f8-452d-a28b-360f405b7c97 /home/brook/VMs ext4 defaults 0 2
╭─ user: brook // host: UBUNTU-16ITH6 in ~ as 🧙 took 3ms
╰─λ
The before edit and after edit state of the file from the external Linux at this point in the process is shown
in the following set of images.
Figures 3a and 3b: Editing /etc/fstab
The file is in the subvolume -- in terms of subvolume path -- /@/.snapshots/1/snapshot, which we will be automatically mounted at the
filesystem hierarchy root when we set it as the Btrfsdefault subvolume.
Part 8: Modify GRUB Scripts in /etc/grub.d
The next step is to modify two of the GRUB scripts in /etc/grub.d that are executed
when making the or updating the GRUB configuration file, /etc/grub/grub.cfg by
grub-mkconfig, or in Ubuntu by update-grub,
which actually executes grub-mkconfig. These two scripts set the subvolume to be
used as the root of the filesystem hierarchy in a way that is not compatible with our desired layout and Snapper.
-
Modify the Ubuntu installation's /etc/grub.d/10_linux file by accessing it in the
mount at its new location under the initial snapshot subvolume that will be the new filesystem hierarchy root by
removing the string rootflags=subvol=${rootsubvol} .
[root@ARCH-16ITH6 brook]# vim /mnt/ubuntu-root/.snapshots/1/snapshot/etc/grub.d/10_linux
Figures 4a, 4b, and 4c: Editing /etc/grub.d/10_linux
The above images show the original state of the file, the state of the file as it is being modifyied in vim, and the state of the file after the modification.
-
Modify the Ubuntu installation's /etc/grub.d/20_linux_xen file by accessing it in
the mount at its new location under the initial snapshot subvolume that will be the new filesystem hierarchy
root by removing the string rootflags=subvol=${rootsubvol} .
[root@ARCH-16ITH6 brook]# vim /mnt/ubuntu-root/.snapshots/1/snapshot/etc/grub.d/20_linux_xen
Figures 5a, 5b, and 5c: Editing /etc/grub.d/20_linux_xen
Part 9: Make Directory to Be Used as a Mountpoint for the .snapshots Subvolume in the Initial Snapshot Subvolume
In our final converted Ubuntu system, the snapshots subvolume will be mounted at /.snapshots filesystem hierarchy path. Remember that in Part 7 we have already created
an entry in the Ubuntu installation's /etc/fstab for this mount. We now make a
directory to mount our snapshots subvolume. Because in the final system the fileystem hierarchy root is actually
the subvolume /@/.snapshots/1/snapshot, and because at this point in the process
the Ubuntu installation's /@ subvolume is mounted in the external Linux at /mnt/ubuntu-root, we can make the directory at /mnt/ubuntu-root/.snapshots/1/snapshot/.snapshot. When we reboot into the Ubuntu
system, the snapshots subvolume will be accessible at /.snapshots as intended and
as requied by Snapper.
-
Make the directory for mounting the snapshots subvolume.
[root@ARCH-16ITH6 brook]# mkdir /mnt/ubuntu-root/.snapshots/1/snapshot/.snapshots
Part 10: Change the Default BtrfsSubvolume from /, Subvolume ID 5 to the Initial Snapshot Subvolume /@/.snapshots/1/snapshot
-
View the current default subvolume as set by the btrfs-convert program.
[root@ARCH-16ITH6 brook]# btrfs subvolume get-default /mnt/ubuntu-root
ID 5 (FS_TREE)
-
Get the subvolume ID of the initial snapshots subvolume.
[root@ARCH-16ITH6 brook]# sudo btrfs subvolume list /mnt/ubuntu-root
ID 257 gen 1214 top level 5 path @
ID 258 gen 1216 top level 257 path @opt
ID 259 gen 1216 top level 257 path @root
ID 260 gen 1177 top level 257 path @srv
ID 261 gen 1192 top level 257 path @usrlocal
ID 262 gen 1215 top level 257 path @varcache
ID 263 gen 1215 top level 257 path @varlog
ID 264 gen 1216 top level 257 path @vartmp
ID 265 gen 1210 top level 257 path .snapshots
ID 266 gen 1223 top level 265 path .snapshots/1/snapshot
From the listing we can see the subvolume ID of the initial snapshot subvolume at subvolume path /@/.snapshots/1/snapshot is 266.
-
Set the Btrfsdefault subvolume to subvolume ID 266.
[root@ARCH-16ITH6 brook]# btrfs subvolume set-default 266 /mnt/ubuntu-root
-
Verify that the default subvolume was changed to subvolume ID 266.
[root@ARCH-16ITH6 brook]# btrfs subvolume get-default /mnt/ubuntu-root
ID 266 gen 1223 top level 265 path @/.snapshots/1/snapshot
-
Unmount the Btrfspartition containing the Ubuntu installation.
[root@ARCH-16ITH6 brook]# umount --recursive /mnt/ubuntu-root
-
Verify that the partition and any of the subvolumes are no longer mounted.
[root@ARCH-16ITH6 brook]# mount | grep /mnt
There should not be any output.
Part 11: Chroot to Installed System and Reinstall GRUB Firmware, Update GRUB,
and Regenerate Initramfs
-
In the external Linux installation or the live ISO, mount the initial snapshot subvolume, i.e., subvolume path
/@/snapshots/1/snapshot.
[root@ARCH-16ITH6 brook]# mount UUID="72aaa46b-9109-4c3d-9b63-8c8e3cc7fd43" /mnt/ubuntu-root
-
Verify the mount.
[root@ARCH-16ITH6 brook]# mount | grep /mnt
/dev/nvme1n1p7 on /mnt/ubuntu-root type btrfs (rw,relatime,ssd,discard=async,space_cache=v2,subvolid=266,subvol=/@/.snapshots/1/snapshot)
-
Mount the home partition.
mount UUID="dbe875a9-94a3-4831-8697-0e869ec4a65f" /mnt/ubuntu-root/home
-
Make a mount point for the EFI System Partition and mount it.
[root@ARCH-16ITH6 brook]# mkdir /mnt/ubuntu-root/boot/efi
[root@ARCH-16ITH6 brook]# mount UUID="CEFD-1322" /mnt/ubuntu-root/boot/efi
-
Mount the subvolumes for the excluded filesystem hierarchy paths.
[root@ARCH-16ITH6 brook]# mount UUID="72aaa46b-9109-4c3d-9b63-8c8e3cc7fd43" /mnt/ubuntu-root/opt -o subvol=/@/@opt
[root@ARCH-16ITH6 brook]# mount UUID="72aaa46b-9109-4c3d-9b63-8c8e3cc7fd43" /mnt/ubuntu-root/root -o subvol=/@/@root
[root@ARCH-16ITH6 brook]# mount UUID="72aaa46b-9109-4c3d-9b63-8c8e3cc7fd43" /mnt/ubuntu-root/srv -o subvol=/@/@srv
[root@ARCH-16ITH6 brook]# mount UUID="72aaa46b-9109-4c3d-9b63-8c8e3cc7fd43" /mnt/ubuntu-root/var/cache -o subvol=/@/@varcache
[root@ARCH-16ITH6 brook]# mount UUID="72aaa46b-9109-4c3d-9b63-8c8e3cc7fd43" /mnt/ubuntu-root/var/log -o subvol=/@/@varlog
[root@ARCH-16ITH6 brook]# mount UUID="72aaa46b-9109-4c3d-9b63-8c8e3cc7fd43" /mnt/ubuntu-root/var/tmp -o subvol=/@/@vartmp
[root@ARCH-16ITH6 brook]# mount UUID="72aaa46b-9109-4c3d-9b63-8c8e3cc7fd43" /mnt/ubuntu-root/usr/local -o subvol=/@/@usrlocal
-
Make mountpoints for the pseudo filesystems and mount them.
[root@ARCH-16ITH6 brook]# mkdir -p /mnt/ubuntu-root/{dev,dev/pts,proc,run,sys}
[root@ARCH-16ITH6 brook]# mount -t proc /proc /mnt/ubuntu-root/proc/
[root@ARCH-16ITH6 brook]# mount -t sysfs /sys /mnt/ubuntu-root/sys/
[root@ARCH-16ITH6 brook]# mount -o bind /dev /mnt/ubuntu-root/dev/
[root@ARCH-16ITH6 brook]# mount -o bind /dev/pts /mnt/ubuntu-root/dev/pts/
[root@ARCH-16ITH6 brook]# mount -o bind /run /mnt/ubuntu-root/run/
[root@ARCH-16ITH6 brook]# mount -o bind /sys/firmware/efi/efivars /mnt/ubuntu-root/sys/firmware/efi/efivars/
-
Copy /etc/resolv.conf from the host system to the installed Ubuntu that we will
chroot into.
[root@ARCH-16ITH6 brook]# cp /etc/resolv.conf /mnt/ubuntu-root/etc/resolv.conf
-
Before chrooting, verify the mounted subvolumes.
[root@ARCH-16ITH6 brook]# mount | grep /mnt/ubuntu-root
/dev/nvme1n1p7 on /mnt/ubuntu-root type btrfs (rw,relatime,ssd,discard=async,space_cache=v2,subvolid=266,subvol=/@/.snapshots/1/snapshot)
/dev/nvme0n1p4 on /mnt/ubuntu-root/home type ext4 (rw,relatime)
/dev/nvme1n1p1 on /mnt/ubuntu-root/boot/efi type vfat (rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,utf8,errors=remount-ro)
/dev/nvme1n1p7 on /mnt/ubuntu-root/opt type btrfs (rw,relatime,ssd,discard=async,space_cache=v2,subvolid=258,subvol=/@/@opt)
/dev/nvme1n1p7 on /mnt/ubuntu-root/root type btrfs (rw,relatime,ssd,discard=async,space_cache=v2,subvolid=259,subvol=/@/@root)
/dev/nvme1n1p7 on /mnt/ubuntu-root/srv type btrfs (rw,relatime,ssd,discard=async,space_cache=v2,subvolid=260,subvol=/@/@srv)
/dev/nvme1n1p7 on /mnt/ubuntu-root/var/cache type btrfs (rw,relatime,ssd,discard=async,space_cache=v2,subvolid=262,subvol=/@/@varcache)
/dev/nvme1n1p7 on /mnt/ubuntu-root/var/log type btrfs (rw,relatime,ssd,discard=async,space_cache=v2,subvolid=263,subvol=/@/@varlog)
/dev/nvme1n1p7 on /mnt/ubuntu-root/var/tmp type btrfs (rw,relatime,ssd,discard=async,space_cache=v2,subvolid=264,subvol=/@/@vartmp)
/dev/nvme1n1p7 on /mnt/ubuntu-root/usr/local type btrfs (rw,relatime,ssd,discard=async,space_cache=v2,subvolid=261,subvol=/@/@usrlocal)
/proc on /mnt/ubuntu-root/proc type proc (rw,relatime)
/sys on /mnt/ubuntu-root/sys type sysfs (rw,relatime)
dev on /mnt/ubuntu-root/dev type devtmpfs (rw,nosuid,relatime,size=12158680k,nr_inodes=3039670,mode=755,inode64)
devpts on /mnt/ubuntu-root/dev/pts type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000)
run on /mnt/ubuntu-root/run type tmpfs (rw,nosuid,nodev,relatime,mode=755,inode64)
efivarfs on /mnt/ubuntu-root/sys/firmware/efi/efivars type efivarfs (rw,nosuid,nodev,noexec,relatime)
-
Chroot into the Ubuntu system from the external Linux.
[root@ARCH-16ITH6 brook]# chroot /mnt/ubuntu-root /bin/bash
-
Verify the chroot.
root@ARCH-16ITH6:/# cat /etc/os-release
PRETTY_NAME="Ubuntu 24.10"
NAME="Ubuntu"
VERSION_ID="24.10"
VERSION="24.10 (Oracular Oriole)"
VERSION_CODENAME=oracular
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=oracular
LOGO=ubuntu-logo
-
Swich to root.
root@ARCH-16ITH6:/# su
-
View GRUB variables.
root@ARCH-16ITH6:/# grub-editenv list
Unlike in Fedora (see ), there are no GRUB variables in my Ubuntu installation,
continuously upgraded since 22.04.
-
Re-install GRUB EFI application to ESP.
root@ARCH-16ITH6:/# grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=Ubuntu
Oct 12 20:21:01 UBUNTU-16ITH6 sudo[7250]: brook : TTY=pts/1 ; PWD=/home/brook ; USER=root ; COMMAND=/usr/sbin/grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=Ubuntu
-
Update GRUB configuration.
root@ARCH-16ITH6:/# update-grub
Oct 12 20:34:27 UBUNTU-16ITH6 sudo[9003]: brook : TTY=pts/1 ; PWD=/home/brook ; USER=root ; COMMAND=/usr/sbin/update-grub
-
Update the initramfs.
root@ARCH-16ITH6:/# update-initramfs
Oct 14 22:30:38 UBUNTU-16ITH6 sudo[37896]: brook : TTY=pts/2 ; PWD=/home/brook ; USER=root ; COMMAND=/usr/sbin/update-initramfs -v -c -k all
Figure 6: Reinstalling the GRUB Firmware Application and Updating the GRUB Configuration
Part 12: Reboot Into Converted System with BtrfsSubvolume Layout and
Working Snapper Configuration and Make Final Adjustments to System Configuration
We can now reboot into the converted Ubuntu system, which at this point will have the subvolume layout illustrated
in the diagram at the top of the article, similar to the one used by openSUSE. The initial snapshot subvolume is
automatically mounted at the filesystem hierarchy root / without explicitly
specifying the subvolume identifiers in the /etc/fstab mount options.
Snapper has been configured and is usable, fully able to rollback the system and set the new post-rollback
read-write snapshot it creates as the new subvolume for the filesystem hierarchy root. Snapper is even
integrated into APT (see, below) such that pre and post snapshots are automatically created during package
management transactions.
The following image of some Konsole panes with outputs of various commands show the characteristics of the
system.
Figure 7: The Converted Ubuntu Installation's Btrfs characteristics
APT Integration for Automatic Snapshot Creation Druing Package Management Transactions
Figure 8: Snapper Snapshots on the Converted Ubuntu and Corresponding Subvolumes
Automatic Snapper Snapshot Creation with systemd
Timers
Automatic Snapper Snapshot Cleanup
Testing Rollbacks
Figures 9a, 9b, 9c, and 9d: Performing a Rollback with Snapper