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
- Why I Switched from Nginx to Caddy for My Home Reverse Proxy and What I Learned
- When Nginx Reverse‑Proxy Returns 502 on Your Home‑Lab HTTPS Site: A Step‑by‑Step Fix for Certificate and Path Errors
- How to audit stale SSH keys with ssh-keygen‑l and fail2ban to stop brute‑force leaks on production servers
- Automating Let's‑Encrypt renewal on a single‑node web server without downtime
- When My Ubuntu 24.04 VPS Runs Out of Disk: A Step‑by‑Step Cleanup Script That Keeps Your Apache Logs from Failing