BTRFS-BACKUP-NG-SNAPPER(1)

πŸ“¦
version 0.9.20 Β· 2 versions
, in fedora 43, fedora 44

πŸ’– btrfs-backup-ng-snapper β€” like, the whole manual πŸ’–

okay bestie, pull up a chair 🫢 this is the man page for btrfs-backup-ng-snapper, one of the btrfs-backup-ng user commands. It's the part of the toolkit that speaks fluent Snapper. Buckle up, it's long, we're doing this properly. ✨


✨ NAME ✨

btrfs-backup-ng-snapper β€” back up and restore snapper-managed snapshots πŸŽ€


🌈 SYNOPSIS 🌈

btrfs-backup-ng snapper detect [--json]
btrfs-backup-ng snapper list [--config NAME] [--type TYPE] [--json]
btrfs-backup-ng snapper backup CONFIG TARGET [OPTIONS]
btrfs-backup-ng snapper restore SOURCE [--list | --snapshot NUM | --all]
[CONFIG]
btrfs-backup-ng snapper status [--config NAME] [--target PATH] [--json]
btrfs-backup-ng snapper generate-config [CONFIG...] [OPTIONS]

πŸ’… DESCRIPTION πŸ’…

So basically: this command backs up and restores snapshots that Snapper manages. It's the little integration bridge that lets btrfs-backup-ng vibe with your existing Snapper setups β€” and it keeps Snapper's metadata (info.xml) and directory structure intact the whole time. No cap. πŸ”₯

Snapper is the tool people use for managing btrfs snapshots, and it's everywhere on openSUSE, Fedora, and Arch Linux. So if you're already running Snapper for local snapshot management, this command is your bestie: it replicates those snapshots out to remote backup storage. 🌸


πŸ‘‘ SUBCOMMANDS πŸ‘‘

🌟 detect

Discover Snapper configurations on the system. Like a little recon mission. πŸ•΅οΈ

btrfs-backup-ng snapper detect [--json]

It scans /etc/snapper/configs/ for Snapper configurations and shows you their subvolumes, snapshot directories, and whether they're valid or not.

  • --json β€” Output in JSON format for scripting. For when you need it machine-readable, iykyk. πŸ€–

🌟 list

List snapshots for one config, or literally all of them.

btrfs-backup-ng snapper list [--config NAME] [--type TYPE]
[--json]
  • --config NAME β€” List snapshots only for the specified Snapper config. If you leave it out, it lists snapshots for all configs. πŸ’–
  • --type TYPE β€” Filter by snapshot type. You can pass this more than once. Valid types are: single (standalone/timeline), pre (before package operations), post (after package operations).
  • --json β€” Output in JSON format.

🌟 backup

Back up Snapper snapshots to a target location. The main event. ✨

