Recover a single file from a damaged Borg archive
When a Borg repository gets corrupted, the instinct is to dump the whole thing back. That’s usually overkill if you just need one config file. Borg actually gives you a fine‑grained extraction tool that can pull a single file even from a partially broken archive.
1. Verify the repository
borg check /srv/backups/myrepo
borg check will surface any integrity problems. If you see corruption, you can try to fix it:
borg check --repair /srv/backups/myrepo
Caveat: --repair rewrites the archive. Make a copy of the damaged repo first. On a production box I usually skip repair and try extraction straight away.
2. Find the snapshot that contains the file
borg list /srv/backups/myrepo | grep -E '^[^:]+::'
That lists snapshot names. If you know the file’s path, narrow the hunt:
borg list /srv/backups/myrepo::2026-10-18T12:00:00Z | grep /etc/nginx/nginx.conf
If the file is missing from the latest snapshot, keep looking at older ones until you hit the right one.
3. Inspect the snapshot without extracting
borg extract --list /srv/backups/myrepo::2026-10-18T12:00:00Z
The --list flag prints every file that Borg can read from the archive. Scan the list for your target. If it appears, you’re good to go.
4. Extract the file
borg extract /srv/backups/myrepo::2026-10-18T12:00:00Z:/etc/nginx/nginx.conf
The syntax is <repo>::<snapshot>:<path>. Borg will create the directory hierarchy under the current working directory, so run the command from the root of your filesystem or give a destination with --destination:
borg extract --destination /tmp/restore /srv/backups/myrepo::2026-10-18T12:00:00Z:/etc/nginx/nginx.conf
If the file is large or you want to avoid pulling the whole tree, use --exclude to skip unrelated directories:
borg extract --exclude '**/*' --destination /tmp/restore /srv/backups/myrepo::2026-10-18T12:00:00Z:/etc/nginx/nginx.conf
5. When the file is missing or corrupted
If the file does not show up in the --list output, it may be gone from that snapshot. Try an older one—Borg’s incremental design means a file that changed later will still exist in earlier backups.
If all snapshots are damaged, you can pull the raw block directly with borg export-tar:
borg export-tar /srv/backups/myrepo::2026-10-18T12:00:00Z:/etc/nginx/nginx.conf | tar -xvf - -C /tmp/restore
It bypasses Borg’s extraction logic and streams the block. It’s slower, but sometimes the only thing that works when metadata is wrecked.
6. Security hygiene
- Encrypt the repo:
borg init --encryption=repokey /srv/backups/myrepo. The key stays on the machine, so only you can read the data. - Verify after every backup:
borg checkis cheap and catches corruption early. - Keep a second copy: Store the repo on another disk or a cloud bucket. Use
borg create --remote-path=borgto push to a remote host. - Use
--exclude-if-present .nobackupto avoid backing up temporary or sensitive files you don’t need.
7. Quick reference
| Command | What it does |
|---|---|
borg check /repo |
Verify integrity |
borg check --repair /repo |
Attempt to fix corruption |
borg list /repo::snap |
Show snapshot contents |
borg extract --list /repo::snap |
List readable files |
borg extract /repo::snap:/path/to/file |
Pull a single file |
| `borg export-tar /repo::snap:/path | tar -xvf -` |
Give these steps a try on a test backup first. Once you’re comfortable, you’ll know that a broken Borg repo doesn’t mean you have to restore an entire system.
See also
- Preventing Rootless Podman from Filling Up My Home Directory with Container Logs
- Running My Home NAS Backups with `nice` and `ionice` So My Desktop Never Freezes
- Docker builds on a 32 GB Raspberry Pi: How I recovered from a full disk
- Using a systemd path unit to clean my home server’s cache when disk space hits 90%
- What a half‑open TCP connection in “ss” really means (and how to close it)