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