Skip to content

Latest commit

 

History

9 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

snapshot-chroot

A small Btrfs/Snapper recovery utility for chrooting into a known-good root snapshot from a live environment.

snapshot-chroot records the root snapshot detected by a user's @reboot cron job, then uses that information during recovery to locate and chroot into the last known successfully booted snapshot.

If no saved snapshot is available, or if a different snapshot is desired, a snapshot number can be selected manually.

Overview

The project consists of two scripts:

  • save-last-snapshot.sh — records the Btrfs root snapshot currently mounted at / after boot.
  • snapshot-chroot.sh — mounts a selected snapshot and prepares a recovery chroot from a live environment.

The saved snapshot record is stored in the user's home directory, which allows it to remain available independently of the root snapshot being recovered.

Example:

Snapshot: 1
Recorded: Mon Aug 10 08:50:45 PM CDT 2026

Intended layout

The current scripts are designed for a Btrfs/Snapper layout using:

@
@home
@/.snapshots

with Snapper root snapshots located at:

@/.snapshots/<snapshot-number>/snapshot

The recovery script also expects a separate EFI System Partition.

Example:

/dev/nvme0n1p2   Btrfs root filesystem
/dev/nvme0n1p1   EFI System Partition

Adjust these values in snapshot-chroot.sh to match the target system.

Requirements

The recovery environment must provide:

bash
awk
btrfs
chroot
mount
umount

The installed system must use Btrfs and the snapshot layout described above.

snapshot-chroot.sh performs privileged mount, Btrfs, and chroot operations and must be run as root.

Recording the last successfully booted snapshot

Copy save-last-snapshot.sh into the user's ~/bin directory and make it executable:

mkdir -p ~/bin
cp save-last-snapshot.sh ~/bin/
chmod +x ~/bin/save-last-snapshot.sh

Add it to the user's crontab:

crontab -e

Add:

@reboot /home/USER/bin/save-last-snapshot.sh

Replace USER with the actual username.

How it works

After boot, save-last-snapshot.sh examines the Btrfs mount options for /.

If the running root filesystem is a Snapper snapshot matching:

@/.snapshots/<number>/snapshot

the script writes the snapshot number and timestamp to:

~/bin/last_snapshot

If the system is not currently running from a matching snapshot, the script exits without modifying the existing record. This preserves the last successfully recorded snapshot boot.

Configuring snapshot-chroot.sh

Before using the recovery script, edit the configuration section:

TARGET_USER="scottm"
ROOT_PARTITION="/dev/nvme0n1p2"
EFI_PARTITION="/dev/nvme0n1p1"
MOUNT_POINT="/mnt"

Set:

  • TARGET_USER to the user whose last_snapshot file should be read.
  • ROOT_PARTITION to the Btrfs filesystem containing @, @home, and @/.snapshots.
  • EFI_PARTITION to the EFI System Partition.
  • MOUNT_POINT to the temporary recovery mount point. /mnt is normally appropriate.

Recovery usage

Boot a live Linux environment that has Btrfs tools installed.

Run:

sudo ./snapshot-chroot.sh

If a valid last_snapshot record exists, the script reports it:

Last successfully booted snapshot: 1

Use snapshot 1 for the recovery chroot? [Y/n]

Press Enter or answer y to use it.

To select another snapshot, answer n and enter the desired snapshot number:

Enter snapshot number to use: 3

If no valid last_snapshot file exists, the script simply asks for a snapshot number.

Snapshot verification

Before building the chroot, snapshot-chroot.sh temporarily mounts the Btrfs top-level filesystem with subvolid=5.

The selected snapshot is then verified at:

@/.snapshots/<snapshot-number>/snapshot

If the snapshot does not exist, recovery stops and mounted filesystems are cleaned up.

Read-only snapshots

The selected snapshot is checked before entering the recovery environment.

If it is already writable:

Snapshot 1 is writable.

recovery continues normally.

If the snapshot is read-only:

Snapshot 3 is read-only.
A writable snapshot is required for system repairs from this chroot.

Make snapshot 3 writable? [y/N]

Answering y changes the Btrfs ro property to false and continues.

Any other response leaves the snapshot read-only and cancels the recovery chroot.

Important

Changing a read-only snapshot to writable modifies that snapshot.

Do this only when the selected snapshot is intended to become a writable recovery target. Consider the effect on any workflow that depends on the snapshot remaining unchanged, including Btrfs send/receive or archival snapshot strategies.

The script does not automatically change the snapshot back to read-only after recovery.

Recovery environment

Once the target snapshot has been selected and verified, the script mounts:

selected root snapshot  -> /mnt
@/.snapshots            -> /mnt/.snapshots
@home                   -> /mnt/home
EFI System Partition    -> /mnt/boot/efi

It also bind-mounts:

/dev
/dev/pts
/proc
/sys
/run

The resulting chroot therefore has access to the installed system, persistent home data, EFI files, and the root snapshot collection.

This makes operations such as the following possible from inside the recovery chroot:

update-initramfs -u
update-grub

or inspection and management of other Btrfs snapshots through:

/.snapshots

For example:

btrfs property get -ts /.snapshots/3/snapshot ro

Leaving the chroot

Exit normally:

exit

The script then unmounts the recovery environment.

A cleanup trap is installed so that mounted filesystems are also cleaned up if the script exits early after recovery setup has begun.

Recovery flow

Boot live environment
        |
        v
Mount @home
        |
        v
Read last_snapshot if available
        |
        v
Accept saved snapshot or select one manually
        |
        v
Mount Btrfs top level
        |
        v
Verify selected snapshot
        |
        v
Check read-only / writable state
        |
        +---- read-only ----> optionally make writable
        |
        v
Mount snapshot as recovery root
        |
        +---- mount @/.snapshots
        +---- mount @home
        +---- mount EFI
        +---- bind /dev /proc /sys /run
        |
        v
Enter chroot
        |
        v
Exit and clean up mounts

Files

snapshot-chroot/
├── save-last-snapshot.sh
├── snapshot-chroot.sh
└── last_snapshot

last_snapshot is an example of the state file generated by save-last-snapshot.sh.

Scope

snapshot-chroot does not perform a Snapper rollback and does not choose which snapshot should become the system's permanent root.

Its purpose is narrower: provide a predictable recovery chroot into a selected Btrfs/Snapper snapshot, with the last successfully booted snapshot offered as the default recovery target when available.

Status

This project is currently being tested on Debian with Btrfs and Snapper.

Review the configuration carefully before using it on another system or Btrfs layout.

About

Recovery chroot utility for Btrfs/Snapper systems, with automatic last-known-good snapshot selection and writable snapshot recovery.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages