New command borg history --manifest
will list out all segment
entries that are PUTs of an all-zeroes key, along with their decrypted
values.
If a repo has been maintained strictly in an append-only manner, and no deletions attempted by an adversary with append-only access, then this will provide a listing of all archives that were ever created. If such an adversary attempts to delete an archive, they'll have to add a new manifest which omits an archive -- and that can be detected by comparing it to older, shadowed manifests.
The invariant can be maintained across authorized deletions if the rightful owner fully compacts after deletions. Process below.
- Verify integrity of recent backups via spot-checks or other situation-specific criteria
- Perform a
borg check
- With lock:
- Read the local list of known-deleted archive IDs (initially empty)
- Run the new
borg history --manifest
command - From the history output, confirm that the archive list only ever
grows from one version of the manifest to the next, or that any
dropped archive IDs are in the known-deleted list
- If there are any unexpected archive removals, log and and exit with an error -- this may be the sign of an attack
- Log this history locally for reference (since it will be lost)
- Choose which archives to prune
- Add them to the known-deleted list
- Perform the
borg delete
action - Perform
borg compact
with 0% threshold so that all DELETEs are compacted
Afterwards, there will only be a single manifest in the history, thanks to the compaction.
I never ever thought of nor ever wanted any of the recipe above to be automatic in any way. This is something for an admin to do manually, starting with disabling e.g. SSH key access to the repo to perform the "lock out any other access" step, setting up a fresh machine from trusted media to temporarily entrust with the repo keys for the remaining steps, etc.
Additionally, the "Verify integrity of all archives against existing integrity data" is the crucial and by far biggest step that is external anyway.