BTRFS-BACKUP-NG-RESTORE(1)

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

✨ btrfs-backup-ng-restore πŸ’…

okay bestie, settle in, because this is the manual for btrfs-backup-ng-restore, a User Commands page (section 1), and it's a whole vibe. πŸ’– It's part of the btrfs-backup-ng family, and it's the one you call when you need your snapshots to come back home. No cap.


🌸 NAME 🌸

btrfs-backup-ng-restore β€” restore snapshots from backup location πŸ¦‹


✨ SYNOPSIS ✨

btrfs-backup-ng restore [OPTIONS] SOURCE DESTINATION
btrfs-backup-ng restore --list SOURCE
btrfs-backup-ng restore --volume PATH --to DESTINATION
btrfs-backup-ng restore --list-volumes
btrfs-backup-ng restore --status SOURCE

πŸ’– DESCRIPTION πŸ’–

Pull snapshots from backup storage back to a local system. That's it, that's the whole job, and honestly it's giving main character energy. This command is what handles disaster recovery, migration between machines, and point-in-time restoration. 😭 Imagine losing everything and then this thing walks in like "hey girl, I got you" β€” iconic.

The restore command automatically handles incremental chains, meaning it makes sure all the parent snapshots required for a successful restore actually get transferred. You don't have to babysit the chain. It just knows. ✨


