Files
docudjeex/content/en/3.serveex/91.advanced/4.btrfs-snapshots.md
T

7.1 KiB

title, description
title description
BTRFS Snapshots Format Debian's root filesystem with BTRFS and use snapshots to instantly roll back a risky update or config change, as a local complement to Backrest's off-site 3-2-1 backups.

:ellipsis{left=0px width=40rem top=10rem blur=140px zIndex=60}

BTRFS is a Linux filesystem with one killer feature for a homelab: snapshots. A snapshot freezes the exact state of a filesystem in an instant, at essentially zero cost, without copying a single byte of data upfront. Break something ten minutes after an apt full-upgrade, or overwrite the wrong .env file, and you can go back to exactly how things were before, without touching a backup at all.

This is not what Backrest and the 3-2-1 rule are for, so it's worth being precise about the difference before setting anything up.

Snapshots are not backups

A snapshot lives on the exact same disk as the data it protects. It's instant, needs no network, and it's perfect for undoing a mistake you just made, but it does nothing at all the day that disk itself dies, gets stolen, or your server burns down. That's what a real 3-2-1 backup is for: a copy on different media, ideally off-site.

Think of it this way:

  • Snapshot = an undo button. Instant, local, cheap, only useful while the disk is alive.
  • Backup = insurance. Slower, off-site, the only thing that survives the disk itself failing.

Keep both. Snapshots make you fearless about updates and experiments, backups make sure a dead drive stays an inconvenience instead of a catastrophe.

::note{to="/serveex/core/installation#partitioning"}

This guide assumes the root partition was formatted with Btrfs during Debian's installation. Btrfs can't be safely bolted onto an existing ext4 root after the fact, so this is a choice you make once, at install time. ::

Formatting the root partition with BTRFS

Debian's Guided partitioning only ever offers ext4. To get Btrfs, pick Manual partitioning instead, at the same step the main install guide describes:

::steps{level="3"}

Select Manual partitioning

At the partitioning method screen, choose Manual instead of Guided - use entire disk.

Create a partition table

Select the disk, confirm creating a new empty partition table, then select the resulting FREE SPACE and choose Create a new partition.

Set the partition size and type

Give the partition the rest of the disk (minus a small EFI partition if you're on UEFI, handled the same way as a Guided install), and set Use as to Btrfs journaling file system, with the mount point /.

Finish partitioning

Finish partitioning and write changes to disk, then confirm with Yes.

Done!

::

Everything else in the installer stays the same.

Taking a snapshot

A snapshot is created with a single command, and completes instantly no matter how much data is on the disk, since Btrfs only starts copying blocks the moment something actually changes (copy-on-write):

sudo mkdir -p /.snapshots
sudo btrfs subvolume snapshot -r / /.snapshots/$(date +%F_%H-%M-%S)
  • -r makes it read-only, which is what you want for a safety net: nothing, including you by accident, can modify a snapshot after the fact.
  • Storing snapshots under /.snapshots keeps them out of the way, and Btrfs is smart enough not to recurse into a subvolume the next time you snapshot / itself, so snapshots never end up containing older snapshots.

Take the habit of running this before anything that could go wrong: sudo apt full-upgrade, editing a systemd unit, or a Docker Compose change that touches something outside /srv/docker.

::tip Give the snapshot a name that means something instead of just a timestamp, for example /.snapshots/before-upgrade-2026-09-09, so you know why it's there when you find it three weeks later. ::

Restoring files from a snapshot

A snapshot is just a folder: everything the filesystem looked like at that instant, browsable like any other directory.

ls /.snapshots/2026-09-09_18-30-00/etc/ssh/

To undo a mistake, copy the file (or folder) back from the snapshot over the current one:

sudo cp -a /.snapshots/2026-09-09_18-30-00/etc/ssh/sshd_config /etc/ssh/sshd_config

-a preserves permissions and ownership, which matters for anything under /etc.

::note

This covers the vast majority of real homelab accidents: a bad config, a deleted file, a package upgrade that broke one thing. Rolling back the entire root filesystem (for a system that no longer boots at all) is also possible, by renaming subvolumes from a live USB, but it's a more delicate, less common operation. The Btrfs documentation covers it if you ever need it, and honestly, if it comes to that, this is exactly the scenario your off-site Backrest backup is for anyway. ::

Managing snapshots

sudo btrfs subvolume list /

Lists every subvolume on the filesystem, snapshots included, each with its own ID. Delete one you no longer need with:

sudo btrfs subvolume delete /.snapshots/2026-09-09_18-30-00

::caution

Snapshots are cheap, not free: the moment the live filesystem diverges from a snapshot, the old blocks stick around for as long as the snapshot references them. A pile of old snapshots on a server that changes a lot (container images, logs) can quietly eat real disk space. Check with df -h / and prune what you don't need anymore. ::

Automating snapshots

Rather than remembering to run the command by hand, a small script plus a systemd timer takes one automatically and prunes old ones:

sudo nano /usr/local/bin/btrfs-snapshot.sh
#!/bin/bash
set -e
mkdir -p /.snapshots
btrfs subvolume snapshot -r / "/.snapshots/$(date +%F_%H-%M-%S)"

# Keep only the 7 most recent snapshots
cd /.snapshots
ls -1 | sort | head -n -7 | while read -r old; do
    btrfs subvolume delete "$old"
done
sudo chmod +x /usr/local/bin/btrfs-snapshot.sh
sudo nano /etc/systemd/system/btrfs-snapshot.service
[Unit]
Description=Take a Btrfs root snapshot

[Service]
Type=oneshot
ExecStart=/usr/local/bin/btrfs-snapshot.sh
sudo nano /etc/systemd/system/btrfs-snapshot.timer
[Unit]
Description=Daily Btrfs root snapshot

[Timer]
OnCalendar=daily
Persistent=true

[Install]
WantedBy=timers.target
sudo systemctl daemon-reload
sudo systemctl enable --now btrfs-snapshot.timer

Check it's scheduled with systemctl list-timers, and trigger one right away to test it with sudo systemctl start btrfs-snapshot.service.

That's it: a rolling, automatic undo button for your server, running quietly alongside the real backups Backrest is already taking off-site.