Btrbk incremental snapshots to external usb - nutthawit/alpine-dotfile GitHub Wiki

Automatically make incremental Btrfs snapshots to the thumb drive for external backup.

In this section, we will create udev rules to automatically make incremental Btrfs snapshots to the thumb drive when it is plugged in.

Prerequisite

Btrbk setup

Udev rule mount USB drive automatically

Configuration

Format the thump drive to btrfs (assume you thumb drive mount on /dev/sda)

DISK=/dev/sda
USB=/dev/sda1

alias p="parted -sa optimal ${DISK}"
p mklabel gpt
p mkpart p 0G 100%
mkfs.btrfs -f -L btr_backup -n 32k ${USB}

The -L option is just a label, which you are free to change.

Prepare directory for store snapshots. We will use /mnt/btr_backup as the path to mount the thumb drive when it is plugged in.

BACKUP=/mnt/btr_backup

mkdir ${BACKUP}
mount ${USB} ${BACKUP} -t btrfs -o rw,subvolid=5
mkdir "${BACKUP}/x509fa"
mkdir "${BACKUP}/lat3430"

Note

I created two separate directories inside the thumb drive to separate the backups for my Asus and Dell laptops.

Create btrbk configure file that target to usb

cat << EOF > /etc/btrbk/btrbk-usb.conf
# Snapshot to usb

compat busybox

timestamp_format long

snapshot_dir /mnt/btr_pool/btrbk_snapshots
subvolume /mnt/btr_pool/@
target /mnt/btr_backup/x509fa
EOF

target is directory where the backup subvolumes are to be created. read more on man 5 btrbk.conf

Install eudev

apk add eudev eudev-doc

Create udev rule

cat << EOF > /etc/udev/rules.d/10-usb-automount.rules
SUBSYSTEM=="block", ATTRS{idVendor}=="0951", ACTION=="add", RUN+="/usr/local/bin/btrbk-create-incremental-backup-to-usb"
EOF

If you never create a udev rule before, you can start by this article

Note

0951 is Kingston vendor ID

Create a dependencies script named get-kingston-usb-node. This script will return /dev/sdXY when I plug in the Kingston USB drive that I use to store the backup.

cat << EOF > /usr/local/bin/get-kingston-usb-node
#!/bin/ash

# This should be return: sdXY
KINGSTON_SDA_CMD=$(ls -l /dev/disk/by-label/ | awk '{print $NF}' | grep sda | sed 's|^../../||')

echo /dev/${KINGSTON_SDA_CMD}

# Exit with the status of the last executed command (optional, but good practice)
exit $?
EOF
chmod +x /usr/local/bin/get-kingston-usb-node

Lastly, create a script that called by udev rule

cat << EOF > /usr/local/bin/btrbk-create-incremental-backup-to-usb
#!/bin/ash

# Mount Kingston usb to backup path
mount $(/usr/local/bin/get-kingston-usb-node) /mnt/btr_backup -t btrfs -o rw,subvolid=5

# Create incremental backup to usb
exec /usr/bin/btrbk -c /etc/btrbk/btrbk-usb.conf -q run
EOF
chmod +x /usr/local/bin/btrbk-create-incremental-backup-to-usb

Restart udev and test rule by:

udevadm control --reload
udevadm test /dev/sda1


calling: test
version 3.2.14
This program is for debugging only, it does not run any program
specified by a RUN key. It may show incorrect results, because
some values may be different, or not available at a simulation run.

 does not exist, please run udevadm hwdb --update
Load module index
timestamp of '/etc/udev/rules.d' changed
Reading rules file: /etc/udev/rules.d/10-usb-automount.rules
Reading rules file: /usr/lib/udev/rules.d/50-udev-default.rules
Reading rules file: /usr/lib/udev/rules.d/60-autosuspend.rules
Reading rules file: /usr/lib/udev/rules.d/60-block.rules

Counting backward from the end of the output to line 4, you will see that your rule is being read without error.

Now unplug your thumb drive, and reboot a Linux machine.

When your system is back online, plug in your thumb drive and run following command:

lsblk

NAME        MAJ:MIN RM   SIZE RO TYPE MOUNTPOINTS
sda           8:0    1 115.2G  0 disk
└─sda1        8:1    1 115.2G  0 part /mnt/btr_backup

You should see /dev/sda1 mounted at /mnt/btr_backup.

Now if you look at /mnt/btr_backup/x509fa you will see the same number of snapshots as in /mnt/btr_pool/btrbk_snapshots.

ls /mnt/btr_backup/x509fa/

@.20250928T2345    @.20250929T0830    @.20250929T1000    @.20250929T1130    @.20250929T1300    @.20250929T1430    @.20250929T1445_1  @.20250929T1454    @.20250929T2035
@.20250929T0000    @.20250929T0900    @.20250929T1030    @.20250929T1200    @.20250929T1330    @.20250929T1441    @.20250929T1446    @.20250929T1454_1  @.20250929T2035_1
@.20250929T0800    @.20250929T0930    @.20250929T1100    @.20250929T1230    @.20250929T1400    @.20250929T1445    @.20250929T1447    @.20250929T1454_2


ls /mnt/btr_pool/btrbk_snapshots/

@.20250929T0800    @.20250929T1000    @.20250929T1200    @.20250929T1330    @.20250929T1430    @.20250929T1445    @.20250929T1446    @.20250929T1454    @.20250929T1454_2  @.20250929T2035_1
@.20250929T0900    @.20250929T1100    @.20250929T1300    @.20250929T1400    @.20250929T1441    @.20250929T1445_1  @.20250929T1447    @.20250929T1454_1  @.20250929T2035    @.20250929T2100

Important

This incremental process may take time, depending on the number of your snapshots. You should wait until the last snapshot is received, which you can notice when the name of the last snapshot in the backup directory is the same as the one in the local snapshot directory.

Notice that my backup (/mnt/btr_backup/x509fa) has more snapshots than the local snapshots because my local snapshots are cleaned according to the configuration in /etc/btrbk/btrbk.conf.


Backup both local and USB while USB is plugged

Currently, when you plug in the USB drive, udev executes only once. This means that snapshots are taken to both local storage and the USB drive only one time when the drive is plugged in. If you wish to take snapshots to both local storage and the USB drive repeatedly while the USB is connected, you need to update the btrbk cron job (/etc/periodic/30min/btrbk) like this:

#!/bin/sh

# If /mnt/btr_backup is mounted do backup to local and usb
if mountpoint -q /mnt/btr_backup; then
    exec /usr/bin/btrbk -c /etc/btrbk/btrbk-usb.conf -q run
else
    exec /usr/bin/btrbk -q run
fi

Restart crond

rc-service crond restart

Restore backup

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 /mnt/btr_pool/@.

Identify Subvolume

# list snapshots managed by btrbk
btrbk list snapshots

# alternative: list all subvolumes
btrbk ls /
btrbk ls -L /

Restore Backup

# copy snapshots from local mounted backup drive
btrfs send /mnt/btr_backup/x509fa/@.20250928T2345 | btrfs receive /mnt/btr_pool/

# move (don't remove) current root subvolume away
mv /mnt/btr_pool/@ /mnt/btr_pool/@.CURRENT

# create read-write subvolume
btrfs subvolume snapshot /mnt/btr_pool/@.20250928T2345 /mnt/btr_pool/@

Reboot a machine

TODO

  1. When USB is plugged, create dialog with 2 options, 1 for snapshot immediately with take name as argument, 2 select local snapshot that you want to send to usb
⚠️ **GitHub.com Fallback** ⚠️