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. Home directory
  2. Primary backup
  3. Secondary backup

Concat + Copy

Most RAID levels require all storage devices to use the same partition size, but drives of various sizes may be concatenated. Instead of using block-level mirroring (RAID 1), periodic synchronization between the two sets allows for recovery from human error.

  primary: sd1 (1TB) + sd2 (5TB)
secondary: sd3 (1TB) + sd4 (5TB)

OpenBSD RAIDc

In this example disks are concatenated to make to make a larger volume using OpenBSD RAID

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

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

bioctl -c c -l /dev/sd1a,/dev/sd2a softraid0
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/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

Manual Backup

For directories that rarely change a one-time snapshot can allow for recovery after a file has been unlinked

cd ~/Movies
find . -maxdepth 1 -type f | cpio -pmdl $PWD/.snapshot/
sudo chown root:root .snapshot/* .snapshot

0 blocks will indicate that no data was replicated.