FreeBSD.software
Home/Guides/BorgBackup on FreeBSD: Deduplicating Backup Review
review·2026-04-09·11 min read

BorgBackup on FreeBSD: Deduplicating Backup Review

In-depth review of BorgBackup on FreeBSD: deduplication, encryption, pruning, remote repositories, ZFS integration, and comparison with Restic and Tarsnap.

BorgBackup on FreeBSD: Deduplicating Backup Review

BorgBackup (Borg) is a deduplicating backup program that stores only unique data chunks across all backups in a repository. If you back up a 50 GB dataset daily and only 500 MB changes each day, Borg stores 50 GB plus incremental deltas -- not 50 GB times the number of backups. This deduplication, combined with optional compression and authenticated encryption, makes Borg one of the most storage-efficient backup tools available. On FreeBSD, Borg runs as a Python-based command-line tool that understands Unix permissions, extended attributes, and file flags. It integrates well with ZFS snapshots for consistent backup sources and with cron/periodic for automated scheduling. This review covers Borg's architecture, FreeBSD installation and configuration, deduplication mechanics, encryption options, pruning strategies, remote repository setup, and how it compares with Restic and Tarsnap.

What BorgBackup Does

Borg is a file-level backup tool that stores files in a content-addressed repository. Each backup creates an "archive" -- a named snapshot of a set of files and directories at a point in time. Borg breaks files into variable-size chunks, deduplicates them against all previous chunks in the repository, optionally compresses them, and stores them with authenticated encryption.

Core capabilities:

  • Deduplication -- content-defined chunking with a rolling hash (Buzhash). Identical data is stored once, regardless of which files or archives contain it.
  • Compression -- LZ4 (fast), zstd (balanced), zlib (good ratio), and LZMA (maximum compression). Selectable per-archive or per-file-type.
  • Authenticated encryption -- AES-256-CTR with HMAC-SHA256 (repokey mode) or the newer blake2b-based AEAD modes. The repository server never sees plaintext data.
  • Pruning -- automatic deletion of old archives based on retention rules (keep last N daily, weekly, monthly, yearly backups).
  • Remote repositories -- back up to a remote server over SSH. The remote server runs borg serve and only needs Borg installed -- no special server software.
  • Mounting archives -- mount any archive as a FUSE filesystem for browsing and selective file recovery.
  • Append-only mode -- repository can be configured so clients can only add new archives, not delete existing ones. Protects against ransomware and compromised clients.
  • Verification -- borg check verifies repository and archive integrity.

Borg does not provide continuous data protection (CDP), real-time replication, or block-level backup. It is a periodic, file-level backup tool designed for daily or hourly scheduled runs.

Installation on FreeBSD

Binary Package Installation

sh
pkg install py311-borgbackup

This installs Borg and its Python dependencies. The binary is accessible as borg:

sh
borg --version

Ports Installation

For custom build options (specific Python version, optional dependencies):

sh
cd /usr/ports/archivers/py-borgbackup make install clean

Optional: FUSE for Mount Support

To mount Borg archives as a filesystem for browsing:

sh
pkg install fusefs-libs3 kldload fusefs sysrc kld_list+=" fusefs"

Repository Setup

Initialize a Local Repository

sh
borg init --encryption=repokey /backup/borg-repo

This creates an encrypted repository at /backup/borg-repo. The encryption key is stored in the repository itself, protected by a passphrase. You will be prompted to set the passphrase.

Back up the key immediately:

sh
borg key export /backup/borg-repo /root/borg-key-backup.txt

Store this key export somewhere safe and offline. Without it and the passphrase, the repository is unrecoverable.

Encryption Modes

  • repokey -- encryption key stored in the repository, protected by passphrase. Most common choice.
  • keyfile -- encryption key stored in ~/.config/borg/keys/. More secure (key not on the repository server) but requires key backup.
  • repokey-blake2 -- same as repokey but uses BLAKE2b instead of SHA-256. Faster on modern CPUs.
  • none -- no encryption. Only use for local repositories on encrypted filesystems (ZFS encryption, GELI).
  • authenticated -- no encryption but data integrity verification. Use when encryption is handled at the storage layer.

