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

Bacula on FreeBSD: Enterprise Backup Review

In-depth review of Bacula on FreeBSD: Director, Storage, and File daemon architecture, PostgreSQL catalog configuration, volume management, job scheduling, and comparison with Bareos.

Bacula on FreeBSD: Enterprise Backup Review

Bacula is an enterprise-grade, open-source backup system that manages backup, recovery, and verification of data across a network. Unlike simple file-copying tools, Bacula provides a complete backup infrastructure: a centralized director that schedules and coordinates jobs, storage daemons that manage backup media, file daemons on client machines that handle the actual data transfer, and a SQL catalog that tracks every file in every backup. On FreeBSD, Bacula integrates through the ports and package system, uses PostgreSQL as its catalog database, and supports ZFS snapshots as part of its backup workflow. This review covers Bacula's architecture, installation on FreeBSD, configuration of all three daemons, volume management, scheduling, and how Bacula compares with its fork Bareos.

Architecture

Bacula uses a client-server model with three distinct daemon types:

Director Daemon (bacula-dir)

The Director is the central brain. It schedules backup jobs, selects which files to back up, chooses which storage device to use, and coordinates the File and Storage daemons. The Director reads its configuration, connects to clients at the scheduled time, and orchestrates the entire backup process. There is typically one Director per backup infrastructure.

Storage Daemon (bacula-sd)

The Storage Daemon manages the physical backup media -- disk volumes, tape drives, or cloud storage. It receives data from File Daemons during backup and sends data back during restore. The Storage Daemon handles volume labeling, media management, and data multiplexing (writing multiple backup streams to a single volume).

File Daemon (bacula-fd)

The File Daemon runs on every machine being backed up. It reads the local filesystem, sends data to the Storage Daemon, and handles file-level backup and restore operations. The File Daemon is lightweight and available for FreeBSD, Linux, macOS, and Windows.

Catalog

The Catalog is a SQL database (PostgreSQL, MySQL, or SQLite) that stores metadata about every backup job: which files were backed up, their sizes, checksums, modification times, and which volume contains each file. The Catalog enables fast file-level restores without scanning backup media.

Installation on FreeBSD

Package Installation

Install the Bacula server components with PostgreSQL support:

sh
pkg install bacula-server

This installs the Director, Storage Daemon, and Console. The File Daemon is typically installed separately on client machines:

sh
pkg install bacula-client

PostgreSQL Catalog Setup

Install and initialize PostgreSQL:

sh
pkg install postgresql16-server sysrc postgresql_enable="YES" service postgresql initdb service postgresql start

Create the Bacula database and user:

sh
su - postgres createuser bacula createdb -O bacula -E UTF8 bacula psql -c "ALTER USER bacula WITH PASSWORD 'bacula-db-password';" exit

Initialize the Bacula catalog schema:

sh
/usr/local/share/bacula/make_postgresql_tables

Enable Services

sh
sysrc bacula_dir_enable="YES" sysrc bacula_sd_enable="YES" sysrc bacula_fd_enable="YES"

Director Configuration

The Director configuration file is at /usr/local/etc/bacula/bacula-dir.conf. This is the most complex configuration file in the Bacula ecosystem.

Basic Director Setup

sh
Director { Name = freebsd-dir DIRport = 9101 QueryFile = "/usr/local/share/bacula/query.sql" WorkingDirectory = "/var/db/bacula" PidDirectory = "/var/run" Maximum Concurrent Jobs = 10 Password = "director-console-password" Messages = Daemon }

Catalog Configuration

sh
Catalog { Name = PostgreSQLCatalog dbname = "bacula" dbuser = "bacula" dbpassword = "bacula-db-password" DB Address = "localhost" DB Port = 5432 }

Client Definition

Define each machine to be backed up:

sh
Client { Name = webserver-fd Address = 192.168.1.10 FDPort = 9102 Catalog = PostgreSQLCatalog Password = "client-password" File Retention = 60 days Job Retention = 6 months AutoPrune = yes }

FileSet Definition

Define which files to back up:

sh
FileSet { Name = "ServerFiles" Include { Options { signature = SHA1 compression = GZIP aclsupport = yes xattrsupport = yes } File = /etc File = /usr/local/etc File = /var/db File = /home File = /root } Exclude { File = /var/db/bacula File = /tmp File = /var/tmp File = /proc } }

Storage Definition

Point the Director to the Storage Daemon:

sh
Storage { Name = File-Storage Address = 192.168.1.1 SDPort = 9103 Password = "storage-password" Device = FileStorage Media Type = File Maximum Concurrent Jobs = 5 }

Pool Definition

Pools organize backup volumes:

sh
Pool { Name = Full-Pool Pool Type = Backup Recycle = yes AutoPrune = yes Volume Retention = 365 days Maximum Volume Bytes = 50G Maximum Volumes = 100 Label Format = "Full-" } Pool { Name = Incremental-Pool Pool Type = Backup Recycle = yes AutoPrune = yes Volume Retention = 30 days Maximum Volume Bytes = 10G Maximum Volumes = 200 Label Format = "Inc-" }

Job Definition

A Job ties together a Client, FileSet, Storage, Pool, and Schedule:

sh
Job { Name = "BackupWebserver" Type = Backup Level = Incremental Client = webserver-fd FileSet = "ServerFiles" Schedule = "WeeklyCycle" Storage = File-Storage Pool = Incremental-Pool Full Backup Pool = Full-Pool Messages = Standard Priority = 10 Write Bootstrap = "/var/db/bacula/%c.bsr" }

Schedule Definition

sh
Schedule { Name = "WeeklyCycle" Run = Full 1st sun at 23:05 Run = Differential 2nd-5th sun at 23:05 Run = Incremental mon-sat at 23:05 }

This schedule runs a full backup on the first Sunday of the month, differential backups on other Sundays, and incremental backups every other day.

Storage Daemon Configuration

The Storage Daemon configuration at /usr/local/etc/bacula/bacula-sd.conf:

sh
Storage { Name = freebsd-sd SDPort = 9103 WorkingDirectory = "/var/db/bacula" PidDirectory = "/var/run" Maximum Concurrent Jobs = 10 } Director { Name = freebsd-dir Password = "storage-password" } Device { Name = FileStorage Media Type = File Archive Device = /backup/bacula LabelMedia = yes Random Access = yes AutomaticMount = yes RemovableMedia = no AlwaysOpen = no Maximum Concurrent Jobs = 5 }

Create the backup directory:

sh
mkdir -p /backup/bacula chown bacula:bacula /backup/bacula

On ZFS, create a dedicated dataset:

sh
zfs create -o compression=lz4 -o atime=off tank/backup/bacula chown bacula:bacula /tank/backup/bacula

File Daemon Configuration

On each client machine, configure /usr/local/etc/bacula/bacula-fd.conf:

sh
Director { Name = freebsd-dir Password = "client-password" } FileDaemon { Name = webserver-fd FDport = 9102 WorkingDirectory = "/var/db/bacula" PidDirectory = "/var/run" } Messages { Name = Standard director = freebsd-dir = all, !skipped, !restored }

Start the File Daemon:

sh
sysrc bacula_fd_enable="YES" service bacula-fd start

Running Backups

Start the Director

sh
service bacula-dir start service bacula-sd start service bacula-fd start

Using bconsole

The Bacula Console (bconsole) is the primary management interface:

sh
bconsole

Run a backup manually:

sh
*run job=BackupWebserver level=Full yes

Check job status:

sh
*status dir *status client=webserver-fd *status storage=File-Storage

List recent jobs:

sh
*list jobs *list jobid=123

Restore Files

Restore files interactively:

sh
*restore

The restore command presents an interactive menu to select which backup to restore from, which files to include, and where to restore them. You can restore to the original location or to an alternate directory.

Restore to an alternate location:

sh
*restore where=/tmp/restore client=webserver-fd

Volume Management

Volumes are the storage units that contain backup data. On disk-based storage, each volume is a file in the archive directory.

Label Volumes

Manually label a volume:

sh
*label storage=File-Storage volume=Full-0001 pool=Full-Pool

With Label Format set in the Pool configuration, volumes are labeled automatically.

Monitor Volumes

List volumes:

sh
*list volumes pool=Full-Pool *list media

Purge an expired volume:

sh
*purge volume=Full-0001

Delete a volume (removes catalog entry):

sh
*delete volume=Full-0001

Volume Retention

Bacula's AutoPrune feature automatically marks volumes as recyclable when all jobs in the volume exceed the Volume Retention period. Combined with Recycle = yes, Bacula reuses volumes automatically, preventing unbounded storage growth.

ZFS Integration

Bacula on FreeBSD benefits from ZFS features:

Pre-Backup ZFS Snapshots

Use a RunBeforeJob script to create a ZFS snapshot before backup, ensuring a consistent filesystem state:

sh
Job { Name = "BackupDatabase" Type = Backup Client = dbserver-fd FileSet = "DatabaseFiles" RunBeforeJob = "/usr/local/etc/bacula/scripts/pre-backup.sh" RunAfterJob = "/usr/local/etc/bacula/scripts/post-backup.sh" }

Create /usr/local/etc/bacula/scripts/pre-backup.sh:

sh
#!/bin/sh zfs snapshot tank/database@bacula-pre-backup mount -t zfs tank/database@bacula-pre-backup /mnt/backup-snapshot

Create /usr/local/etc/bacula/scripts/post-backup.sh:

sh
#!/bin/sh umount /mnt/backup-snapshot zfs destroy tank/database@bacula-pre-backup

Backup Storage on ZFS

Store Bacula volumes on a ZFS dataset with compression:

sh
zfs create -o compression=zstd -o atime=off -o recordsize=1m tank/backup/bacula

The large recordsize (1 MB) is appropriate because Bacula writes large sequential blocks. ZFS compression provides additional space savings on top of Bacula's own compression.

Monitoring and Reporting

Email Reports

Configure email notifications in the Director:

sh
Messages { Name = Standard mailcommand = "/usr/local/sbin/bsmtp -h localhost -f \"Bacula <bacula@example.com>\" -s \"Bacula: %t %e of %c %l\" %r" operatorcommand = "/usr/local/sbin/bsmtp -h localhost -f \"Bacula <bacula@example.com>\" -s \"Bacula: Intervention needed for %j\" %r" mail = admin@example.com = all, !skipped operator = admin@example.com = mount console = all, !skipped, !saved append = "/var/log/bacula/bacula.log" = all, !skipped }

Catalog Queries

Query the catalog directly for reporting:

sh
psql -U bacula bacula -c "SELECT name, level, jobstatus, jobbytes, jobfiles, starttime FROM job ORDER BY starttime DESC LIMIT 20;"

Bacula vs Bareos

Bareos (Backup Archiving Recovery Open Sourced) is a fork of Bacula created in 2010. The two projects share a common heritage but have diverged significantly.

Choose Bacula when:

  • You need a stable, well-tested backup system with a long track record.
  • You are comfortable with the bconsole interface.
  • You have existing Bacula infrastructure and expertise.
  • You want the option of Bacula Systems commercial support.

Choose Bareos when:

  • You want a modern web-based management interface (Bareos WebUI).
  • You want features that Bareos has added post-fork (improved cloud storage, better TLS handling, modernized code).
  • You prefer a community-driven project without a commercial entity controlling the open-source version.
  • You are starting fresh with no existing Bacula infrastructure.

The configuration formats are similar but not identical. Migration from Bacula to Bareos is possible but requires configuration adjustments and catalog migration.

Limitations

  • Complexity -- Bacula's three-daemon architecture and extensive configuration files have a steep learning curve. Expect to spend days, not hours, on initial setup.
  • Console interface -- bconsole is functional but text-based. No built-in web interface (Bacula Systems offers a commercial web GUI, and third-party tools like Baculum exist).
  • Documentation -- the official documentation is comprehensive but dense. The learning curve is real.
  • Single-node Director -- the Director is a single point of failure. No built-in Director clustering or failover.
  • Catalog database -- the PostgreSQL catalog must be backed up separately. Losing the catalog means losing the ability to do file-level restores from existing volumes.

Verdict

Bacula on FreeBSD is the right choice for organizations that need a comprehensive backup system with fine-grained control over every aspect of the backup process. Its three-daemon architecture, while complex, provides flexibility that simpler tools cannot match -- different storage types, multi-site replication, tape library support, and granular scheduling are all built in.

The investment in learning Bacula pays off when managing backups for 10+ servers with different retention requirements, multiple storage tiers, and compliance-driven audit trails. For simpler needs -- a single server, a few directories, ZFS snapshots supplemented with off-site copies -- Bacula is likely overkill. Tools like restic or borg provide simpler backup workflows for small environments. But when the backup requirements get complex, Bacula's architecture handles the complexity without breaking down.


Frequently Asked Questions

Can I use SQLite instead of PostgreSQL for the Bacula catalog?

Yes, for small deployments with a few clients and limited backup history. SQLite lacks concurrent write support, so it becomes a bottleneck as the number of simultaneous jobs increases. PostgreSQL is recommended for any deployment with more than 5 clients.

How do I back up the Bacula catalog itself?

Create a job that runs pg_dump before or after the regular backup cycle. Alternatively, use ZFS snapshots of the PostgreSQL data directory. The catalog is the most critical piece of the Bacula infrastructure -- without it, restoring individual files from backup volumes is extremely difficult.

Does Bacula support backing up ZFS snapshots directly?

Not natively. Use RunBeforeJob scripts to create a ZFS snapshot and mount it at a known path, then configure the FileSet to back up the mount point. RunAfterJob scripts clean up the snapshot after the backup completes.

How much disk space do Bacula volumes need?

It depends on the total data size, backup frequency, retention period, and deduplication/compression settings. A rough estimate: if you back up 100 GB of data daily with 30-day retention and incremental backups average 5% change per day, you need roughly 250-300 GB for volumes plus catalog overhead.

Can Bacula back up Windows clients from a FreeBSD Director?

Yes. The Bacula File Daemon is available for Windows. Install it on the Windows machine, configure it with the Director's address and password, and define the Client and Job in the Director configuration. The Director orchestrates backups across mixed FreeBSD, Linux, and Windows environments.

Is Bacula still actively developed?

Yes. Bacula Systems (the commercial entity) and the community continue to develop Bacula. The community edition receives updates, though some features are reserved for the commercial enterprise edition. The open-source version is fully functional for backup and recovery.

Get more FreeBSD guides

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