btrfs, linux, OYB software, shell

Easy sync BTRFS snapshots with btrfs-sync

To complement the last BTRFS tool btrfs-snp (which allows us to schedule snapshots), I would like to share a new tool to synchronize them locally or remotely  to achieve efficient data redundancy.

With btrfs-snp we can replicate our BTRFS snapshots in a different BTRFS system, and have a second copy of our versioned subvolume in a much more efficient manner than using the traditional rsync.


  • Local or remote sync through SSH
  • Simple syntax
  • Progress indication
  • Support for xz or pbzip2 compression in order to save bandwidth
  • Retention policy
  • Automatic incremental synchronization
  • Cron friendly


The syntax is similar to that of scp



Synchronize snapshots of home to a USB drive

Synchronize snapshots of home to a USB drive in another machine

Synchronize one snapshot of home to a USB drive in another machine

Synchronize only monthly snapshots of home to a USB drive in another machine

Use --verbose  to get more details


Daily synchronization over the internet, keep only last 50

Daily synchronization in LAN, mirror snapshot directory


Get the script and make it executable. You can do this in two lines, but better inspect it first. Don’t trust anyone blindly.

It is recommended to set up a designated user for receiving the snapshots that has sudoers access to the  btrfs  command.

  • Create a btrfs user at the both ends

  • Create a public key in your sending machine

  • Give passwordless access to the btrfs user at the remote machine.

  • Give permissions to the btrfs user to use the btrfs on both ends. Create a file

with the contents

If you want to run it from cron, you might have to install it first because some distributions have already completely replaced it by systemd timers.

This was the case for me in Arch Linux. In my case, I installed cronie.

cronie logs the output to the system log by default, but you can set an email system if you want old style cron mails.

Also, note that you can use chronic if you only want logging to occur only if something goes wrong.

Comparison with rsync

The main difference between these two methods is that BTRFS works at the block level, whereas rsync works at the file level.

Because rsync works with files, it will not detect things such as renaming or moving a file, so it can only send it again. Also, it needs to analyze the existing files at the destination to see if they have been updated or not.

In order to achieve this, it can either analyze modification dates and sizes, which is relatively fast, or compare checksum of file chunks at both ends which is more robust but slower. In any case, there will be a significant processing overhead when you are synchronizating a whole partition with many thousands of files.

A plus of this approach is that you are able to exclude certain files or folders, where BTRFS works by subvolumes in an all or nothing fashion.

BTRFS on the other hand understands blocks, and because it is a COW filesystem, it already knows what bytes have changed between a snapshot and the next. If we renamed the file, only some tiny metadata has changed, and BTRFS knows that we don’t need to transfer the whole file again, only those few bytes.

The same happens when a big file changes internally, such as an image file for a virtual machine where we have been working.

This is the same reason why snapshots in COW filesystems are so space efficient, allowing us to create instant safety copies of huge volumes that only takes extra space as we change the files in them.

Obviously a drawback is that you need a BTRFS filesystem at both ends, but why would we stick to an old generation filesystem where we now have more modern and featureful ones?



Author: nachoparker

Humbly sharing things that I find useful [ github dockerhub ]

8 Comments on “Easy sync BTRFS snapshots with btrfs-sync

  1. (removed markdown)

    Hey nacho,
    thanks for a great tool!

    unfortunately I cannot make it work

    created btrfs users on both machines
    to gain passwordless ssh access to the remote with i executed
    ssh-copy-id -i ~/.ssh/ btrfs@
    sudo -u btrfs ssh-copy-id btrfs@ didn’t work for me.
    Now being able to access ssh btrfs@ without a password and granting btrfs full sudo privileges on remote i try to run
    sudo btrfs-sync –verbose /media/backup_local btrfs@:/media/backup_remote/
    but get
    SSH access error to btrfs@ Do you have passwordless login setup, and adequate permissions for /media/backup_remote?
    on remote the folder /media/backup_remote is owned by btrfs and permissions are set to 777

    what do I do wrong?
    Local machine: PRETTY_NAME=”Raspbian GNU/Linux 9 (stretch)”
    Remote machine: PRETTY_NAME=”Debian GNU/Linux 10 (buster)” (ncp installed via softy)


  2. Why does the script want to be run via sudo? What is the need when you already have given passwordless sudo rights to the btrfs user on both machines? I thought the precise purpose of setting up the btrfs user was that you don’t have to ssh as root. If the script is run via sudo, the ssh command is of course also executed by root not by btrfs. Thefore one would have to add root’s pubkey to .ssh/authorized_keys on the target machine, not btrfs’ as the ssh-copy-id command above does.
    But again, if the whole script is run via sudo, there is no point in granting sudo rights to the btrfs command to user btrfs. What is the idea here?

Leave a Reply

Your email address will not be published. Required fields are marked *