Automating File System Snapshots With the Snapper Utility
The Snapper utility can be used to automate the management of file system snapshots. The utility can make it easier to create and delete snapshots, while enabling users to compare the differences between snapshots and revert changes at the file level. For information about the Snapper utility, visit the upstream project page at http://snapper.io/.
Attention:
Snapshots record the state of the file system at a moment in time. As such, it is not possible to guarantee file system integrity for transactional processes that may have been in operation at the time when a snapshot was taken. While utilities like the snapper command may help to capture before and after snapshots for particular operations, such as when using the dnf command, these snapshots are still unaware of other processes that may be running on the system at the same time. If you have processes that may have intensive I/O or memory usage, such as database or middleware applications, you should stop these or ensure that all activity is complete before taking a snapshot to help to reduce the likelihood of data integrity or file system corruption issues within the snapshot.
If not already installed, you can install the Snapper utility from
the ol8_UEKR6
yum repository, by running:
sudo dnf install -y snapper
Creating a Snapper Configuration for a Subvolume
You can use the snapper command to create and manage snapshots of Btrfs subvolumes.
To set up the snapper
configuration for an
existing mounted Btrfs subvolume:
sudo snapper -c config_name create-config -f btrfs fs_name
In the previous command, config_name is the name of the configuration and fs_name is the path of the mounted Btrfs subvolume. Running the command does the following:
-
Adds an entry for config_name to the
/etc/sysconfig/snapper
file. -
Creates the configuration file
/etc/snapper/configs/config_name
. -
Sets up a
.snapshots
subvolume for the snapshots.
For example, the following command sets up the
snapper
configuration for a Btrfs
root
file system:
sudo snapper -c root create-config -f btrfs /
Use the snapper list-configs command to list all of the existing configurations:
sudo snapper list-configs
Config | Subvolume ------------+---------- home_config | /home root | /
Note:
The default snapper SELinux policy allows snapper to manage
snapshots in the /
,
/etc
, /mnt
,
/usr
, /var
and
HOME_ROOT
(usually
/home
). If you create a new directory, for
example /data
or /srv
.
You may need to set the SELinux file context for that
directory so that snapper can create and manage snapshots for
that directory. For example to enable snapper to manage
snapshots on the /data
directory, you can
run:
$ sudo semanage fcontext -a -t snapperd_data_t "/data/\.snapshots(/.*)?" $ sudo restorecon -R -v /data
Creating Different Types of Snapshots
You can create the following three types of snapshots by using the snapper command:
- post
-
You use a post snapshot to record the state of a subvolume after a modification. A post snapshot should always be paired with a pre snapshot that you take immediately before you make the modification.
- pre
-
You use a pre snapshot to record the state of a subvolume before a modification. A pre snapshot should always be paired with a post snapshot that you take immediately after you have completed the modification.
- single
-
You use a single snapshot to record the state of a subvolume but it does not have any association with other snapshots of the subvolume.
To create a single snapshot of a subvolume, use the snapper create command, for example:
sudo snapper -c config_name create --description "description"
Single snapshots are useful for periodic backup purposes and can also be used to create a back-up timeline, as described in Automatic Snapper Snapshots. For actions that are likely to result in specific file system modifications that you may need to roll back, you can use pre and post snapshots to capture snapshots of the file system before and after a transaction.
For example, the following commands create pre and post snapshots of a subvolume:
sudo snapper -c config_name create -t pre -p N
... Modify the subvolume's contents...
sudo snapper -c config_name create -t post --pre-num N -p N'
Specifying the -p option with the
snapper command displays the number of the
snapshot so that you can reference it when creating the post
snapshot or when comparing the contents of the
pre
and post
snapshots.
Note that you can use the --command option
with the snapper command to wrap an operation
with pre
and post
snapshots. For example:
snapper -c root create --command "cd /tmp/build; make install" \ --description "Installing a home built binary"
Pre and post snapshots are frequently used when performing system changes that may be too complex to revert manually, such as when installing or upgrading packages. The DNF snapper plugin that is described in Automatic Snapper Snapshots uses pre and post snapshots in exactly this way and uses the description field to store the DNF transaction that triggered the snapshot.
For example, in the following set of snapshots, you can identify
periodic, single snapshots that are triggered as part of a
timeline and then a pre and post snapshot that is triggered by
the DNF snapper plugin when the vim
package
is installed.
$ sudo snapper -c root list
# | Type | Pre # | Date | User | Cleanup | Description | Userdata ---+--------+-------+------------------------------+------+----------+--------------------------+--------- 0 | single | | | root | | current | 1 | single | | Wed 25 Nov 2020 07:00:30 EST | root | timeline | timeline | 2 | single | | Wed 25 Nov 2020 08:00:01 EST | root | timeline | timeline | 3 | single | | Wed 25 Nov 2020 09:00:01 EST | root | timeline | timeline | 4 | pre | | Wed 25 Nov 2020 09:07:21 EST | root | number | /usr/bin/dnf install vim | 5 | post | 4 | Wed 25 Nov 2020 09:07:25 EST | root | number | /usr/bin/dnf install vim | 6 | single | | Wed 25 Nov 2020 10:00:01 EST | root | timeline | timeline |
Automatic Snapper Snapshots
By default, each snapper configuration
contains settings for a periodic backup, which is controlled by
the TIMELINE_CREATE
configuration variable in
the
/etc/snapper/configs/config_name
file. Automatic snapshots are triggered by a systemd timer unit
that you must enable to allow the timeline to be created:
sudo systemctl enable --now snapper-timeline.timer
A second systemd timer unit handles the cleanup of stale snapshots so that your snapshots remain manageable. You should enable this unit as well, for example:
sudo systemctl enable --now snapper-cleanup.timer
When the systemd timer units are enabled, periodic snapshot
events trigger automatically for every snapper configuration
that has the TIMELINE_CREATE
variable
enabled. If you wish to disable periodic snapshots for a
particular configuration, change the variable value to
no
in the configuration file.
By default, the snapper timeline configuration keeps 10 hourly,
10 daily, 10 monthly, and 10 yearly snapshots. Snapshots are
pruned by the cleanup timer. For busy subvolumes such as the
root
subvolume, you might want to modify
these values to better cater to your requirements. You set these
values by changing the following configuration variables:
TIMELINE_LIMIT_HOURLY="10" TIMELINE_LIMIT_DAILY="10" TIMELINE_LIMIT_WEEKLY="10" TIMELINE_LIMIT_MONTHLY="10" TIMELINE_LIMIT_YEARLY="10"
The cleanup timer also prunes other snapshots to keep the total
number of snapshots reduced. See the
SNAPPER(8)
and
SNAPPER-CONFIGS(5)
manual pages for more
information.
You can install the DNF snapper plugin on a system to automatically trigger pre and post snapshots for DNF transactions. This feature can help you roll back changes in cases where system package upgrades cause a failure that you need to debug or to enable you to analyze which files were modified during an installation or upgrade. Note that this plugin requires no user configuration or interaction to work. To install the plugin, use the following command:
sudo dnf install python3-dnf-plugin-snapper
When installed, a snapshot is triggered for each subsequent DNF transaction. See https://dnf-plugins-extras.readthedocs.io/en/latest/snapper.html for more information.
Working With Btrfs Snapshots by Using Snapper
To list the snapshots that exist for a snapper configuration or subvolume, run:
sudo snapper -c config_name list
To display the files and directories that have been added, removed, or modified between two snapshots, use the status subcommand and specify the numbers of the two snapshots that you want to compare:
sudo snapper -c config_name status N .. N'
To display the differences between the contents of all the files in between two snapshots, use the diff subcommand:
sudo snapper -c config_name diff N .. N'
You can also display the difference in a single file over two snapshots by providing the full path to the file:
sudo snapper -c config_name diff N .. N' /path/to/file
To delete a snapshot, specify its number to the delete subcommand:
sudo snapper -c config_name delete N''
To undo the changes in the subvolume from post snapshot N' to pre snapshot N':
sudo snapper -c config_name undochange N .. N'
Note that undoing a change does not revert the file system to the previous snapshot but it reverts modifications made to existing files in the snapshot. This means that files created after the snapshot was taken continue to remain after an undochange operation. The undochange subcommand does not check data integrity for its changes. You should be careful of using this command without clearly evaluating the implications of the changes that it is likely to make.
For more information, see the snapper(8)
manual page.
You can mount any snapshot generated by snapper just as you would work with any other Btrfs snapshot. You may need to correlate the snapshot volume id with the snapper snapshot number to work out which snapshot you should mount or restore. Run the snapper list command to identify the number of the snapshot you wish to roll back to. For example, to see all pre and post snapshots, to roll back to a snapshot from before a DNF package update was run:
sudo snapper -c root list -t pre-post
Running the previous command produces the following output:
Pre # | Post # | Pre Date | Post Date | Description | Userdata ------+--------+------------------------------+------------------------------+---------------------------------+--------- 4 | 5 | Wed 25 Nov 2020 09:07:21 EST | Wed 25 Nov 2020 09:07:25 EST | /usr/bin/dnf install vim | 127 | 128 | Mon 30 Nov 2020 08:25:42 EST | Mon 30 Nov 2020 08:30:57 EST | /usr/bin/dnf update |
Note that the number of the pre snapshot that we intend to mount is 127 in this case. Use the btrfs subvolume list command to obtain the subvolume ID for the snapper snapshot and use this or the path to the snapshot subvolume to mount the file system, for example:
sudo btrfs subvolume list /|grep .snapshots.*127
The output of the previous command is as follows:
ID 521 gen 11533 top level 268 path .snapshots/127/snapshot
Then, run the following command:
sudo mount -o subvolid=521 /dev/sda2 /mnt
You can also use this information to boot into a snapshot of the root file system. See Mounting Alternate Snapshots as the root File System for more infomration.