Eric Radman : a Journal

FFS Backup

For large data sets, home directories, or backups, ZFS has a wide range of supurb features. But if an advanced file system is not available, as FFS on OpenBSD or EXT2/3/4 on Linux can also be used. For backups the goal will be to maintain three copies that guard against hardware failure and human error.

  1. Working set (on user workstation)
  2. Primary backup (on SSD)
  3. Secondary backup (SSD or spinning disk)

OpenBSD RAID

In this example disks are concatenated to make to make a larger volume

fdisk -gy /dev/rsd0c
fdisk -gy /dev/rsd1c
fdisk -gy /dev/rsd2c

echo 'RAID *' | disklabel -wAT- sd0
echo 'RAID *' | disklabel -wAT- sd1
echo 'RAID *' | disklabel -wAT- sd2

bioctl -c c -l /dev/sd0a,/dev/sd1a,/dev/sd2a softraid0

Configuring RAID5 is exactly the same, except with the flag -c 5.

fdisk -gy sd4
echo '/ssd *' | disklabel -wAT- sd4
doas newfs /dev/rsd4a

To reconstruct softraid devices, wipe the first megabyte

dd if=/dev/zero of=/dev/sd0c bs=1M count=1
dd if=/dev/zero of=/dev/sd1c bs=1M count=1
dd if=/dev/zero of=/dev/sd2c bs=1M count=1

Replication

To repliate data from primary to the secondary backup, schedule rsync(1) from /etc/daily.local (run at 01:30 by default)

# abort if file systems are not mounted
df -l /ssd | egrep -q '/ssd$' || exit 1
df -l /hdd | egrep -q '/hdd$' || exit 1

# copy from primary to secondary backup devices
/usr/local/bin/rsync -rlogpt --delete \
  --exclude ".snapshot" \
  /ssd/ /hdd

The delay in synchronizing these two file systems is important, since we do not want mistakes to be replicated immediately.

Inode Snapshots

rsync / openrsync have an important behavior: files are not overwitten in place. Instead temporary files are created and subsequently renamed. This means we can simulate a snapshot by creating hardlinks.

#!/bin/sh -u
# ffs-snapshot.sh

today=$(date +"%Y-%m-%d")

for fs in $(cd /ssd; ls -d *); do
    cd /ssd/$fs
    mkdir -p .snapshot
    # link file, excluding snap cache
    find . -type f ! -path "*/.snapshot/*" | grep -v '/Cache/' | cpio -pmdl /ssd/$fs/.snapshot/$today

    # keep last eight snapshots
    for snap in $(ls -dr /ssd/$fs/.snapshot/* | tail +8); do
        rm -rf /ssd/$fs/.snapshot/$snap
    done
done

cpio(1) often overlooked but it remains standard in all Unix-like distributions, and can combined with other tools in unique ways. Flags used here are

-p Copy files from one location to another
-m Restore modification times
-d Create intermediate directories as needed
-l Links files instead of copying

Because cpio reads a list of files on STDIN we can easily filter out directories that will not be included. ls(1) will display the number of references to each file

$ ls -li /ssd/eradman/{,.snapshot/*}/t14-1260p/.profile
49629792 -rw-r--r--  3 eradman  eradman  488 Nov 22 12:42 /ssd/eradman/.snapshot/2025-12-06/t14-1260p/.profile
49629792 -rw-r--r--  3 eradman  eradman  488 Nov 22 12:42 /ssd/eradman/.snapshot/2025-12-07/t14-1260p/.profile
49629792 -rw-r--r--  3 eradman  eradman  488 Nov 22 12:42 /ssd/eradman//t14-1260p/.profile