Skip to content

Wisp: Snapper Snapshots in the GNOME Top Bar

On most btrfs installations snapper is already running and nobody notices. openSUSE sets it up out of the box; on Fedora, Arch and Debian it is a package away. It takes a snapshot every hour, and with the distribution’s own plugin installed (snapper-zypp-plugin on openSUSE, snap-pac on Arch, the dnf plugin on Fedora) one on either side of every package transaction as well. By the time something breaks there is almost certainly a good copy of the system sitting on the disk.

Getting to it is the part I did not enjoy. I wanted the snapshot list in the top bar and a restore two clicks away, so I wrote Wisp: snapper snapshots in GNOME Shell, listed in a menu in the top bar, with everything snapper can do from the command line reachable from a settings window. This post covers what it does, what has to be installed first, and two things about snapper that bite whether or not you use a GUI for it.

the menu listing two configs, newest snapshots first

The Problem

Reading snapshots back means the command line. To find out what changed since this morning you list the snapshots, read off two numbers, and diff them:

snapper -c root list
snapper -c root status 118..127
snapper -c root -v undochange 118..127 /etc/fstab

That works, and it is exactly what you do not want to be reciting from memory at the moment you actually need it. The alternative was a separate application to install and open. I wanted it in the shell I am already looking at.

The name is the faint light that hangs over a bog at night. A snapshot is the same sort of thing: the shape the system had, still there after the moment it belonged to.

What I Built: snapper snapshots in GNOME Shell

A menu and a settings window, and behind them the whole of snapper rather than a subset of it. From the menu: take a snapshot with a description no cleanup rule will remove, delete one after a confirmation that says exactly what goes, open one in Files and read it as it was. Per snapshot: rename it, mark it important, change its cleanup rule, turn read-only off, and add up what it alone is holding on to.

The part I use most is the diff. Everything that has changed since a snapshot, searchable, and for a package transaction, exactly what that transaction changed. From there you either put chosen files back or roll the root filesystem back.

changed files since a snapshot, five selected for restoring

The settings side covers timeline limits per config, creating or removing a config, snapper’s own timers, btrfsmaintenance’s jobs, and what btrfs has handed out to chunks. The menu updates live whoever changed the snapshots, so a snapshot taken in a terminal shows up without a refresh. Anything missing is named along with the line that installs it.

Prerequisites

PackageWhy
snapper and one configRequired. Not installed by default on most distributions, and there is nothing to list until a config exists.
polkitAnything that belongs to root: a snapshot for a config this account may not change, restoring files, rolling back, and the optional lock in front of the menu.
util-linux, btrfs-progsThe Storage page. Sizes for the snapshots themselves need btrfs counting them, which is off by default; the Storage page turns it on.

Check that snapper is actually there and has something to show before installing anything else:

snapper --version
systemctl status snapperd.service
snapper list-configs

An empty list-configs means there is nothing for the extension to do yet. GNOME Shell 46 or newer is the other requirement.

Installation

Step 1: install the extension

It is uploaded to extensions.gnome.org and still in review, so for now it installs from a release. Every tag builds the same zip that goes there:

gnome-extensions install --force wisp.zip

From the sources, tools/install-local.sh installs into the running session and tools/pack.sh builds the same zip:

git clone https://github.com/epogonii/wisp
cd wisp
tools/install-local.sh

Step 2: restart the shell

Before enabling it, not after. A running shell keeps an extension’s JavaScript in memory for the life of the process, so new code needs a new shell. On X11, Alt+F2 then r does it. On Wayland it has to be a new session.

Step 3: enable and verify

gnome-extensions enable wisp@epogonii.github.io
gnome-extensions info wisp@epogonii.github.io | grep State

Expected result: State: ACTIVE, and snapper snapshots in GNOME Shell: an indicator in the top bar listing your configs, newest snapshot first. If the menu is there but empty, read the next section.

Why There Is A Password Prompt

This is the part that surprises people, and it is snapper’s design rather than the extension’s. snapperd does not use polkit. Each config carries its own ALLOW_USERS and ALLOW_GROUPS in /etc/snapper/configs/<name>, and both are empty until somebody fills them in. A fresh install therefore tells an ordinary account nothing at all, which is what an empty menu means.

Rather than ask for a password every time it lists something, Wisp offers to add the account to the config once, through pkexec:

sudo snapper -c <config> set-config ALLOW_USERS=<you> SYNC_ACL=yes

polkit puts up that prompt and the password never reaches the extension. SYNC_ACL is what puts an ACL on the snapshot directory; without it the snapshots are listed but their files cannot be opened. Everything after that goes straight to snapperd over D-Bus as the user, with no prompt.

Restoring files, rolling back, the settings in /etc/snapper/configs and the systemd timers belong to root either way. Each one asks, and each one shows the command it is about to run before it runs it.

The fstab Trap

Worth knowing whether you use Wisp or the command line. snapper rollback points btrfs at a different default subvolume, so it takes effect at the next boot. It does nothing at all if /etc/fstab names the subvolume it mounts at /:

grep ' / ' /etc/fstab
# UUID=...  /  btrfs  subvol=@,compress=zstd:1  0 0
#                     ^^^^^^^^ this overrules the default subvolume

An explicit subvol= wins every time, so the rollback appears to succeed and the machine comes back exactly as it was. Where that is the case Wisp says so up front, instead of letting the reboot say it.

Preferences

gnome-extensions prefs wisp@epogonii.github.io
PageWhat is on it
AppearanceWhere the indicator sits and whether it is shown, what a middle click does, how many snapshots each config lists, ages or dates, whether a finished action answers with a pill under the panel or a notification, and the lock: never, after a while, or every time.
SnapshotsOne row per config with the subvolume it snapshots, whether it shows in the menu, whether this account may read it, and the timeline and numbered limits snapper cleans up by.
Schedulesnapper’s three timers, and how often btrfsmaintenance balances, scrubs, defragments and trims.
StorageSize, what btrfs has handed out to chunks, what is written, what is free, and the same per chunk type, plus what each config’s snapshots are taking between them, once btrfs is counting.
the Storage page

Gotchas

  • Per-snapshot sizes are blank until btrfs quota groups are on, because btrfs is not counting by default. The Storage page has a button that turns it on.
  • An empty menu on a working snapper install is almost always ALLOW_USERS, not a bug.
  • A rollback needs a reboot to mean anything, and needs fstab checked first.
  • Every string is translatable and none is translated yet. po/wisp.pot holds them, msginit --locale=<code> --input=po/wisp.pot --output=po/<code>.po starts a language, and pull requests are welcome.

For an issue: extension version, GNOME Shell version and distribution, snapper --version, whether systemctl status snapperd.service answers, and the shell’s log:

journalctl --user -b 0 -o cat /usr/bin/gnome-shell | grep -i wisp

Takeaways

  • If you run btrfs, you probably already have hourly snapshots and snapshots around every package transaction. The snapshots are not the missing piece; reaching them is.
  • snapper’s access control is per config in a text file, not polkit. Nothing works for a normal account until ALLOW_USERS and SYNC_ACL are set.
  • An explicit subvol= in fstab silently defeats snapper rollback. Check it before you need it.
  • Restoring a handful of files is the operation you actually want most of the time, and it is the one snapper snapshots in GNOME Shell make quick. A full rollback is the rare case.

Links

Status: the extension is submitted to extensions.gnome.org and still in the review queue. Until it clears, the release zip above is the way to install it.

Published inGNOME ShellLinux