For most FreeBSD deployments, repokey-blake2 is the recommended choice:

sh
borg init --encryption=repokey-blake2 /backup/borg-repo

Remote Repository

Initialize a repository on a remote server:

sh
borg init --encryption=repokey-blake2 ssh://backup-server/backup/borg-repos/freebsd-server

The remote server needs Borg installed. The connection uses SSH, so standard SSH key authentication applies.

Creating Backups

Basic Backup

sh
borg create /backup/borg-repo::daily-$(date +%Y%m%d-%H%M) \ /etc \ /usr/local/etc \ /home \ /root \ /var/db/mysql \ --exclude '/home/*/.cache' \ --exclude '*.tmp' \ --exclude '/var/db/mysql/*.pid'

This creates an archive named daily-20260409-0200 containing the specified paths, excluding cache directories and temporary files.

Compression Options

sh
# Fast compression (default for daily backups) borg create --compression lz4 /backup/borg-repo::daily-$(date +%Y%m%d) /etc /home # Balanced compression (good for weekly/monthly) borg create --compression zstd,3 /backup/borg-repo::weekly-$(date +%Y%m%d) /etc /home # Maximum compression (for archival) borg create --compression lzma,6 /backup/borg-repo::archive-$(date +%Y%m%d) /etc /home

LZ4 adds negligible CPU overhead and achieves 2:1 compression on typical data. Zstd at level 3 achieves 3:1 with moderate CPU usage. LZMA achieves 4:1+ but is slow -- use it only for long-term archives.

Backup with Progress and Statistics

sh
borg create --stats --progress /backup/borg-repo::daily-$(date +%Y%m%d) /etc /home

The --stats flag prints deduplication statistics after completion, showing how much new data was stored versus how much was deduplicated.

Automated Backup Script

Create a comprehensive backup script for FreeBSD:

sh
cat > /usr/local/bin/borg-backup.sh << 'SCRIPT' #!/bin/sh export BORG_REPO="ssh://backup-server/backup/borg-repos/freebsd-server" export BORG_PASSPHRASE="your_passphrase_here" ARCHIVE_NAME="$(hostname)-$(date +%Y%m%d-%H%M%S)" LOG="/var/log/borg-backup.log" echo "Starting backup: ${ARCHIVE_NAME}" >> "$LOG" # Create backup borg create \ --stats \ --compression zstd,3 \ --exclude '/home/*/.cache' \ --exclude '/var/tmp/*' \ --exclude '/tmp/*' \ --exclude '*.core' \ "${BORG_REPO}::${ARCHIVE_NAME}" \ /etc \ /usr/local/etc \ /home \ /root \ /var/db \ /var/mail \ >> "$LOG" 2>&1 BACKUP_STATUS=$? # Prune old backups borg prune \ --keep-daily 7 \ --keep-weekly 4 \ --keep-monthly 6 \ --keep-yearly 2 \ "$BORG_REPO" \ >> "$LOG" 2>&1 # Compact repository (free disk space from pruned archives) borg compact "$BORG_REPO" >> "$LOG" 2>&1 echo "Backup completed with status: ${BACKUP_STATUS}" >> "$LOG" if [ $BACKUP_STATUS -ne 0 ]; then echo "Borg backup failed on $(hostname)" | mail -s "Backup FAILED" admin@example.com fi SCRIPT chmod 700 /usr/local/bin/borg-backup.sh

Schedule with cron:

sh
crontab -e # Add: 0 2 * * * /usr/local/bin/borg-backup.sh

Deduplication Mechanics

Borg's deduplication is the core of its storage efficiency. Understanding how it works helps you optimize backups.

Content-Defined Chunking

