Why pull a single file from a Borg archive?
When a configuration file or a database dump is corrupted, you often need only that one file, not the whole archive. Extracting the entire archive just to get a single file wastes bandwidth, CPU, and disk space—especially when the archive lives on a remote server or in a cloud bucket.
Because Borg keeps the archive compressed and deduplicated, the cost of pulling a single file is proportional to the file’s size and the number of blocks it occupies. Below is a quick walk‑through for retrieving a single file efficiently, both locally and remotely, and piping the data through other tools for immediate processing or secure transfer.
Borg basics recap
- Repository – a directory or remote storage that holds one or more archives.
- Archive – a snapshot of a filesystem at a point in time, identified by a name (e.g.,
2026-10-07T12-00-00). - Encryption – Borg supports AES‑256‑CTR encryption by default; the key is stored in
~/.config/borg/keys/. - Remote access – Borg can talk to a remote repository over SSH using the
borgcommand on the client and aborgservedaemon on the server.
The commands below assume you have a local repository at /srv/borg/repo and a remote one at user@backup.example.com:/srv/borg/repo.
Direct extraction with borg extract
The simplest way to pull a single file is to use borg extract with the --list flag to locate the file, then specify its path.
# List the contents of an archive
borg list /srv/borg/repo::2026-10-07T12-00-00
# Extract a single file
borg extract /srv/borg/repo::2026-10-07T12-00-00 /etc/nginx/nginx.conf
borg extract preserves the file’s metadata (permissions, ownership, timestamps) by default. If you only need the raw data, add --no-rc to skip the integrity check, but be aware that this skips the SHA‑256 verification step.
Caveats
- Path resolution – The file path must match the archive’s internal path. If the archive was created with
--exclude-cachesor--exclude, the file may not exist. - Permissions – Running
borg extractas a non‑root user will create the file with that user’s UID/GID unless--numeric-owneris used. - Large archives – Even though only one file is extracted, Borg still reads the archive’s index and decompresses the relevant blocks. For very large archives, this can be noticeable.
Remote extraction via SSH
When the repository is on a remote host, you can still use borg extract directly. Borg will open an SSH session and stream the data back to the client.
# Extract from a remote repository
borg extract user@backup.example.com:/srv/borg/repo::2026-10-07T12-00-00 /var/www/html/index.html
The command runs on the client; the remote side only serves the archive blocks. This keeps the bandwidth cost to the size of the requested file plus the minimal overhead of the archive index.
Security considerations
- SSH key authentication – Use a dedicated key with
authorized_keysand disable password authentication for that key. - Firewall – Make sure the SSH port is reachable from the client, but not open to the wider internet if possible.
- Key rotation – Rotate the key regularly and keep the old key in a secure backup.
Piping the file for immediate use
If you just need the file content, you can pipe it straight into another command instead of writing it to disk first. Borg lets you extract a file to stdout with --output. For example, to view a config file:
borg extract --output - /srv/borg/repo::2026-10-07T12-00-00 /etc/ssh/sshd_config | less
Or to restore it into a container without touching the host filesystem:
borg extract --output - user@backup.example.com:/srv/borg/repo::2026-10-07T12-00-00 /etc/mysql/my.cnf | docker exec -i db_container mysql -u root -p < /dev/stdin
Common pitfalls
- Wrong archive name – Double‑check the timestamp or name; Borg is case‑sensitive.
- Missing files – If you used
--excludeduring backup, the file simply isn’t there. - Permission errors – If you’re restoring to a system that expects a specific UID/GID, use
--numeric-owneror run the command as root.
TL;DR
- List the archive to find the exact path.
- Run
borg extract repo::archive path/to/file. - For remote repos, prepend
user@host:. - Use
--output -to stream to another command if you don’t want a temporary file.
That’s all there is to it. Happy restoring!
See also
- Summarizing /var/log/syslog Errors into JSON with jq for Grafana Dashboards
- Why ssh keeps asking for a password after adding a key and how to correct the PubkeyAuthentication setting
- When systemd‑resolved overrides /etc/hosts: a quick fix
- Fixing “Host key verification failed” After Renaming a Jump Host Server
- How to Stop a systemd Timer from Failing After a Reboot Due to an Unset $USER Variable