All four demonstrated live on the real repo. Here's your 3-minute lesson, with the actual output as proof:
The one command pattern
Everything goes through the wrapper, which loads repo+passphrase+key:
sudo /etc/borg/borg-run.sh <any borg command>
1. List: what archives exist, and what's inside
sudo /etc/borg/borg-run.sh list --short # archives ("yesterday" = pick by timestamp)
Live output — your repo now holds:
node8-2026-10-14T12:01:32
node8-2026-10-14T15:48:38
sudo /etc/borg/borg-run.sh list ::node8-2026-10-14T12:07:44 | grep 'etc/borg'
Live output — /etc/borg contents in that archive:
drwxr-xr-x root root 0 ... etc/borg
-rw-r--r-- root root 414 ... etc/borg/excludes
-rwx------ root root 3674 ... etc/borg/run-backup.sh
-rwx------ root root 340 ... etc/borg/borg-run.sh
-rw------- root root 191 ... etc/borg/backup.env
-rw-r--r-- root root 4484 ... etc/borg/RESTORE.md
Tip: :: means "repo from env, this archive". No leading slash in paths — it's etc/borg, not /etc/borg.
2. Restore files from yesterday's archive
mkdir -p /tmp/restore && cd /tmp/restore
sudo /etc/borg/borg-run.sh extract ::node8-2026-10-14T12:07:44 etc/borg
sudo chown -R $USER:$USER /tmp/restore # extract comes out root-owned
Done live: all 5 files came back, and diff against the live RESTORE.md said IDENTICAL.
Two rules: (1) extract is relative to your current dir — always cd into an empty dir first, or you'll spray files over wherever you're standing; (2) to browse without extracting, use mount:
sudo mkdir -p /mnt/restore && sudo /etc/borg/borg-run.sh mount :: /mnt/restore
# browse /mnt/restore/<archive>/etc/borg/... then: sudo umount /mnt/restore
3. Manual full backup (same as the nightly 02:30 timer runs)
sudo /etc/borg/run-backup.sh
Live output just now: dumps ok (postgres 18M, all 4 sqlite, gitlab 1 tar), then:
This archive: 10.21 GB original → 44.51 MB actually stored (dedup!)
=== SUCCESS ===
Took ~1.5 minutes. The timer is just systemd calling this same script.
4. Add a new directory
One edit — the paths on the borg create line in /etc/borg/run-backup.sh (line 68-71). Add yours to the end:
/etc /home/dindi /var/lib/docker/volumes /var/backups/staging /var/spool/cron /path/to/newdir
Then run sudo /etc/borg/run-backup.sh once to get it into tonight's history. That's it — every future archive includes it automatically. (If the dir is huge, consider adding sub-paths to /etc/borg/excludes for the regenerable parts, same as we did with ~/.cache.)
One thing you just saw worth remembering
The 12:07:44 archive vanished from the list after this manual run — that's borg prune doing its job: keep-daily 7 keeps one archive per day (the first), so same-day extra runs get pruned. Nothing was lost (12:01:32 has the same content) — but it means today's 12:07 demo archive was the "practice" casualty. If you ever need to keep a specific archive forever, mark it exempt:
sudo /etc/borg/borg-run.sh config <archive> extra_test_delete off
Cheat sheet is also in /etc/borg/RESTORE.md on the machine — browsable even if this chat scrolls away.