Borg splits files into variable-size chunks using a rolling hash (Buzhash). Chunk boundaries are determined by the file content, not by fixed offsets. This means:

  • Inserting data at the beginning of a file shifts all fixed-offset boundaries, causing a non-deduplicating backup tool to re-store the entire file. Borg re-stores only the new chunk at the insertion point.
  • Files with identical content in different paths or archives are stored once.
  • Small changes to large files result in only the changed chunks being stored.

Deduplication Ratio

Check your repository's deduplication efficiency:

sh
borg info /backup/borg-repo

This shows total original size, deduplicated size, and compression ratio. A healthy repository with daily backups of changing data typically shows 5:1 to 20:1 deduplication ratios after a few weeks.

Chunk Size Tuning

The default chunk size parameters work well for most workloads. For repositories backing up many large files (databases, virtual machine images), larger chunks reduce metadata overhead:

sh
borg init --chunker-params=19,23,21,4095 --encryption=repokey-blake2 /backup/borg-repo

This increases average chunk size from ~2 MB to ~4 MB. Do not change chunker parameters on an existing repository.

Pruning and Retention

Pruning removes old archives based on retention rules. It does not immediately free disk space -- that requires a separate compact step (Borg 1.2+).

Retention Strategy

sh
borg prune \ --keep-daily 7 \ --keep-weekly 4 \ --keep-monthly 12 \ --keep-yearly 5 \ /backup/borg-repo

This keeps:

  • The last 7 daily backups.
  • 4 weekly backups (one per week, going back 4 weeks).
  • 12 monthly backups (one per month, going back 12 months).
  • 5 yearly backups (one per year, going back 5 years).

Compact After Pruning

sh
borg compact /backup/borg-repo

This frees disk space occupied by chunks that are no longer referenced by any archive.

Dry Run

Test pruning before executing:

sh
borg prune --dry-run --list --keep-daily 7 --keep-weekly 4 /backup/borg-repo

The --list flag shows which archives would be kept and which would be pruned.

Restoring from Backups

List Archives

sh
borg list /backup/borg-repo

List Files in an Archive

sh
borg list /backup/borg-repo::daily-20260409-0200

Restore Specific Files

sh
cd / borg extract /backup/borg-repo::daily-20260409-0200 etc/pf.conf etc/rc.conf

This restores etc/pf.conf and etc/rc.conf to their original paths relative to the current directory.

Restore Everything

sh
cd / borg extract /backup/borg-repo::daily-20260409-0200

Mount and Browse

sh
mkdir /mnt/borg borg mount /backup/borg-repo::daily-20260409-0200 /mnt/borg ls /mnt/borg/etc/ cp /mnt/borg/home/user/important-file.txt /home/user/ borg umount /mnt/borg

FUSE mounting is the most convenient way to browse backups and selectively restore files.

ZFS Integration

On FreeBSD, combining Borg with ZFS snapshots provides the most consistent backup strategy.

Pre-Backup ZFS Snapshot

sh
# Create consistent snapshots zfs snapshot zroot/var/db/mysql@borg-pre-backup # Mount snapshot read-only mkdir -p /mnt/borg-source/mysql mount -t zfs zroot/var/db/mysql@borg-pre-backup /mnt/borg-source/mysql # Back up from snapshot (consistent state) borg create /backup/borg-repo::daily-$(date +%Y%m%d) \ /etc /home /mnt/borg-source/mysql # Cleanup umount /mnt/borg-source/mysql zfs destroy zroot/var/db/mysql@borg-pre-backup

This ensures the database files are in a consistent state during the backup, avoiding corruption from files changing mid-backup.

Append-Only Mode

Protect against ransomware or compromised clients by configuring the remote repository in append-only mode:

On the backup server, create a restricted SSH key in ~/.ssh/authorized_keys:

sh
command="borg serve --append-only --restrict-to-path /backup/borg-repos/freebsd-server",restrict ssh-ed25519 AAAA... client-key

With append-only mode, the client can create new archives but cannot delete existing ones. An administrator on the backup server can prune old archives manually.

