4

I'm planing to use btrfs send/receive to synchronize two filesystems and keep a few older snapshots (like a time machine) on the backup.

Now what happens if a user ask me to remove a file or directory from all the backup snapshots because it contains sensitive data?

I fear this is not possible to do that and still be able to use send/receive. Is this right?

ascobol
  • 288
  • 2
  • 14

1 Answers1

1

This is indeed possible (at least in my experiment, it worked).

First delete the file(s) on the send side, take a snapshot, and send/receive it using whatever existing snapshots are available for an incremental update.

Now you will have a snapshot on the remote side which doesn't have the file(s) in question, and you can use that for all future backups.

The last thing, is to remove the file(s) from all the old snapshots. The important part is not to touch the snapshot you just sent, with the files removed - because you need to keep that one unchanged to use it as a parent for future backups.

So, for each of the older snapshots on the receiving side, make them writable, delete the files, then (optionally) make them read-only again.

Here's a full set of commands showing the process on two dummy btrfs filesystem images:

set -x

echo "Make two btrfs images for our test"
dd if=/dev/zero bs=1M count=512 of=/tmp/img1.img
dd if=/dev/zero bs=1M count=512 of=/tmp/img2.img
losetup -f /tmp/img1.img
losetup -f /tmp/img2.img
mkfs.btrfs --mixed /dev/loop0
mkfs.btrfs --mixed /dev/loop1

echo "Mount them"
mkdir /tmp/sender /tmp/receiver
mount -t btrfs /dev/loop0 /tmp/sender
mount -t btrfs /dev/loop1 /tmp/receiver

btrfs subvolume create /tmp/sender/test

mkdir /tmp/sender/snaps
mkdir /tmp/receiver/snaps

echo "Create a 1 MB file, this is what we'll delete in the future"
dd if=/dev/urandom bs=1M count=1 of=/tmp/sender/test/f1

echo "Take our first snapshot, and send it"
btrfs subvolume snapshot -r /tmp/sender/test /tmp/sender/snaps/snap1
sync
btrfs send /tmp/sender/snaps/snap1 | btrfs receive /tmp/receiver/snaps

echo "Create a 2 MB file, snapshot, send and receive, using snap1 as parent"
dd if=/dev/urandom bs=2M count=1 of=/tmp/sender/test/f2
btrfs subvolume snapshot -r /tmp/sender/test /tmp/sender/snaps/snap2
sync
btrfs send -p /tmp/sender/snaps/snap1 /tmp/sender/snaps/snap2 | btrfs receive /tmp/receiver/snaps

echo "Now we can delete snap1 on the sender."
btrfs subvolume delete /tmp/sender/snaps/snap1

echo "Create a 3 MB file, snapshot send and receive, using snap2 as parent"
dd if=/dev/urandom bs=3M count=1 of=/tmp/sender/test/f3
btrfs subvolume snapshot -r /tmp/sender/test /tmp/sender/snaps/snap3
sync
btrfs send -p /tmp/sender/snaps/snap2 /tmp/sender/snaps/snap3 | btrfs receive /tmp/receiver/snaps

echo "Now we can delete snap2 on the sender."
btrfs subvolume delete /tmp/sender/snaps/snap2

echo "Delete the file we don't want anymore on the sender"
rm /tmp/sender/test/f1

echo "Snapshot, and send the deletion"
btrfs subvolume snapshot -r /tmp/sender/test /tmp/sender/snaps/snap4
btrfs send -p /tmp/sender/snaps/snap3 /tmp/sender/snaps/snap4 | btrfs receive /tmp/receiver/snaps

echo "Now we can delete snap3 on the sender - this will remove all reference to f1 on the sender"
btrfs subvolume delete /tmp/sender/snaps/snap3

echo "Confirm filesystem usage"
sync
btrfs filesystem du /tmp/sender/snaps/*
btrfs filesystem du /tmp/receiver/snaps/*

echo "Then, we can go and clean up the file in all backups on the receiver"
btrfs property set -t s /tmp/receiver/snaps/snap1 ro false
rm /tmp/receiver/snaps/snap1/f1
btrfs property set -t s /tmp/receiver/snaps/snap1 ro true

btrfs property set -t s /tmp/receiver/snaps/snap2 ro false
rm /tmp/receiver/snaps/snap2/f1
btrfs property set -t s /tmp/receiver/snaps/snap2 ro true

btrfs property set -t s /tmp/receiver/snaps/snap3 ro false
rm /tmp/receiver/snaps/snap3/f1
btrfs property set -t s /tmp/receiver/snaps/snap3 ro true

echo "Lastly, make sure incremental backups are still working against snap4"
echo "Create a 5 MB file, snapshot send and receive, using snap4 as parent"
dd if=/dev/urandom bs=5M count=1 of=/tmp/sender/test/f5
btrfs subvolume snapshot -r /tmp/sender/test /tmp/sender/snaps/snap5
sync
btrfs send -p /tmp/sender/snaps/snap4 /tmp/sender/snaps/snap5 | btrfs receive /tmp/receiver/snaps

echo "And see that usage is as we expect - all references to the 1MB file are gone."
sync
btrfs filesystem du /tmp/sender/snaps/*
btrfs filesystem du /tmp/receiver/snaps/*

echo "Clean up"
umount /tmp/sender /tmp/receiver
losetup -d /dev/loop0 /dev/loop1
rm /tmp/img1.img /tmp/img2.img
usedbytes
  • 11
  • 1