Backup Script

2023/10/09

I recently had my laptop’s SSD fail, and it took me a long time to get back up and running - partially because I tried to install and run Wayland instead of X (which worked out reasonably well - I ended up switching back to X mostly because OnlyOffice was super slow on Wayland/sway, but it seems to me like Wayland is coming within a couple of years!). But a lot of the issue was that I hadn’t made a proper backup in years, so I needed to remember how I had set up a ton of different software. I’d been using CloneZilla, which is basically a live disk that lets you clone entire disks/partitions, for backups, but there were some problems:

The upshot of this, and the biggest problem of all, was that I wasn’t actually using my backup software. After looking into alternatives, I’ve decided to switch to restic. The big disadvantage of restic is that it’s designed to back up files, not systems. Restic (unlike, for example, timeshift) doesn’t have a concept of “configuration” or “bootloader”, so to the extent that it’s capable of backing these things up, it is backing up files on the disk. So when this hard drive fails, restoring my system won’t be trivially easy. But in exchange for that, I get:

Based on my tests, I suspect that each incremental backup will take up something like 5 minutes and 100 MB, assuming I haven’t downloaded any huge files. To make creating backups (and eventually restoring them) easier, I wrote a script that:

  1. Uses yay -Qqe and yay -Qqm to export lists of explicitly installed repo and aur packages
  2. Uses restic to back up my home and /etc directories (hopefully backing up /etc and ~/.config captures most of my configuration files)
  3. Cleans up backups older than 1 year old

The script is adapted from the Arch Linux wiki, and I’ve included it below:

#!/bin/bash

if [[ -n $(pgrep 'restic' | grep 'restic backup') ]]; then
  echo 'restic is already running...' 1>&2
  exit 0
fi

if [ ! -d "$1" ]; then
  echo "Backup directory not found: $1"
  exit 1
fi
BACKUP_DIR="$1"

set -e
set -v

######
# Backup package list
######
PKG_DIR="$BACKUP_DIR/packages"
# set $date to string date
printf -v date '%(%Y-%m-%d)T' -1
# export only "official" packages
yay -Qqe | grep -v "$(yay -Qqm)" > "$PKG_DIR/$date.official.txt"
# export aur packages
yay -Qqm > "$PKG_DIR/$date.aur.txt"

######
# Restic backup
######

export RESTIC_REPOSITORY="$BACKUP_DIR/restic"
export RESTIC_PASSWORD='ResticBackup123'
export RESTIC_COMPRESSION='auto'
export RESTIC_CACHE_DIR=~/.cache/restic
export RESTIC_READ_CONCURRENCY=4

mkdir -p "${RESTIC_CACHE_DIR}"

restic unlock 
restic backup /etc /home/sam --exclude-file=/etc/restic/excludes.txt --tag scheduled --exclude='**/mnt'
restic check --with-cache --read-data-subset=5G
restic forget --prune --keep-within 1y

This script looks for a file containing patterns to exclude from the backup, which doesn’t come with restic: /etc/restic/excludes.txt. Mine looks like:

**/*cache
**/*Cache
**/lost+found
**/tmp
**/.Trash*
**/Trash*
**/trash*
**/.trash*
**/.venv