btrfs-backup-ng snapper backup CONFIG TARGET [OPTIONS]
  • CONFIG β€” Snapper configuration name (e.g., "root", "home").
  • TARGET β€” Destination path. For btrfs destinations, use a local path (e.g., /mnt/backup/root) or SSH (e.g., ssh://user@host:/backups/root). For non-btrfs destinations, use a raw target that writes a btrfs send stream to a file: raw:///path (local) or raw+ssh://user@host/path (remote). The target must exist and is not created; the .snapshots tree and each numbered slot are created below it (see PATHS in btrfs-backup-ng(1)).

Options:

  • --snapshot NUM β€” Back up only the specified snapshot number. Just the one. 🎯
  • --type TYPE β€” Filter by snapshot type. Can be specified multiple times.
  • --min-age DURATION β€” Skip snapshots younger than the specified age. Format: 30m, 1h, 1d. Super useful to avoid backing up incomplete pre/post pairs β€” like, wait for them to actually finish, babe. πŸ™ˆ
  • --compress METHOD β€” Compression for remote transfers. Valid: none, zstd, gzip, lz4, pigz, lzop. Default: zstd for SSH targets, none for local.
  • --rate-limit RATE β€” Bandwidth limit for transfers. Examples: 10M, 1G, 500K. Be kind to your network πŸ’œ
  • --ssh-sudo β€” Use sudo for btrfs commands on the remote host (SSH / raw+ssh targets).
  • --ssh-key FILE β€” Path to SSH private key file.
  • --ssh-auth-sock PATH β€” Explicit ssh-agent socket (overrides auto-discovery; useful under sudo).
  • --ssh-host-key-policy POLICY β€” Host-key verification: accept-new (default) or strict.
  • --dry-run β€” Show what would be backed up without making changes. Zero commitment, honestly iconic. πŸ‘‘
  • -v, --verbose β€” Enable verbose output.
  • --encrypt METHOD β€” Encrypt the backup (raw:// / raw+ssh:// targets only).
  • --gpg-recipient KEYID β€” GPG recipient key (required with --encrypt gpg).
  • --no-progress β€” Disable progress bars (default when not in a terminal).
  • --progress β€” Show progress bars (default when running in a terminal).
  • --skip-remote-lock β€” Proceed even if a pin cannot be recorded on the backup location, wherever its lock store lives (a remote target's lock directory, or a local location's lock file). Only safe when nothing else can prune this location during the run. A medium mounted read-only needs no pin and none is asked for.
  • --timestamp-format FMT β€” strftime format for the timestamp in backup names (default: %Y%m%d-%H%M%S).

🌟 restore

Restore Snapper snapshots from a backup location. Bring it back. πŸ¦‹

btrfs-backup-ng snapper restore SOURCE [OPTIONS] [CONFIG]
  • SOURCE β€” Backup location to restore from. Can be local or an SSH URL.
  • CONFIG β€” Local Snapper configuration name to restore into. Required to restore; optional with --list (listing only reads the source, no big deal).

Options:

  • -l, --list β€” List available backups at the source location.
  • --snapshot NUM β€” Restore a specific snapshot number. Can be specified multiple times. On a reused (duplicate) snapper number, it restores the newest by date and warns you. πŸ‘€
  • --backup-name NAME β€” Restore the exact raw backup by its unique name (shown by --list). Can be specified multiple times. Use this to reach an older copy when a snapper number was reused after a prune.
  • --date DATE β€” Restrict the selection to backups whose date matches DATE (YYYY-MM-DD[ HH:MM:SS] prefix). Disambiguates a reused --snapshot.
  • -a, --all β€” Restore all available backups. Everything. All of it. πŸ’–
  • --ssh-sudo β€” Use sudo for btrfs commands on the remote host (SSH / raw+ssh targets).
  • --ssh-key FILE β€” Path to SSH private key file.
  • --ssh-auth-sock PATH β€” Explicit ssh-agent socket (overrides auto-discovery; useful under sudo).
  • --ssh-host-key-policy POLICY β€” Host-key verification: accept-new (default) or strict.
  • --gpg-keyring PATH β€” GPG keyring to decrypt an encrypted raw snapper backup. Must match the keyring the backup was encrypted for.
  • --openssl-cipher CIPHER β€” OpenSSL cipher fallback for a legacy raw backup whose .meta sidecar does not record one. Modern sidecars are authoritative and override this.
  • --dry-run β€” Show what would be restored without making changes.
  • --json β€” Output in JSON format (with --list).
  • --from-config NAME β€” Only restore from this snapper config in backup.

okay breathe, bestie, this next bit is the Big Paragraph and it matters, so read it slow 🌸

A restore is a transfer through the same planner and executor a backup uses, into Snapper's own layout. The selection is restored exactly as given, never expanded to a chain (--all selects everything). Each increment's parent is chosen from what the local config already holds, by identity (a slot's received_uuid against the identity the backup's stream carries), never by Snapper number: a backup whose parent is already restored is received as an increment from that copy, one whose parent is not there is received in full. Onto empty recovery media, --snapshot N is one full send into slot 1. Every selected backup lands in a NEW slot whether or not a copy is already there. The copy is received into .snapshots/{N}.incoming/, checked, given its renumbered info.xml, and only then renamed to .snapshots/{N}/, so a restore that fails mid-receive leaves no numbered slot and no temp. The number is decided when the copy is published, with a rename that cannot replace an existing entry: a snapshot Snapper creates while the restore runs keeps its slot and the copy lands under the next free number. One writer runs below a .snapshots tree at a time β€” a restore into a config, or a backup into a local target β€” and a second one started meanwhile is refused with the reason. The backup is pinned on its location for the duration (released if a transfer fails or the run is interrupted), and no prune deletes a pinned slot or stream, on any location type; --skip-remote-lock for a location that can be read but not written, and nothing for a medium mounted read-only. A raw:// increment whose parent is neither in the config nor selected is refused before anything is transferred. πŸ’…

⚠️ A restored snapshot is written directly into .snapshots/{N}/ (not via snapper create), so the Snapper daemon does NOT see it until it reloads. Restart it (systemctl restart snapperd, as root) or reboot after a restore before using snapper diff, snapper undochange, or a rollback against it; the command prints a reminder. The on-disk snapshot is complete and correct β€” only the daemon's in-memory view lags, and snapper list alone does not make it look again. Restored slots use Snapper's native 0755 directory mode.

For a raw+ssh:// source written with --ssh-sudo (root-owned remote directory), pass --ssh-sudo to restore as well, or it will report a permission error instead of the backups. When Snapper has reused a number after a prune, a raw target can hold two backups with the same number; --snapshot NUM restores the newest by date and warns. To restore an older copy, use --backup-name NAME (names are shown by --list) or narrow --snapshot NUM with --date YYYY-MM-DD.


🌟 status

Show backup status for Snapper configurations. The vibe check. πŸ“Š

btrfs-backup-ng snapper status [--config NAME] [--target PATH]
[--json]
  • --config NAME β€” Show status for a specific config only.
  • --target PATH β€” Check backup status at the specified target. Shows which snapshots are backed up vs pending.
  • --json β€” Output in JSON format.

🌟 generate-config

Generate TOML configuration for Snapper volumes. Let it cook. πŸ“

btrfs-backup-ng snapper generate-config [CONFIG...] [OPTIONS]
  • CONFIG β€” Snapper configuration names to include. If omitted, it generates for all configs.

Options:

  • --target PATH β€” Target path for backups. The config name will be appended (e.g., /mnt/backup becomes /mnt/backup/root for the root config).
  • --type TYPE β€” Snapshot types to include. Can be specified multiple times. Default: single.
  • --min-age DURATION β€” Minimum snapshot age. Default: 0.
  • -o, --output FILE β€” Write configuration to file.
  • --append FILE β€” Append to existing configuration file.
  • --ssh-sudo β€” Add ssh_sudo = true to SSH targets.
  • --json β€” Output in JSON format.

πŸŽ€ BACKUP DIRECTORY LAYOUT πŸŽ€

Snapper backups preserve the native Snapper directory structure. Exactly like this, no notes:

/backups/root/.snapshots/
β”œβ”€β”€ 559/
β”‚   β”œβ”€β”€ info.xml        # Snapper metadata
β”‚   └── snapshot/       # btrfs subvolume
β”œβ”€β”€ 560/
β”‚   β”œβ”€β”€ info.xml
β”‚   └── snapshot/
└── 561/
    β”œβ”€β”€ info.xml
    └── snapshot/

This layout enables direct restoration back into Snapper-managed volumes. That's the whole point, bestie. 🫢


...more coming, don't go anywhere πŸ’–

🌸 CONFIGURATION 🌸

okay so for automated backups you literally just add your Snapper volumes to your config.toml and it's giving effortless:

[[volumes]]
path = "/"
source = "snapper"

[volumes.snapper]
config_name = "root"
include_types = ["single", "pre", "post"]
min_age = "1h"

[[volumes.targets]]
path = "ssh://backup@server:/backups/root"
ssh_sudo = true
compress = "zstd"

then bestie you run:

btrfs-backup-ng run

periodt. that's the whole vibe. ✨


πŸŽ€ Configuration Options πŸŽ€

  • config_name β€” the Snapper config name (like "root" or "home") OR "auto" if you want it to just, yk, detect it for you. main character energy.
  • include_types β€” which snapshot types you're letting in the group chat: "single", "pre", "post".
  • exclude_cleanup β€” cleanup algorithms to skip: "number", "timeline", "empty-pre-post".
  • min_age β€” the minimum snapshot age before it gets backed up (like "30m", "1h", "1d"). no one likes a backup that's Too Fresh πŸ’…

πŸ¦‹ SNAPSHOT TYPES πŸ¦‹

  • single β€” standalone snapshots, made by hand or by timeline (hourly snapshots are the classic example). living on their own, thriving.
  • pre β€” snapshots taken before your package manager does its thing (zypper, dnf, etc.). the "before" pic.
  • post β€” snapshots taken after your package manager does its thing. the glow-up pic.

πŸ‘‘ EXAMPLES πŸ‘‘

Detect Snapper configurations:

btrfs-backup-ng snapper detect

List all snapshots for root config:

btrfs-backup-ng snapper list --config root

List only timeline snapshots:

btrfs-backup-ng snapper list --type single

Backup root config to local drive:

sudo btrfs-backup-ng snapper backup root /mnt/backup/root

Backup to remote server with compression:

sudo btrfs-backup-ng snapper backup root ssh://backup@server:/backups/root

Backup specific snapshot:

sudo btrfs-backup-ng snapper backup root /mnt/backup/root --snapshot 559

Backup only timeline snapshots older than 1 hour:

sudo btrfs-backup-ng snapper backup root /mnt/backup --type single --min-age 1h

Dry run to see what would be backed up:

sudo btrfs-backup-ng snapper backup root /mnt/backup --dry-run

List backups at a location:

btrfs-backup-ng snapper restore --list /mnt/backup/root

Restore a specific snapshot:

sudo btrfs-backup-ng snapper restore /mnt/backup/root --snapshot 559 root

Restore all backups:

sudo btrfs-backup-ng snapper restore /mnt/backup/root --all root

Check backup status:

btrfs-backup-ng snapper status --target /mnt/backup/root

Generate config for root:

btrfs-backup-ng snapper generate-config root --target ssh://server:/backups

Generate and save config:

btrfs-backup-ng snapper generate-config root --target /mnt/backup -o snapper.toml

Append to existing config:

btrfs-backup-ng snapper generate-config root --append ~/.config/btrfs-backup-ng/config.toml

πŸ”₯ INCREMENTAL TRANSFERS πŸ”₯

both backup and restore use incremental btrfs send/receive whenever they possibly can. and the parent? it's whatever the DESTINATION already holds β€” decided by identity (received_uuid). so a backup finds its parent among the target's slots, and a restore finds its parent among the local config's:

Snapshot 559: 2.1 GB (full, no parent available)
Snapshot 560: 156 MB (incremental from 559)
Snapshot 561:  89 MB (incremental from 560)

like… the way that 561 is 89 MB?? that's the incremental slay, we love to see it πŸ’–


⭐ EXIT STATUS ⭐

  • 0 β€” Success 🫢
  • 1 β€” Failure (Snapper not found, config not found, transfer error, etc.) 😭

🌈 FILES 🌈

  • /etc/snapper/configs/ β€” Snapper configuration files
  • /.snapshots/ β€” default snapshot directory for the root config
  • /home/.snapshots/ β€” default snapshot directory for the home config
  • .snapshots/{num}/info.xml β€” the Snapper metadata file for each snapshot
  • .snapshots/{num}/snapshot/ β€” the actual btrfs snapshot subvolume

πŸ’œ SEE ALSO πŸ’œ

btrfs-backup-ng(1), btrfs-backup-ng-restore(1), snapper(8), btrfs-send(8), btrfs-receive(8)

go read these too bestie, iykyk πŸ“š


🧚 NOTES 🧚

Snapper has to be installed and configured on the source system. the backup destination? literally any btrfs filesystem will do β€” Snapper is NOT required over there. so chill.

Restored snapshots get assigned the next free snapshot numbers of the local config. and the info.xml is the backup's own, with only the number changed β€” so type, description, date, cleanup, userdata and any element Snapper wrote are all preserved verbatim. no detail lost, no cap. πŸ’…


and that's the whole page, bestie!! this was btrfs-backup-ng, January 2026, page BTRFS-BACKUP-NG-SNAPPER(1) πŸ’– go make some backups, you absolute icon πŸ‘‘

πŸ“¦ where this page comes from