Skip to main content
RunBook Academy

← All labs in Linux

Lab · intermediate · ~90 min

Lab: Backup tools — rsync, Borg, and Restic

B · Nested virtualisationC · Simulation

Objectives

  • Choose the right tool for a given backup shape
  • Run rsync --link-dest to make nightly targets that look like full backups but share hardlinks with previous days
  • Initialise a Borg repository, run an incremental backup, prune old archives
  • Initialise a Restic repository, snapshot, restore a single file, verify with check
  • Restore from each tool and confirm the restored file matches the source byte-for-byte

Prerequisites

What this lab is

You will build three backup repositories from the same source data, restore a single file from each, and confirm the restored bytes match. The tools cover three different shapes of backup problem:

  1. rsync —link-dest — local filesystem snapshots that look like full backups but share hardlinks with previous days. Cheap, no encryption, no compression, no dedup across machines. Good for on-host backups of small datasets.
  2. Borg — encrypted, authenticated, content-defined-chunked backups with deduplication and compression. Good for offsite or remote backups of a single host to a remote server.
  3. Restic — also encrypted and content-defined-chunked, with snapshots that copy-on-write, plus a built-in check that walks the entire repository to verify integrity. Good for the same shape of problem as Borg, with a friendlier command line and built-in verification.

The lesson this lab reinforces: backups that are not exercised are backups that do not exist. The lab’s deliverable is a restore test, not a backup test.

Setup

A scratch directory with three files of different sizes and shapes:

SRC=/var/tmp/backup-lab
mkdir -p "$SRC"
# 50 MiB sparse file
truncate -s 50M "$SRC/big.bin"
# 200 small files
for i in $(seq 1 200); do echo "line $i" > "$SRC/small_$i.txt"; done
# A file we will modify between backups to test incremental behaviour
echo "version 1" > "$SRC/changelog.md"
du -sh "$SRC"

The plain rsync -a SRC DEST/ shape is not a backup tool, it is a copy tool. The lab’s first job is to replace that with the --link-dest form so that yesterday’s data is shared with today’s target via hardlinks.

BACKUP=/var/tmp/backup-rsync
mkdir -p "$BACKUP"

# First backup: a full copy.
rsync -a --link-dest="$BACKUP/last" "$SRC/" "$BACKUP/$(date +%F)/"
# Save the name for the next run.
ln -sfn "$(date +%F)" "$BACKUP/last"

# Modify a file and run a second backup.
echo "version 2" > "$SRC/changelog.md"
rsync -a --link-dest="$BACKUP/last" "$SRC/" "$BACKUP/$(date +%F)/"
ln -sfn "$(date +%F)" "$BACKUP/last"

Inspect:

# Each dated directory looks like a full backup.
ls "$BACKUP/2026-08-12"
ls "$BACKUP/2026-08-13"

# But the disk usage is roughly the size of one copy + the deltas.
du -sh "$BACKUP"/*
du -sh "$BACKUP"

# A file that did not change is hardlinked; inode count proves it.
ls -li "$BACKUP/2026-08-12/big.bin"
ls -li "$BACKUP/2026-08-13/big.bin"
# Both should share an inode number.

Step 2 — Borg [UNVERIFIED]

Borg is the right shape for a single host backing up to a remote server over SSH. It encrypts the data, deduplicates it across archives, and lets you prune old archives while keeping the ones that matter.

export BORG_REPO=/var/tmp/backup-borg
export BORG_PASSPHRASE='lab-only-do-not-reuse-in-production'

borg init --encryption=repokey "$BORG_REPO"

# First archive.
borg create --stats --list "$BORG_REPO::$(hostname)-$(date +%F-%H%M)" "$SRC"

# Modify a file and back up again.
echo "version 2" > "$SRC/changelog.md"
borg create --stats "$BORG_REPO::$(hostname)-$(date +%F-%H%M)" "$SRC"

borg list "$BORG_REPO"

Prune old archives. Keep the last 7 daily:

borg prune --keep-daily=7 --keep-weekly=4 --keep-monthly=6 "$BORG_REPO"

Restore:

# List the contents of an archive.
borg list "$BORG_REPO::$(hostname)-2026-08-12-1200"

# Extract one file.
borg extract "$BORG_REPO::$(hostname)-2026-08-12-1200" "changelog.md"
# Restore to a directory by changing into it first.
mkdir -p /tmp/borg-restore && cd /tmp/borg-restore
borg extract "$BORG_REPO::$(hostname)-2026-08-12-1200"
diff -r /tmp/borg-restore "$SRC" && echo "restore matches"

Step 3 — Restic [UNVERIFIED]

Restic covers the same shape of problem as Borg with a different command surface. Its check is the differentiator: it walks the repository and verifies every chunk, on demand.

export RESTIC_REPOSITORY=/var/tmp/backup-restic
export RESTIC_PASSWORD='lab-only-do-not-reuse-in-production'
restic init

restic backup "$SRC"

echo "version 2" > "$SRC/changelog.md"
restic backup "$SRC"

restic snapshots

Restore:

mkdir -p /tmp/restic-restore && cd /tmp/restic-restore
restic restore latest --target .
diff -r . "$SRC" && echo "restore matches"

# Restore a single file from a specific snapshot.
restic restore <snapshot-id> --target /tmp/restic-restore-file --include changelog.md

Verify:

restic check

restic check exits non-zero if any chunk is unreadable or its hash does not match. Run it on a schedule.

Acceptance criteria

  • Three backup trees produced, three restores verified by diff -r.
  • rsync disk-usage evidence: du -sh for the last tree versus the sum of its dated copies.
  • Borg prune output recorded.
  • restic check output recorded.
  • A short decision note: which tool fits the host’s backup shape, and how often the maintainer will run check / verify.

Deliverables

  • · A daily snapshot tree built with rsync --link-dest, with disk-usage evidence vs a plain rsync copy
  • · A Borg repository with three dated archives and a prune that retains the last 7
  • · A Restic snapshot list, a single-file restore, and a `restic check` output
  • · A note on which tool fits which shape of backup problem

Verification status

Last reviewed
2026-08-09
Executed end to end
not yet run on hardware

The commands and configuration here have been reviewed against the verified software versions, but nobody has run this lab start to finish on a system meeting its prerequisites. Treat the Expected Outcome as the intended result rather than an observed one, and keep the Cleanup section to hand.