Btrfs

Setup encrypted external drive for backups

Prepare the external drive

sudo cryptsetup --type luks2 -y -v luksFormat /dev/sda1
sudo cryptsetup -v luksOpen /dev/sda1 cryptbackup
sudo mkfs.btrfs /dev/mapper/cryptbackup
sudo mkdir /srv/backup
sudo mount -o noatime,compress=zstd:1 /dev/mapper/cryptbackup /srv/backup
sudo restorecon -Rv /srv/backup

Setup /etc/crypttab

sudo blkid -s UUID -o value /dev/sda1 | sudo tee -a /etc/crypttab

Add the following line to /etc/crypttab:

cryptbackup UUID=<UUID of /dev/sda1> none discard

Setup /etc/fstab

sudo blkid -s UUID -o value /dev/mapper/cryptbackup | sudo tee -a /etc/fstab

Add the following line to /etc/fstab:

UUID=<UUID of /dev/mapper/cryptbackup> /srv/backup btrfs compress=zstd:1,nofail 0 0

Reload the daemons:

sudo systemctl daemon-reload

Mount the filesystems:

sudo mount -av

btrfs-backup script

#!/usr/bin/env bash

LOGFILE="/var/log/btrfs-backup.log"
SNAP_DATE=$(date '+%Y-%m-%d_%H%M%S')

# Check if device is mounted
if ! grep "/srv/backup" /etc/mtab >/dev/null; then
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] Backup device is not mounted." | tee -a "$LOGFILE"
    notify-send -i computer-fail "Backup device is not mounted"
    exit 1
fi

create_snapshot() {
    if ! btrfs subvolume snapshot -r "$1" "${1}/.snapshots/$2-$SNAP_DATE" >/dev/null; then
        echo "[$(date '+%Y-%m-%d %H:%M:%S')] Error creating snapshot of $1" | tee -a "$LOGFILE"
        notify-send -i computer-fail "Error creating snapshot of $1"
        exit 1
    else
        echo "[$(date '+%Y-%m-%d %H:%M:%S')] Create snapshot of $1: OK" | tee -a "$LOGFILE"
    fi
}

send_snapshot() {
    mkdir -p "/srv/backup/$SNAP_DATE"
    if ! btrfs send -q "${1}/.snapshots/$2-$SNAP_DATE" | btrfs receive -q "/srv/backup/$SNAP_DATE"; then
        echo "[$(date '+%Y-%m-%d %H:%M:%S')] Error sending snapshot of $1 to /srv/backup" | tee -a "$LOGFILE"
        notify-send -i computer-fail "Error sending snapshot of $1 to /srv/backup"
        exit 1
    else
        echo "[$(date '+%Y-%m-%d %H:%M:%S')] Send snapshot of $1 to /srv/backup: OK" | tee -a "$LOGFILE"
    fi
}

# Create root and home snapshots
create_snapshot "/" "root"
create_snapshot "/home" "home"

# Send root and home snapshots
send_snapshot "/" "root"
send_snapshot "/home" "home"

Move/copy the script to /etc/cron.daily/btrfs-backup.

Collected with ❤ by Jeffrey Serio

Last updated: 2024-04-23 Tue 18:03

Emacs 29.3 (Org mode 9.6.24)