Bacula is a mature, enterprise-class open-source backup solution that supports tape libraries, disk-based storage, and remote clients across heterogeneous environments. Its client-server architecture separates the Director (job scheduler and catalog manager), Storage Daemon (tape or file I/O), and File Daemon (agent running on each backed-up host), allowing you to scale from a single server to thousands of clients. On RHEL 8, Bacula packages are available from the EPEL repository or directly from the Bacula.org community builds. This tutorial covers installation, catalog database setup, a working director configuration, and basic bconsole operations.

Prerequisites

  • RHEL 8 server with EPEL enabled: dnf install -y epel-release
  • At least 10 GB of free disk space for the backup storage directory
  • MariaDB or PostgreSQL installed for the Bacula catalog database
  • Root or sudo access
  • Firewall ports: TCP 9101 (Director), 9102 (File Daemon), 9103 (Storage Daemon)

Step 1 — Install Bacula Components

Install all Bacula daemons and the console on the backup server. In a larger environment, the Storage Daemon and File Daemon can run on separate hosts, but for this tutorial all components share one machine.

dnf install -y bacula-director bacula-storage bacula-console bacula-client

# Install MariaDB for the catalog
dnf install -y mariadb-server
systemctl enable --now mariadb

# Secure the MariaDB installation
mysql_secure_installation

Open the necessary firewall ports:

firewall-cmd --permanent --add-port={9101,9102,9103}/tcp
firewall-cmd --reload

Step 2 — Initialize the Catalog Database

Bacula ships helper scripts to create the catalog database and tables. Run these as root; they connect to MariaDB, create the bacula database, and populate the schema.

# Create the database and bacula OS user
/usr/libexec/bacula/create_mysql_database -u root
/usr/libexec/bacula/make_mysql_tables -u root
/usr/libexec/bacula/grant_mysql_privileges -u root

# Verify the tables exist
mysql -u bacula -p bacula -e "SHOW TABLES;"

If you prefer PostgreSQL, install postgresql-server, initialize the cluster (postgresql-setup --initdb), enable it, then use create_postgresql_database, make_postgresql_tables, and grant_postgresql_privileges from the same /usr/libexec/bacula/ directory.

Step 3 — Configure the Bacula Director

The Director configuration lives in /etc/bacula/bacula-dir.conf. The file defines the Director itself, Storage resources, Client (File Daemon) resources, FileSets, Schedules, Pools, and Jobs. Below is a minimal working configuration for a single client backing up to a local file device.

# /etc/bacula/bacula-dir.conf (abridged)
Director {
  Name = backup-dir
  DIRport = 9101
  QueryFile = "/usr/libexec/bacula/query.sql"
  WorkingDirectory = "/var/spool/bacula"
  PidDirectory = "/var/run"
  Maximum Concurrent Jobs = 5
  Password = "director-console-password"
  Messages = Daemon
}

Storage {
  Name = FileStorage
  Address = localhost
  SDPort = 9103
  Password = "storage-daemon-password"
  Device = FileChanger
  Media Type = File
  Maximum Concurrent Jobs = 10
}

Client {
  Name = localhost-fd
  Address = localhost
  FDPort = 9102
  Catalog = MyCatalog
  Password = "file-daemon-password"
  File Retention = 60 days
  Job Retention = 6 months
  AutoPrune = yes
}

Catalog {
  Name = MyCatalog
  dbname = "bacula"
  dbuser = "bacula"
  dbpassword = ""
}

FileSet {
  Name = "Full Set"
  Include {
    Options { signature = MD5 }
    File = /etc
    File = /home
    File = /var/www
  }
  Exclude {
    File = /var/spool
    File = /tmp
  }
}

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
}

Pool {
  Name = Default
  Pool Type = Backup
  Recycle = yes
  AutoPrune = yes
  Volume Retention = 365 days
  Maximum Volume Bytes = 50G
  Maximum Volumes = 100
  Label Format = "Vol-"
}

Job {
  Name = "BackupLocalhost"
  JobDefs = "DefaultJob"
  Type = Backup
  Client = localhost-fd
  FileSet = "Full Set"
  Schedule = "WeeklyCycle"
  Storage = FileStorage
  Pool = Default
  Messages = Standard
  Priority = 10
}

Step 4 — Configure the Storage Daemon

Edit /etc/bacula/bacula-sd.conf to define the storage device that corresponds to the Storage resource in the Director config. For file-based storage, point Archive Device at a directory with sufficient free space.

# /etc/bacula/bacula-sd.conf (Device section)
Device {
  Name = FileChanger
  Media Type = File
  Archive Device = /var/bacula/storage
  LabelMedia = yes
  Random Access = yes
  AutomaticMount = yes
  RemovableMedia = no
  AlwaysOpen = no
  Maximum Concurrent Jobs = 5
}

mkdir -p /var/bacula/storage
chown -R bacula:bacula /var/bacula

Start and enable all three daemons:

systemctl enable --now bacula-dir bacula-sd bacula-fd
systemctl status bacula-dir bacula-sd bacula-fd

Step 5 — Test with bconsole

bconsole is the command-line interface to the Director. Use it to label volumes, run jobs manually, and check status.

# Connect to the Director
bconsole

# Inside bconsole:
# Label a new volume in the Default pool
label

# Run the backup job immediately
run job=BackupLocalhost yes

# Check overall status
status director

# List completed and running jobs
list jobs

# List backed-up files for a specific job (replace 1 with job ID)
list files jobid=1

# Restore interactively
restore all

To exit bconsole, type quit. Job output and errors are also logged to /var/log/bacula/ and to the catalog, queryable with list joblog jobid=<N>.

Step 6 — Automate Volume Labeling and Pruning

For production use, enable automatic volume labeling so Bacula creates new volumes as needed, and configure pruning so the catalog and storage don’t grow unbounded.

# In the Pool resource in bacula-dir.conf, ensure these are set:
# Label Format = "Vol-"    ← Bacula auto-names volumes Vol-0001, Vol-0002, etc.
# AutoPrune = yes
# Volume Retention = 365 days
# Recycle = yes

# After editing, reload the Director without restarting
bconsole
reload

# Manually prune expired volumes
prune volume

Pair this with a cron job or systemd timer to run bconsole -c /etc/bacula/bconsole.conf <<EOF ... EOF scripts for automated maintenance tasks such as prune jobs and purge volume for recycled volumes.

Conclusion

You have installed Bacula on RHEL 8, initialized a MariaDB catalog database, written a Director configuration covering FileSets, Schedules, Pools, and Jobs, configured file-based storage, started all three daemons, and run your first backup and restore using bconsole. Bacula’s modular architecture means you can expand this foundation by adding remote clients (install bacula-client on each host and add a Client resource to the Director config), tape libraries via the Autochanger resource, or additional Storage Daemons for redundancy. Regularly test your restores — a backup that has never been tested is not a backup.

Next steps: How to Configure Bacula with a Tape Autochanger on RHEL 8, How to Back Up MySQL Databases with Bacula on RHEL 8, and How to Monitor Bacula Jobs with Baculum Web UI on RHEL 8.