Pulling a single file from a Borg backup without unpacking the whole archive is a common task for sysadmins who need quick recovery of a configuration file, a database dump, or a user document.
The following walkthrough shows how to do it safely, efficiently, and with a minimal security footprint.
Why pull a single file?
- Speed – Extracting an entire archive can take minutes or hours on large repositories.
- Disk space – You may not have room to unpack thousands of files.
- Security – Extracting only what you need reduces the attack surface; you avoid exposing the rest of the backup to the current filesystem.
- Automation – Scripts that restore a single file can run in CI/CD pipelines or as part of a systemd timer.
Borg basics recap
Borg is a deduplicating backup program that stores data in a repository.
Each backup is an archive that can contain one or more directories.
The repository can be local or remote (SSH, HTTP, or a network filesystem).
Borg supports strong encryption (repokey, passphrase, or keyfile) and can be configured to use a keyfile stored on the backup host.
The key commands we’ll use:
borg list # list archives
borg extract # extract files
borg config # view repository settings
All commands are run from the machine that hosts the repository.
If the repository is remote, prepend the SSH URL (e.g., user@backup.example.com::repo).
Prerequisites
Borg installed – On Debian/Ubuntu:
apt install borgbackup.
On Arch:pacman -S borg.
On Red Hat/Fedora:dnf install borgbackup.Repository initialized –
If you haven’t set up a repo yet, create one with:borg init --encryption=repokey /srv/borg/repoReplace the path with wherever you keep your backups.
Find the file you want
The first thing to do is locate the file inside the archive.
Borg’s list command lets you drill down into a specific archive:
borg list user@backup.example.com::repo::2024-10-18T14:30:00
You’ll see a tree of directories and files.
If you’re looking for /etc/nginx/nginx.conf, just scroll or pipe the output:
borg list user@backup.example.com::repo::2024-10-18T14:30:00 | grep nginx.conf
If you have many archives, you can narrow it down with --prefix or --depth.
Borg can also list all archives in the repo:
borg list user@backup.example.com::repo
Extract the single file
Once you know the archive and the path, use extract with the --files-from flag to pull just that one file:
borg extract \
--files-from <(echo "/etc/nginx/nginx.conf") \
user@backup.example.com::repo::2024-10-18T14:30:00 \
/tmp/nginx.conf
- The
<(echo ...)trick feeds a single line to--files-from. - The destination (
/tmp/nginx.conf) is optional; if omitted, Borg restores to the current working directory.
If you prefer an interactive prompt, drop the --files-from and just run:
borg extract user@backup.example.com::repo::2024-10-18T14:30:00
Borg will ask you to confirm the files to extract.
This is handy when you’re unsure of the exact path.
Security considerations
Use a keyfile – Store your keyfile on the backup host and reference it with
--keyfile.
That way you never expose the passphrase on the command line or in scripts.borg extract \ --keyfile /etc/borg/keyfile \ --files-from <(echo "/etc/nginx/nginx.conf") \ user@backup.example.com::repo::2024-10-18T14:30:00 \ /tmp/nginx.confRun as a dedicated user – Don’t run Borg as root unless absolutely necessary.
A dedicated backup user keeps permissions tidy and limits damage if something goes wrong.Check the integrity – After extraction, verify the file’s checksum against what you expect.
Borg itself verifies the archive before extraction, but a quicksha256sum /tmp/nginx.confis a good sanity check.
Automating single-file restores
In practice, you’ll often want a small wrapper script:
#!/usr/bin/env bash
set -euo pipefail
REPO="user@backup.example.com::repo"
ARCHIVE="2024-10-18T14:30:00"
FILE="/etc/nginx/nginx.conf"
DEST="/tmp/nginx.conf"
borg extract \
--keyfile /etc/borg/keyfile \
--files-from <(echo "$FILE") \
"$REPO::$ARCHIVE" \
"$DEST"
Make it executable (chmod +x restore-nginx.sh) and call it from a systemd timer or a CI job.
Because it only pulls one file, the job finishes fast and leaves the rest of the repo untouched.
Common pitfalls
Wrong path – Borg paths are relative to the archive’s root.
If you back up/withborg create --one-file-system ::archive /, the file inside the archive will be/etc/nginx/nginx.conf.
Forgetting the leading slash will causeborgto look foretc/nginx/nginx.confrelative to the current directory, which fails.Archive name mismatch – Archive names are timestamps by default.
Double‑check the exact name; a typo will return “archive not found”.Missing permissions – If you run Borg as a non‑root user and the file was owned by root, the restored file will be owned by the backup user unless you preserve ownership with
--preserve-permissions.
For config files this is usually fine, but for database dumps you might need the original ownership.Large archives – Even if you’re only pulling one file, Borg still has to scan the entire archive header.
On huge repos, this can add a noticeable delay.
If you routinely need a handful of files, consider splitting your backup into smaller logical archives.
Final thoughts
Pulling a single file from a Borg repository is a quick, low‑footprint operation that keeps the rest of your backup safe and out of reach.
With the right keyfile setup, a dedicated backup user, and a tidy wrapper script, you can recover individual items in seconds without touching the whole archive.
See also
- Stop systemd‑journald from filling your Raspberry Pi’s 8 GB SD card with logs – how to cap its size
- Send a Telegram Alert When Your Home Server’s /home Reaches 90% Usage With a Tiny systemd Service and curl
- Stop the “REMOTE HOST IDENTIFICATION HAS CHANGED!” error by cleaning ~/.ssh/known_hosts.
- Easily Remove Stale Entries from ~/.ssh/known_hosts When a Host Rebuilds with ssh-keygen ‑R
- How to use journalctl to trace why my systemd‑service crashes after a kernel upgrade