A Backup Without a Restore Test Is Decoration
One sentence, written in passing in a comment, sums up everything I have to say on the subject:
Don’t forget that a backup policy without regular restore tests is just decoration: you don’t know whether your backup works until you’ve restored it.
The rest of this article is merely the deployment of that sentence.
The only test that counts
A backup that has never been restored is not a backup, it is a hypothesis. The day you need it is exactly the day you cannot afford to discover that:
- the repository has been corrupted for six months,
- the encryption passphrase lives in the head of a former employee,
- the script has been silently failing for two years because the destination got renamed,
- the restore takes fifteen hours when your SLA asks for two (I lived it in this PowerDNS post-mortem ).
So the restore test has a cadence, not a calendar date: on every major change (new tool, new destination, new retention) and periodically on the existing setup. And it tests the full scenario: complete restore onto a blank machine, timed, with integrity verification of the restored data. Restoring “just one file” to reassure yourself is testing the thread of the parachute.
Git is already a backup (and a remote is just a URL)
Good instinct on the mirroring: git is distributed by design, so your local clone is already a full backup with the entire history.
And a remote is just a URL. Nothing prevents having several per repo:
git remote set-url --add origin git@forgejo.local:user/repo.git
One git push goes to every destination at once. You can even configure it per branch, or by named remote: origin to GitHub, backup to your Forgejo
, archive to a self-hosted GitLab/Gitea/Gitolite.
On the automation side, hooks (pre-push, post-commit) let you trigger whatever you want without depending on a third-party service: a post-push that syncs to a second remote or fires an rsync is three lines of shell.
That simplicity is why I often answer “you don’t even need a Forgejo to have a solid strategy”. Git mirroring covers source code; the rest of the system deserves better and that comes next.
The rest of the system: Restic, Borg, rsnapshot
For everything that is not a git repo, two tool families have proven themselves and I systematically recommend one:
- Restic (often paired with rclone for cloud destinations, the combo I use): native encryption, deduplication, snapshots, multiple destinations.
- Borg (and its ecosystem, including the associated snapshots): the historical reference, aggressive deduplication, compression.
- Plakar (FR, one to watch) and from the old world rsnapshot, which honestly beats a homemade rsync script: rotations and hardlinks handled properly where the homemade script simulates them.
What they all have in common: defined retention, encryption and a restore command that has been executed at least once. If your tool doesn’t tick those three boxes, the problem is not the tool, it is the policy.
Snapshots are not backups
A vocabulary precision that avoids tragedies: a Btrfs or ZFS snapshot is not a backup. It lives on the same storage, the same machine, the same pool. A disk failure, a power surge, a ransomware with write rights: the snapshot and the data leave together.
What snapshot-capable filesystems still bring and it is valuable: near-instant datasets and snapshots, letting you roll back on a logical mistake (a badly scoped rm -rf, a failed migration) without restoring the whole chain. It is a safety net at the instant level, not at the site level.
So: Btrfs or ZFS for snapshots and datasets on primary storage, Restic or Borg for the copy on another medium, with retention and encryption. The two layers replace nothing of each other.
The stable OS as part of the policy
A detail that is not secondary: the machine performing the backups and the one hosting them must be boring. A good Debian Stable or an Ubuntu LTS, nothing newer, nothing exotic. The replication of your backup policy must never depend on a freshly updated version.
A filesystem that snapshots, a good backup system, a stable operating system for the job: the three components, in that order of boringness.
Summary
- A backup policy without regular restore tests is decoration. The test is full, timed, on a blank machine and has a cadence.
- Git is distributed: your local clone is a full backup, a remote is just a URL and
git remote set-url --addgives you mirroring in one line. Hooks automate without third-party services. - Restic (+rclone) or Borg for the rest: encryption, deduplication, retention. Rsnapshot over a homemade rsync script.
- A Btrfs/ZFS snapshot is not a backup: same storage, same failure. It is instant rollback, not the remote copy.
- The OS that backs up is stable and boring: Debian Stable or Ubuntu LTS.
[edit: 2026] The Ansible implementation of all this: the plakar role .