πŸŽ€ ARGUMENTS πŸŽ€

  • SOURCE β€” Backup location to restore from. This can be a local path (like /mnt/backup/home) or an SSH URL (like ssh://user@host:/path/to/backup). 🌈
  • DESTINATION β€” Local path to restore snapshots to. Must be on a btrfs filesystem. It gets created if it does not exist: it's an output location, the place this command was asked to put something new. That's the key difference between it and a backup location, which must exist (see PATHS in btrfs-backup-ng(1)). πŸ’…

πŸ’… OPTIONS πŸ’…

Listing and Selection πŸ”

  • -l, --list β€” List available snapshots at the backup location, without restoring anything. Just window shopping. πŸ›οΈ
  • -s, --snapshot NAME β€” Restore one specific snapshot, by name.
  • --before DATETIME β€” Restore the snapshot closest to the specified time. Format: YYYY-MM-DD or YYYY-MM-DD HH:MM:SS.
  • -a, --all β€” Restore all snapshots from the backup location (a full mirror). 1:1, no crumbs. πŸ’―
  • -i, --interactive β€” Interactively select which snapshot to restore from a list. You get to pick, bestie, choose wisely. 🫢
  • --fs-checks auto|strict|skip β€” Filesystem verification mode: auto (warn and continue), strict (error on failure), skip (no checks). Default: auto.
  • --skip-remote-lock β€” Proceed even if a pin cannot be recorded on the 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.
  • --skip-verify β€” Skip the pre-restore integrity check for raw backups (restore even if the stored stream's checksum no longer matches, and skip the extra read). Use this for last-copy recovery of a partially-corrupt backup. 😭 It's the "I have no other copy" button, so treat it with care.
  • --timestamp-format FMT β€” strftime format for parsing snapshot timestamps in direct mode (defaults to the config's [global] timestamp_format, else the built-in).

Transfer Options πŸš€

  • --dry-run β€” Print the restore plan and stop. It's the same plan a real run prints and executes, and it refuses exactly what the run would refuse. Love a preview that doesn't lie. πŸ’–
  • --no-incremental β€” Send every snapshot in full (no -p). The chain a snapshot depends on is still brought, but as full sends. Big, chunky, honest transfers.
  • --compress METHOD β€” Compress the transfer from an ssh:// backup location: the remote runs btrfs send through the compressor, and this host decompresses before btrfs receive. Any method run --compress accepts works (zstd, gzip, lz4, xz, ...). Other sources ignore it: a local source has no wire, and a raw:// or raw+ssh:// stream is sent exactly as it was stored. The decompressor must be installed on this host; the restore refuses before connecting when it is not. 🚫
  • --rate-limit RATE β€” Bandwidth limit for transfers. Examples: 10M, 1G, 500K. Throttle it, queen. 🐒
  • --progress β€” Show progress bars during transfers. ✨
  • --no-progress β€” Disable progress bars. For the calm, no-drama runs. 🧘

Safety Options πŸ›‘οΈ

  • --overwrite β€” Not supported in this release. Snapshots already at the destination are left exactly as they are, and a warning says so; anything missing is still restored. To replace an existing snapshot, remove it yourself and run the restore again. Why the option does not replace, and what a replacement must satisfy, is in docs/RESTORE-OVERWRITE.md.
  • --in-place β€” Not implemented in this release. The command refuses and restores nothing (exit status 2). A restore receives each snapshot as a nested subvolume at DESTINATION/name and never replaces DESTINATION itself. To replace a location, restore into a staging directory, verify it, and swap the subvolumes yourself; the README's Strategy 2 gives the commands and the rollback. The running root filesystem can only be replaced from a rescue system. πŸ’€
  • --yes-i-know-what-i-am-doing β€” Confirm dangerous operations. Heads up: it does not unlock --in-place. Nice try though. πŸ™ˆ

SSH Options 🌐

  • --ssh-sudo β€” Use sudo for btrfs commands on the remote host.
  • --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 for this run: accept-new (default) or strict. 🫢

Decryption Options πŸ”

  • --gpg-keyring PATH β€” GPG keyring to decrypt an encrypted raw backup (raw:// / raw+ssh://). 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 record the cipher and are authoritative, so this is only consulted for backups written before that was sealed.

Other Options πŸ¦‹

  • --prefix PREFIX β€” Filter snapshots by prefix (e.g., "home-" to only show home snapshots).
  • --no-fs-checks β€” Skip btrfs subvolume verification. Needed when backup directories are regular directories rather than btrfs subvolumes.

Config-Driven Restore Options βš™οΈ

  • -c, --config FILE β€” Path to configuration file.
  • --volume PATH β€” Restore backups for volume defined in config (e.g., /home). Uses the backup target(s) configured for that volume.
  • --target INDEX β€” Target index to restore from (0-based). Default: first target (0). Use with --volume to select which backup target to restore from.
  • --to PATH β€” Destination path for config-driven restore. Required when using --volume.
  • --list-volumes β€” List volumes and their backup targets from the configuration file.

Recovery Options 🩹

  • --status β€” Show status of locks and incomplete restores at the backup location. A location holding snapper backups (numbered .snapshots/<n> slots, or raw streams with .snapper-meta.json sidecars) lists those backups as well, each with the pins a snapper restore holds on it.
  • --unlock [LOCK_ID] β€” Unlock stuck restore sessions. Use "all" to unlock all restore locks, or specify a specific lock ID.
  • --cleanup β€” Remove what an interrupted restore left at DESTINATION. Each receive is recorded in a run marker under DESTINATION/.btrfs-backup-ng/restore/ and the marker is removed once the copy is verified. A subvolume is deleted only when a marker whose restore is no longer running names it, directly under the destination (never .., never through a symlink), and it has no received_uuid. Everything else is reported and left, including any subvolume no marker names, however empty. Honours --dry-run and asks for confirmation. 🧹

πŸ”₯ RESTORE STRATEGIES πŸ”₯

Strategy 1: Direct Restore (Default) πŸ’«

Restore the latest snapshot directly:

btrfs-backup-ng restore /mnt/backup/home /mnt/restore \
    --prefix "home-" --no-fs-checks

Strategy 2: Specific Snapshot 🎯

Restore a specific point in time:

btrfs-backup-ng restore /mnt/backup/home /mnt/restore \
    --snapshot home-20260101-120000 --no-fs-checks

Strategy 3: Interactive Selection 🫢

Choose from a list:

btrfs-backup-ng restore /mnt/backup/home /mnt/restore \
    --interactive --no-fs-checks

Strategy 4: Full Mirror πŸͺž

Restore all snapshots:

btrfs-backup-ng restore /mnt/backup/home /mnt/restore \
    --all --no-fs-checks

🌈 EXAMPLES 🌈

  • List available snapshots: btrfs-backup-ng restore --list /mnt/backup/home --no-fs-checks
  • Restore latest snapshot from local backup: btrfs-backup-ng restore /mnt/backup/home /mnt/restore --no-fs-checks
  • Restore from SSH backup with sudo: btrfs-backup-ng restore ssh://backup@server:/backups/home /mnt/restore --ssh-sudo
  • Restore specific snapshot: btrfs-backup-ng restore /mnt/backup/home /mnt/restore --snapshot home-20260101-120000
  • Restore snapshot closest to a date: btrfs-backup-ng restore /mnt/backup/home /mnt/restore --before 2026-01-01 12:00
  • Check for stuck locks: btrfs-backup-ng restore --status /mnt/backup/home --no-fs-checks
  • Unlock all stuck restore sessions: btrfs-backup-ng restore --unlock all /mnt/backup/home --no-fs-checks
  • Clean up partial restores: btrfs-backup-ng restore --cleanup /mnt/restore
  • List configured volumes and targets: btrfs-backup-ng restore --list-volumes
  • List snapshots for a configured volume: btrfs-backup-ng restore --volume /home --list
  • Restore using config (knows backup location): btrfs-backup-ng restore --volume /home --to /mnt/restore
  • Restore from second configured target: btrfs-backup-ng restore --volume /home --target 1 --to /mnt/restore

🧚 INCREMENTAL CHAINS 🧚

A restore brings the chain a snapshot depends on: the older snapshots at a btrfs backup location, or the parent recorded in the .meta sidecar of a raw:// store. Whatever is already at the destination is skipped, and "already there" is decided by identity (the copy's received_uuid against the backup's own), never by name. Each snapshot is sent as an increment from the newest one the destination holds, or in full when it holds none. A request that is already satisfied succeeds with Already at the destination, so nothing to do. 😌

Example chain:

snap-1 (full) -> snap-2 (incr) -> snap-3 (incr) -> snap-4 (incr)

To restore snap-4 onto an empty destination, snapshots 1, 2, 3 and 4 are all transferred; if snap-2 is already there, only 3 and 4 are. ✨

πŸ’– WHAT IS ALREADY AT THE DESTINATION πŸ’–

Okay so bestie, before literally anything gets transferred, the restore does a lil vibe check on every single name it's about to receive. πŸ‘€

And if the destination already has something sitting under that name that is not this backup's copy? Like:

  • a partial from an interrupted restore 😭
  • a subvolume somebody made by hand πŸ™ˆ
  • a copy of a different snapshot πŸ’€
  • or just a plain directory 🌸

…then the whole restore refuses. It names the path, tells you what that thing actually is, and transfers nothing. No cap.

And it is never deleted. Not touching it. Not even a little. Hands off. πŸ’…

Same energy for a raw:// increment whose parent is no longer in the store β€” refused the exact same way, because fr fr, a stored increment only applies onto its parent. That's just how it works. ✨


🩹 RECOVERY FROM FAILURES 🩹

So when a transfer fails, the restore cleans up after itself like the responsible main character it is: the partial copy it made gets removed, and its pin on the backup gets released. Slay. 🫢

But when a restore gets killed outright β€” SIGKILL, power loss, the whole dramatic exit πŸ’€ β€” it leaves behind a partial subvolume and its run marker. And guess what? The next restore will straight up refuse to receive onto it. Iconic boundaries, honestly.

Meanwhile, a pin that a killed restore held on an ssh:// or raw+ssh:// target expires on its own a few minutes later. It just… heals. 🧚

But if you don't wanna wait? To recover at once:

  1. Check status: btrfs-backup-ng restore --status SOURCE
  2. Unlock any stuck sessions: btrfs-backup-ng restore --unlock all SOURCE
  3. Clean up partial restores: btrfs-backup-ng restore --cleanup DESTINATION
  4. Retry the restore

Four steps. That's it. You got this. πŸŽ€


πŸ‘‘ SEE ALSO πŸ‘‘


And that's the whole page, bestie!! πŸ’œ This was btrfs-backup-ng β€” BTRFS-BACKUP-NG-RESTORE(1) β€” your girl, dated January 2026. Go forth and restore responsibly. Periodt. βœ¨πŸ’…πŸŒˆ

πŸ“¦ where this page comes from