Tool for creating snapshots and remote backups of btrfs subvolumes
Btrbk is a backup tool for btrfs subvolumes, taking advantage of btrfs specific capabilities to create atomic snapshots and transfer them incrementally to your backup locations.
The source and target locations are specified in a config file, which allows to easily configure simple scenarios like "laptop with locally attached backup disks", as well as more complex ones, e.g. "server receiving backups from several hosts via ssh, with different retention policy".
Btrbk is designed to run as a cron job for triggering periodic snapshots and backups, as well as from the command line (e.g. for instantly creating additional snapshots).
Btrbk is a single perl script, and does not require any special installation procedures or libraries. Download the latest btrbk source tarball, or try latest master:
wget https://raw.githubusercontent.com/digint/btrbk/master/btrbk chmod +x btrbk sudo ./btrbk ls /
For more information, read the installation documentation.
Please consult the btrbk(1) man-page provided with this package for a full description of the command line options.
btrbk, you will need to create a configuration file. You might want to take a look at
btrbk.conf.exampleprovided with this package. For a detailed description, please consult the btrbk.conf(5) man-page.
When playing around with config-files, it is highly recommended to check the output using the
dryruncommand before executing the backups:
btrbk -c /path/to/myconfig -v dryrun
This will read all btrfs information on the source/target filesystems and show what actions would be performed (without writing anything to the disks).
In this example, we assume you have a laptop with:
/mnt/btr_pool, containing a subvolume
rootfsfor the root filesystem (i.e. mounted on
/) and a subvolume
homefor the user data,
/mnt/btr_pool/btrbk_snapshotswhich will hold the btrbk snapshots,
/mnt/btr_backup, containing a subvolume or directory
mylaptopfor the incremental backups.
snapshot_preserve_min 2d snapshot_preserve 14d
target_preserve_min no target_preserve 20d 10w *m
volume /mnt/btr_pool target /mnt/btr_backup/mylaptop subvolume rootfs subvolume home [...]
#!/bin/sh exec /usr/bin/btrbk -q -c /etc/btrbk/btrbk-mylaptop.conf run
If you want the snapshots to be created only if the backup disk is attached, simply add the following line to the config:
For a quick additional snapshot of your home, run:
# btrbk snapshot home
Let's say you have a fileserver at "myserver.mydomain.com" where you want to create backups of your laptop disk, the config would look like this:
volume /mnt/btr_pool subvolume rootfs target /mnt/btr_backup/mylaptop target ssh://myserver.mydomain.com/mnt/btr_backup/mylaptop
In addition to the backups on your local usb-disk mounted at
/mnt/btr_backup/mylaptop, incremental backups would also be pushed to
If you're a sysadmin and want to trigger backups directly from your fileserver, the config would be something like:
volume ssh://alpha.mydomain.com/mnt/btr_pool target /mnt/btr_backup/alpha subvolume rootfs subvolume home
volume ssh://beta.mydomain.com/mnt/btr_pool target /mnt/btr_backup/beta subvolume rootfs subvolume dbdata
This will pull backups from alpha/beta.mydomain.com and locally create:
If all you want is to create snapshots of your home directory on a regular basis:
timestamp_format long snapshot_preserve_min 18h snapshot_preserve 48h 20d 6m
volume /mnt/btr_pool snapshot_dir btrbk_snapshots subvolume home
#!/bin/sh exec /usr/bin/btrbk -q run
Note that you can run btrbk more than once an hour, e.g. by calling
sudo btrbk runfrom the command line. With this setup, all those extra snapshots will be kept for 18 hours.
Let's say we have a host (at 192.168.0.42) running btrbk with the setup of the time-machine example above, and we need a backup server to only fetch the snapshots.
/etc/btrbk/btrbk.conf (on backup server):
target_preserve_min no target_preserve 0d 10w *m
volume ssh://192.168.0.42/mnt/btr_pool target /mnt/btr_backup/my-laptop subvolume home snapshot_dir btrbk_snapshots snapshot_preserve_min all snapshot_create no
If the server runs btrbk with this config, 10 weeklies and all monthlies are received from 192.168.0.42. The source filesystem is never altered because of
Common virtual machine setups have multiple volume sections with same host, but distinct port numbers for each machine.
# This propagates to all subvolume sections: target /mnt/btr_backup/
volume ssh://localhost:2201/mnt/btr_pool group vm vm01 subvolume home snapshot_name vm01-home subvolume data snapshot_name vm01-data
volume ssh://localhost:2202/mnt/btr_pool group vm vm02 subvolume home snapshot_name vm02-home
volume ssh://localhost:2203/mnt/btr_pool [...]
This will create
Note that btrbk holds a single reference to every btrfs filesystem tree, regarding UUID's as "globally unique". If the configured subvolumes point to the same filesystem on different machines (ports), you will see log lines like this when running
Assuming same filesystem: "ssh://localhost:2201/dev/sda1", "ssh://localhost:2202/dev/sda1"
If you want to make backups from a filesystem other than btrfs (e.g. ext4 or reiserfs), you need to create a synchronization subvolume on the backup disk:
# btrfs subvolume create /mnt/btr_backup/myhost_sync
Configure btrbk to use
myhost_syncas source subvolume:
volume /mnt/btr_backup subvolume myhost_sync snapshot_name myhost
snapshot_preserve_min latest snapshot_preserve 14d 20w *m
The btrbk package provides the "btrbk-mail" script, which automates the synchronization using rsync, and can be run as cron job or systemd timer unit. For configuration details, see the config section in "/contrib/cron/btrbk-mail".
Alternatively, you can run any synchronization software prior to running btrbk. Something like:
#!/bin/sh rsync -az --delete \ --inplace --numeric-ids --acls --xattrs \ -e 'ssh -i /etc/btrbk/ssh/id_rsa' \ myhost.mydomain.com:/data/ \ /mnt/btr_backup/myhost_sync/
exec /usr/bin/btrbk -q run
This will produce snapshots
/mnt/btr_backup/myhost.20150101, with retention as defined with the snapshot_preserve option.
If your backup server does not support btrfs, you can send your subvolumes to a raw file.
This is an experimental feature: btrbk supports "raw" targets, meaning that similar to the "send-receive" target the btrfs subvolume is being sent using
btrfs send(mirroring filesystem level data), but instead of instantly being received (
btrfs receive) by the target filesystem, it is being redirected to a file, optionally compressed and piped through GnuPG.
raw_target_compress xz raw_target_encrypt gpg gpg_keyring /etc/btrbk/gpg/pubring.gpg gpg_recipient [email protected]
volume /mnt/btr_pool subvolume home target raw ssh://cloud.example.com/backup ssh_user btrbk # incremental no
This will create a GnuPG encrypted, compressed files on the target host. For each backup, two files are created:
/backup/home.YYYYMMDD.btrfs.xz.gpg: main data file containing the btrfs send-stream,
/backup/home.YYYYMMDD.btrfs.xz.gpg.info: sidecar file containing metadata used by btrbk.
I you are using raw incremental backups, please make sure you understand the implications (see btrbk.conf(5), TARGET TYPES).
Since btrbk needs root access, it is very advisable to take all the security precautions you can. In most cases backups are generated periodically without user interaction, so it is not possible to protect your ssh key with a password. The steps below will give you hints on how to secure your ssh server for a backup scenario. Note that the
btrbkexecutable is not needed on the remote side, but you will need the
btrfsexecutable from the btrfs-progs package.
On the client side, create a ssh key dedicated to btrbk, without password protection:
ssh-keygen -t rsa -b 2048 -f /etc/btrbk/ssh/id_rsa -C [email protected] -N ""
The content of the public key (/etc/btrbk/ssh/idrsa.pub) is used for authentication in "authorizedkeys" on the server side (see sshd(8) for details).
Btrbk comes with a shell script "sshfilterbtrbk.sh", which restricts ssh access to sane calls to the "btrfs" command needed for snapshot creation and send/receive operations (see sshfilterbtrbk(1)).
Copy "sshfilterbtrbk.sh" to "/backup/scripts/", and configure sshd to run it whenever the key is used for authentication. Example "/root/.ssh/authorized_keys":
# example backup source (also allowing deletion of old snapshots) command="/backup/scripts/ssh_filter_btrbk.sh -l --source --delete" ...
example backup target (also allowing deletion of old snapshots)
command="/backup/scripts/ssh_filter_btrbk.sh -l --target --delete" ...
example fetch-only backup source (snapshot_preserve_min=all, snapshot_create=no),
restricted to subvolumes within /home or /data
command="/backup/scripts/ssh_filter_btrbk.sh -l --send -p /home -p /data" ...
Create a user dedicated to btrbk and add the public key to "/home/btrbk/.ssh/authorized_keys". In "btrbk.conf", choose either:
backend btrfs-progs-btrbkto use separated binaries with elevated privileges (suid or fscaps) instead of the "btrfs" command (see btrfs-progs-btrbk).
backend btrfs-progs-sudo, configure "/etc/sudoers" and add the
You might also want to restrict ssh access to a static IP address within your network:
For even more security, set up a chroot environment in "/etc/ssh/sshdconfig" (see [sshdconfig(5)]).
Btrbk does not provide any mechanism to restore your backups, this has to be done manually. In the instructions below, we assume that you have a btrfs volume mounted at
/mnt/btr_pool, and the subvolume you want to restore is at
Important: don't use
btrfs property setto make a subvolume read-write after restoring. This is a low-level command, and leaves "Received UUID" in a false state which causes btrbk to fail on subsequent incremental backups. Instead, use
btrfs subvolume snapshot(without
-rflag) as described below.
# list snapshots managed by btrbk btrbk list snapshots
alternative: list all subvolumes
btrbk ls / btrbk ls -L /
From the list, identify the snapshot you want to restore. Let's say it's
(skip this step if you restore from a snapshot)
# locally mounted backup disk btrfs send /mnt/btr_backup/data.20150101 | btrfs receive /mnt/btr_pool/
from / to remote host
Hint: Try to send-receive backups incrementally if possible. In case you still have common snapshot / backup pairs (i.e. both "snapshotsubvol" and "targetsubvol" are listed above), use
btrfs send -p.
From this point on,
data.20150101on both disks can be used as parents for subsequent send-receive operations, and a received_uuid relationship is established (see below).
# if still present, move broken subvolume away mv /mnt/btr_pool/data /mnt/btr_pool/data.BROKEN
create read-write subvolume
btrfs subvolume snapshot /mnt/btr_pool/data.20150101 /mnt/btr_pool/data
datasubvolume is restored, you can carry on with incremental backups to
# if everything went fine, delete the broken subvolume btrfs subvolume delete /mnt/btr_pool/data.BROKEN
Make sure to keep
data.20150101subvolumes on both disks at least until you created a new backup using btrbk, in order to keep the incremental chain alive.
btrbk origin -t /mnt/btr_backup/data.20150101 btrbk ls -L /mnt/btr_pool /mnt/btr_backup
received_uuid relationship: correlated, identical read-only subvolumes, cross-filesystem.
a.received_uuid = b.received_uuid a.received_uuid = b.uuid
btrfs send | btrfs receive.
/mnt/btr_pool/data.20150101 === /mnt/btr_backup/data.20150101
parent_uuid relationship: "is-snapshot-of"
a.parent_uuid = b.uuid
btrfs subvolume snapshotor
btrfs send -p | btrfs receive.
Make sure to also read the btrbk FAQ page. Help improve it by asking!
So btrbk saved your day?
I will definitively continue developing btrbk for free, but if you want to support me you can do so:
The source code for btrbk is managed using Git.
git clone https://dev.tty0.ch/btrbk.git
Mirror on GitHub:
git clone https://github.com/digint/btrbk.git
Your contributions are welcome!
If you would like to contribute or have found bugs:
Any feedback is appreciated!
btrbk is free software, available under the GNU General Public License, Version 3 or later.