back 2017-01-08 Linuxbtrfs
  1. btrfs Snapshots and Backups
    1. Snapshots introduced
    2. Snapshots for Backups
      1. Backups to a none-btrfs target
        1. Out of space
        2. Untrusted target? Encryption!

btrfs Snapshots and Backups

One of the btrfs killer-features is snapshots and its CoW.
A Snapshot is a subvolume which has a parent subvolume.
It stores only the changes by creating a copy on writes.
Snapshots can be read-only.
Like any other subvolumes snapshots can be mounted.

Snapshots introduced

A Simple test run

# Create a snapshot
echo before snap > /home/$USER/test
btrfs subvolume snapshot /home /mnt/snaps/home-old
echo after snap > /home/$USER/test

cat /home/$USER/test
# after snap
cat /mnt/snaps/home-old/$USER/test
# before snap

as expected :)

btrfs subvolume delete /mnt/snaps/home-old

Snapshots for Backups

Snapshot are excellent for backups.

  • Since they are ordinary mounts we need no fancy tool for recovering.
    Just jump into the directory and pick the files you need.
  • No worry about permissions, ownerships, ACLs …
  • No need to iterate over ~1e12 small files and compare mtime.
  • No changes during the backup process

You’ll ask yourself: Backup on the same disk?
Of course not.
btrfs is capable to create a readable binary stream from a subvolume using btrfs send. It’s counterpart btrfs receive writes updates to a given subvolume. Additionally, it allows to transfer the difference between two snapshots:
btrfs send -p snapYesterday snapToday.
Note: btrfs-send needs read-only snapshots!

Assumed backup.home is a machine with btrfs and ssh. We can now transfer the subvolume over the network.

# Create a read-only snapshot
btrfs subvolume snapshot -r /home /mnt/backup
# Initially transfer the whole subvolume
btrfs send /mnt/backup | ssh root@backup.home btrfs receive /mnt/homeFromPC
# Transfer the changes since `backup`
btrfs subvolume snapshot -r /home /mnt/backup-new
btrfs send -p /mnt/backup /mnt/backup-new | ssh root@backup.home btrfs receive /mnt/homeFromPC

Neat, isn’t it?

A script could help to create daily backup snapshots, transfer them and delete the outdated. Fortunately there are nice tools around: Available Backup Tools

I picked btrbk cause its fits perfect for my case.

Backups to a none-btrfs target

Obviously, my target is not btrfs powered.
The solution is sshfs + image files.

# Mount the remote target
sshfs -o uid=0 -o gid=0 -o reconnect remote:backups /mnt/remote

# Create a image file (100GB)
dd if=/dev/zero of=/mnt/remote/btrfs-1.img bs=1 seek=100G count=1

# Make it btrfs
mkfs.btrfs /mnt/remote/btrfs-1.img

# Mount it
mount /mnt/remote/btrfs-1.img /mnt/backup

You could now use /mnt/backup as btrfs backup target.

Out of space

Time is passing, things are growing.
No Problem for btrfs.
Just add another device

# Create another image file: btrfs-2.img
dd if=/dev/zero of=/mnt/remote/btrfs-2.img bs=1 seek=100G count=1

# Add it 
btrfs device add /mnt/remote/btrfs-2.img /mnt/backup

# Check it
btrfs filesystem show /mnt/backup

Untrusted target? Encryption!

Thanks to the image files it is possible to add an encryption layer.

# Create a image file (100GB)
dd if=/dev/zero of=/mnt/remote/btrfs-1.img bs=1 seek=100G count=1

# Create a password key file
echo "my-32-char-super-secret-password" > /root/luksKey

# Encrypt the image
cryptsetup luksFormat --key-file=/root/luksKey /mnt/remote/btrfs-1.img

# Decrypt and create a mapper device
cryptsetup luksOpen --key-file=/root/luksKey /mnt/remote/btrfs-1.img backup_btrfs-1

You can now use the /dev/mapper/backup_btrfs-1 device to setup your encrypted remote btrfs backup target.

That’s it :)
PS: I use this setup currently on one of my Hetzner root servers in conjunction with a StorageBox.

Interesting posts

Another try of the btrfs filesystem
Nginx reverse proxy setup to host multiple applications using Docker
Installation and configuration of PsiTransfer