BTRFS-BACKUP-NG(1)
π NAME π
okay so welcome to the manual page for btrfs-backup-ng, bestie β it lives in the User Commands part of the manual (that's section 1, iykyk). And what does it do? Automated btrfs backup management with incremental transfers. That's the whole vibe. β¨
πΈ SYNOPSIS πΈ
btrfs-backup-ng [OPTIONS] COMMAND [COMMAND_OPTIONS]
literally that's it. options first, then a command, then that command's own options. π«Ά
π DESCRIPTION π
btrfs-backup-ng is a modern, feature-rich tool for automating BTRFS snapshot backup management. She's not doing one thing, she's doing the whole wardrobe:
- TOML configuration files π
- time-based retention policies
- parallel execution
- stream compression
- space-aware operations with quota support
- automatic subvolume detection
- robust SSH transfer support
Main character energy, fr fr. π
π¦ The two modes π¦
The tool can run in two modes, and you gotta know which one you're in:
- Config-driven mode β you use a TOML configuration file to define volumes, targets, and retention policies. You get here through subcommands like
run,snapshot,transfer. Very organized, very demure. - Legacy mode β you give source and destination paths straight on the command line, just like the original
btrfs-backuptool did. The source, the destination and an absolute-ffolder all have to exist; see PATHS below for the whole situation. Snapshots get taken into.snapshotsinside the source, or into the-ffolder. And here's the important bit: when that folder is empty while.snapshotsis still holding the chain from an earlier release, the run is refused rather than started as a brand-new chain β unless you pass--accept-full-send. Don't ignore that one, bestie, it's protecting you. π
β¨ GLOBAL OPTIONS β¨
-h,--helpβ show the help message and dip. π-v,--verboseβ turn on verbose output. more words, more lore.-q,--quietβ suppress the non-essential output. silence is golden. π€«--debugβ enable debug output with detailed logging.--btrfs-debugβ runs everybtrfs sendandbtrfs receivewith-vv, and logs each line they print, one per file operation, as it arrives, prefixed with the process that printed it. This implies--debug, since those lines get logged at that level. Same setting is available asbtrfs_debug = trueunder[global]in the configuration file. In legacy mode this option has always existed as--btrfs-debug; until this release its output was just... discarded. ποΈπ not anymore tho. she's loud now.-V,--versionβ show the version and exit.-c,--config FILEβ path to the configuration file. Defaults to~/.config/btrfs-backup-ng/config.tomlor/etc/btrfs-backup-ng/config.toml.
π COMMANDS π
runβ execute all configured backup jobs (snapshot + transfer + prune). The full routine, head to toe. Seebtrfs-backup-ng-run(1).snapshotβ create snapshots only, no transferring to targets. Just the snappy part. Seebtrfs-backup-ng-snapshot(1).transferβ transfer existing snapshots to targets without creating new ones. Seebtrfs-backup-ng-transfer(1).pruneβ apply retention policies to clean up old snapshots and backups. Marie Kondo but for snapshots. Seebtrfs-backup-ng-prune(1).listβ show snapshots and backups across all configured volumes. Seebtrfs-backup-ng-list(1).statusβ show job status, last run times, and statistics. the receipts β¨ Seebtrfs-backup-ng-status(1).configβ configuration management (validate,init,import,detect). Seebtrfs-backup-ng-config(1).installβ install the systemd timer/service for automated backups. seebtrfs-backup-ng-install(1).uninstallβ remove the installed systemd timer/service. she said bye πrestoreβ restore snapshots from the backup location back to the local system. Seebtrfs-backup-ng-restore(1).verifyβ verify backup integrity at local or remote locations. Seebtrfs-backup-ng-verify(1).estimateβ estimate backup transfer sizes before execution. no surprises, we love that. Seebtrfs-backup-ng-estimate(1).
π CONFIGURATION π
Config files use TOML format, and they're searched in this exact order:
- CLI specified:
--config /path/to/config.toml - User config:
~/.config/btrfs-backup-ng/config.toml - System config:
/etc/btrfs-backup-ng/config.toml
Example configuration β look at her, she's perfect:
[global]
snapshot_dir = ".snapshots"
incremental = true
[global.retention]
min = "1d"
hourly = 24
daily = 7
weekly = 4
monthly = 12
[[volumes]]
path = "/home"
snapshot_prefix = "home-"
[[volumes.targets]]
path = "/mnt/backup/home"
[[volumes.targets]]
path = "ssh://backup@server:/backups/home"
ssh_sudo = true
compress = "zstd"
π§ PATHS π§
okay this is the part where the rules are rules. Which paths get created is decided by what a path is, not by where it was typed β so there are no exceptions. periodt.
- A backup location must exist and is never created. A source subvolume, a target on every transport (local,
raw://,ssh://,raw+ssh://) and an absolute snapshot base are all statements that something is there β whether they came from the configuration file, fromsnapper backup TARGET, or from legacy mode'sSOURCE,DESTINATIONand absolute-ffolder. If one is missing, it's refused with a message naming the likely cause and the remedy; nothing gets created. This is 100% deliberate, and here's why: a target on a removable or network filesystem that wasn't mounted used to have its mount point rebuilt on the root filesystem and the backup written there. And an absolutesnapshot_dirthat wasn't mounted had the snapshots written to the root filesystem β where they succeed. π so. Mount the filesystem, correct the path, or create the directory once by hand, and run again. - An output location is created. That's anywhere a command was asked to put something new: the restore destination,
verify --temp-dir, and the file written byconfig init -o,completions installormanpages install. - The program's own state is created. Its state directory, transfer cache, run lock, the parents of
log_fileandtransaction_log, and ssh control sockets. Hers. π - Below a location that exists, one level at a time, never the location itself. The
.btrfs-backup-ngtree under a target, a relativesnapshot_dirunder its volume, the per-volume directory under an absolutesnapshot_dir, the.snapshotsslots of a snapper backup, and the lock directory on a remote target.
π RETENTION POLICIES π
Time-based retention (applied by the btrfs-backup-ng-prune(1) command) uses these settings. For each bucket, the oldest snapshot in the interval is kept β that's the first-of-interval representative, matching the btrbk/snapper convention. π
minβ minimum retention period (e.g.,"1d","12h","1M","1y"). Nothing is deleted before this age. Month and year units are calendar-aware:1Mis one calendar month (not a flat 30 days) and1yis one calendar year. The valueallkeeps every snapshot in the scope for ever, whatever the bucket counts say (that's btrbk'ssnapshot_preserve_min all, its default). An invalid value fails loudly and prunes nothing.hourlyβ number of hourly snapshots to keep (one per clock hour).dailyβ number of daily snapshots to keep (one per day).weeklyβ number of weekly snapshots to keep (one per ISO-8601 week).monthlyβ number of monthly snapshots to keep (one per calendar month).yearlyβ number of yearly snapshots to keep (one per year).
πΈ COMPRESSION πΈ
Supported compression methods for transfers:
noneβ no compression. that's the default. πzstdβ Zstandard compression. recommended, fast with a good ratio. the girlies love her. π₯gzipβ standard gzip compression.lz4β very fast compression with a lower ratio.pigzβ parallel gzip (multi-threaded). she multitasks.lzopβ fast compression, low CPU usage.
π¦ SSH TARGETS π¦
Remote targets use SSH URLs, like this:
ssh://user@host:/path/to/backup
And here are the options for SSH targets:
ssh_sudoβ usesudofor btrfs commands on the remote host.ssh_keyβ path to the SSH private key file. πssh_host_key_policyβ host-key verification policy:accept-new(default; trust-on-first-use, but rejects a changed key) orstrict(only hosts already present inknown_hosts; an unknown host is refused). Also settable per run with--ssh-host-key-policy.
π SSH SECURITY π
btrfs-backup-ng verifies the remote host's SSH key on every connection. The default policy, accept-new, trusts a host's key on first contact and pins it, then refuses to connect if that key later changes β which is the usual man-in-the-middle signal, bestie, do not ignore her. Set ssh_host_key_policy = strict (or pass --ssh-host-key-policy strict) to require that the host already be present in known_hosts and refuse any unknown host.
Under sudo, host keys are verified and pinned against the invoking operator's ~/.ssh/known_hosts (not root's), so the trust you established interactively still applies. Operator ssh_opts are honored too, so an explicit StrictHostKeyChecking in there takes precedence over the tool's default.
SSH ControlMaster sockets are created in an unpredictable, private (0700) directory β preferring $XDG_RUNTIME_DIR β and they're removed when the connection closes, so a local user can't hijack the multiplexed connection. The internal command lock is likewise placed in a private per-user directory instead of a predictable /tmp path. And it is left in place after a run, deliberately: it's an flock, which excludes by inode, and removing the file while another process is waiting on it would let two processes each lock a different file at the same path. so yeah, she stays. π
π RAW TARGETS π
So likeβ¦ normal targets need btrfs receive on the other end, right? Which is great until the other end is literally just an NFS share living its best life. Raw targets are the fix: they write the btrfs send stream straight into files, no btrfs receive involved, periodt. That means you can back up onto non-btrfs filesystems β NFS, SMB, cloud storage, whatever β and optionally squeeze in compression and encryption. Iconic behaviour honestly. π
URL schemes
raw:///pathβ a local raw target. Yes that's three slashes, she's built different, don't touch it.raw+ssh://user@host/pathβ remote raw target, but make it β¨SSHβ¨.
Configuration options
compressβ which compression method to use:gzip,pigz,zstd,lz4,xz,lzo,bzip2,pbzip2.encryptβ which encryption method to use:gpg,openssl_enc.gpg_recipientβ the GPG key recipient. Required if you're doinggpgencryption, no skipping it bestie.gpg_keyringβ optional GPG keyring path.openssl_cipherβ the OpenSSL cipher (default:aes-256-cbc).
Example raw target configuration
[[volumes.targets]]
path = "raw:///mnt/nas/backups/home"
compress = "zstd"
encrypt = "gpg"
gpg_recipient = "backup@example.com"
For OpenSSL encryption, the passphrase comes from an environment variable, so go ahead and export that vibe:
export BTRFS_BACKUP_PASSPHRASE="your_passphrase"
# or (btrbk compatible)
export BTRBK_PASSPHRASE="your_passphrase"
File naming convention
She has a whole naming system and it's actually so satisfying to look at:
snapshot-name.btrfs # No compression/encryption
snapshot-name.btrfs.zst # Compressed with zstd
snapshot-name.btrfs.gpg # GPG encrypted
snapshot-name.btrfs.zst.gpg # Compressed + GPG encrypted
snapshot-name.btrfs.enc # OpenSSL encrypted
snapshot-name.btrfs.zst.enc # Compressed + OpenSSL encrypted
β¨ EXAMPLES β¨
Okay here's the greatest hits, use them, screenshot them, study them π
- Run all backup jobs:
btrfs-backup-ng run
- Create snapshots only:
btrfs-backup-ng snapshot
- Run with compression and rate limiting:
btrfs-backup-ng run --compress zstd --rate-limit 50M
- List all snapshots:
btrfs-backup-ng list
- Validate configuration:
btrfs-backup-ng config validate
- Install hourly timer:
sudo btrfs-backup-ng install --timer hourly
- Restore from backup:
btrfs-backup-ng restore ssh://server:/backups/home /mnt/restore
- Estimate backup sizes:
btrfs-backup-ng estimate --volume /home
- Estimate with space check:
btrfs-backup-ng estimate --volume /home --check-space
- Detect btrfs subvolumes:
sudo btrfs-backup-ng config detect
π¦ FILES π¦
Where she keeps her stuff, the whole tour π«Ά
~/.config/btrfs-backup-ng/config.tomlβ user configuration file./etc/btrfs-backup-ng/config.tomlβ system-wide configuration file./var/log/btrfs-backup-ng.logβ the default log file location, that's where the drama gets recorded.~/.local/share/btrfs-backup-ng/transactions.jsonlβ transaction log for user installations./var/lib/btrfs-backup-ng/transactions.jsonlβ transaction log for system installations.
π EXIT STATUS π
She tells you how it went, no mind games:
0β success. ate and left no crumbs π1β general error. not the vibe.2β configuration error. bestieβ¦ check your config first, I'm begging π
π SEE ALSO π
Go read your siblings, they're all iconic:
btrfs-backup-ng-run(1), btrfs-backup-ng-snapshot(1), btrfs-backup-ng-transfer(1), btrfs-backup-ng-prune(1), btrfs-backup-ng-list(1), btrfs-backup-ng-status(1), btrfs-backup-ng-restore(1), btrfs-backup-ng-verify(1), btrfs-backup-ng-estimate(1), btrfs-backup-ng-config(1), btrfs-backup-ng-install(1), btrfs(8), btrfs-send(8), btrfs-receive(8)
π BUGS π
Found a bug? Not her fault (jk, maybe) β report it at https://github.com/berrym/btrfs-backup-ng/issues and she'll handle it π«Ά
π AUTHORS π
- Michael Berry
<trismegustis@gmail.com>(2024-present) - Robert Schindler
<r.schindler@efficiosoft.com>(2017) - Chris Lawrence
<lawrencc@debian.org>(2014, original author)
β COPYRIGHT β
Copyright (C) 2014-2026 Chris Lawrence, Robert Schindler, Michael Berry. Licensed under the MIT License.
And that's a wrap on btrfs-backup-ng, bestie β¨ this whole page dropped as btrfs-backup-ng, January 2026, and it lives in section BTRFS-BACKUP-NG(1) β go forth, back up your subvolumes, and stay slaying ππΈ
π¦ where this page comes from
- fedora 43: btrfs-backup-ng 0.9.20-2.fc43 Β· MIT
- fedora 44: btrfs-backup-ng 0.9.20-1.fc44 Β· MIT
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms