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:
shpkg install bacula-server
This installs the Director, Storage Daemon, and Console. The File Daemon is typically installed separately on client machines:
shpkg install bacula-client
PostgreSQL Catalog Setup
Install and initialize PostgreSQL:
shpkg install postgresql16-server sysrc postgresql_enable="YES" service postgresql initdb service postgresql start
Create the Bacula database and user:
shsu - 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
shsysrc 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
shDirector { 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
shCatalog { 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:
shClient { 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:
shFileSet { 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:
shStorage { 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:
shPool { 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:
shJob { 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
shSchedule { 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:
shStorage { 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:
shmkdir -p /backup/bacula chown bacula:bacula /backup/bacula
On ZFS, create a dedicated dataset:
shzfs 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:
shDirector { 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:
shsysrc bacula_fd_enable="YES" service bacula-fd start
Running Backups
Start the Director
shservice bacula-dir start service bacula-sd start service bacula-fd start
Using bconsole
The Bacula Console (bconsole) is the primary management interface:
shbconsole
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:
shJob { 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:
shzfs 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:
shMessages { 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:
shpsql -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.