BorgBackup vs Restic

Restic is Borg's most direct competitor. Both use content-defined chunking and deduplication.

Choose Borg when:

  • You want the most mature deduplicating backup tool with the longest track record.
  • You need append-only repositories for ransomware protection.
  • You prefer local or SSH-based remote storage.
  • You want FUSE mounting for browsing archives.
  • You need fine-grained compression control (per-archive or per-type).

Choose Restic when:

  • You need native cloud storage support (S3, B2, Azure, GCS) without additional tools.
  • You want a single static binary with no runtime dependencies.
  • You need to back up to multiple backend types from the same tool.
  • You prefer Go's deployment simplicity over Python's dependency management.

Both are excellent. The practical difference often comes down to storage backend: Borg for SSH-based storage, Restic for cloud object storage.

BorgBackup vs Tarsnap

Tarsnap is a cloud backup service by Colin Percival (FreeBSD Security Officer Emeritus). The comparison:

  • Storage -- Tarsnap stores data on Tarsnap's servers (AWS-based). Borg stores data wherever you point it. Tarsnap is a service; Borg is a tool.
  • Cost -- Tarsnap charges per byte stored and transferred. Borg has no recurring cost beyond your own storage.
  • Encryption -- both provide client-side encryption. Tarsnap's encryption is handled by the client, and Tarsnap cannot read your data.
  • Deduplication -- both deduplicate. Tarsnap deduplicates server-side as well, which can reduce costs.
  • Trust model -- Tarsnap requires trusting a third-party service. Borg with your own infrastructure requires trusting only yourself.

Tarsnap is ideal for small, critical datasets (server configurations, encryption keys, small databases) where the convenience of a managed service outweighs the cost. Borg is better for large datasets where storage costs would be prohibitive on Tarsnap.

Monitoring

Check Repository Integrity

sh
borg check /backup/borg-repo

Run this monthly. It verifies the integrity of the repository data structures and all stored chunks.

Check a Specific Archive

sh
borg check --archives-only --last 5 /backup/borg-repo

Repository Info

sh
borg info /backup/borg-repo

Shows total size, deduplicated size, number of archives, and encryption mode.

Verdict

BorgBackup is the best file-level backup tool for FreeBSD systems that store backups on local disks or remote SSH servers. Its deduplication reduces storage costs dramatically for daily backups, its encryption protects data in transit and at rest, and its pruning system automates retention management. On FreeBSD, Borg pairs naturally with ZFS snapshots for consistent database backups and with cron for automated scheduling.

The main limitation is the lack of native cloud storage support -- if you need to back up directly to S3 or B2, Restic is the better choice. For SSH-based backup to your own infrastructure, Borg is the gold standard.


Frequently Asked Questions

How do I back up a FreeBSD jail?

Back up the jail's filesystem path directly: borg create repo::jail-daily /usr/local/jails/myjail. For running jails, take a ZFS snapshot first to ensure consistency.

What happens if a backup is interrupted?

Borg uses a transaction-based approach. Interrupted backups leave the repository in a consistent state -- the incomplete archive is discarded, and the repository remains valid. Re-run the backup to create a complete archive.

How much storage does Borg need?

For the first backup, roughly equal to the source data (minus compression savings). Subsequent backups store only changed chunks. A typical server with 50 GB of data and daily backups uses 55-60 GB after a month with good deduplication.

Can I use Borg without encryption?

Yes: borg init --encryption=none /backup/borg-repo. Use this only if the storage is already encrypted (ZFS encryption, GELI, encrypted cloud storage).

How do I migrate a Borg repository to a new server?

Copy the entire repository directory to the new server with rsync -a. The repository is self-contained. Update the backup script to point to the new location.

Does Borg support Windows?

No. Borg is Unix-only (FreeBSD, Linux, macOS). For cross-platform backups, use Restic.

Get more FreeBSD guides

Weekly tutorials, security advisories, and package updates. No spam.