Bacula is a mature, enterprise-grade open-source backup solution that manages backup, recovery, and data verification across heterogeneous networks. It uses a three-tier architecture — Director, Storage Daemon, and File Daemon — allowing centralised policy management with distributed storage targets. On RHEL 9, Bacula packages are available from the EPEL repository and integrate naturally with systemd. This tutorial covers installing all Bacula components, writing the essential configuration files, and performing a complete backup and restore cycle using the bconsole interactive shell.

Prerequisites

  • RHEL 9 server designated as the Bacula Director and Storage host
  • EPEL repository enabled (dnf install -y epel-release)
  • A MariaDB or PostgreSQL instance for the Bacula catalog database
  • Root or sudo access
  • Client nodes reachable by hostname or IP from the Director

Step 1 — Install Bacula Components

Install the Director, Storage Daemon, File Daemon (client agent), console, and database backend on the primary server. Install only the File Daemon on remote client nodes.

# On the Bacula Director/Storage server
sudo dnf install -y bacula-director bacula-storage bacula-client bacula-console

# Install the MySQL/MariaDB catalog backend
sudo dnf install -y bacula-director-mysql mariadb-server

# Start MariaDB and create the Bacula catalog
sudo systemctl enable --now mariadb
sudo /usr/libexec/bacula/grant_mysql_privileges
sudo /usr/libexec/bacula/create_mysql_database
sudo /usr/libexec/bacula/make_mysql_tables

# On remote clients only
sudo dnf install -y bacula-client

Step 2 — Configure the Bacula Director

The Director configuration (/etc/bacula/bacula-dir.conf) defines all backup jobs, clients, schedules, file sets, and storage pools. The example below shows a minimal but functional configuration.

# /etc/bacula/bacula-dir.conf (key sections)

Director {
    Name = bacula-dir
    DIRport = 9101
    QueryFile = "/etc/bacula/query.sql"
    Password = "dir_password"
    Messages = Daemon
}

Client {
    Name = webserver-fd
    Address = 192.168.1.20
    FDPort = 9102
    Catalog = MyCatalog
    Password = "client_password"
    File Retention = 60 days
    Job Retention = 6 months
}

FileSet {
    Name = "WebFiles"
    Include {
        Options { signature = MD5 }
        File = /var/www
        File = /etc
    }
    Exclude {
        File = /var/www/html/cache
    }
}

Schedule {
    Name = "DailyFull"
    Run = Full daily at 02:00
}

Job {
    Name = "BackupWebserver"
    Type = Backup
    Client = webserver-fd
    FileSet = "WebFiles"
    Schedule = "DailyFull"
    Storage = File1
    Messages = Standard
    Pool = Default
    Priority = 10
}

Pool {
    Name = Default
    Pool Type = Backup
    Recycle = yes
    AutoPrune = yes
    Volume Retention = 365 days
}

Step 3 — Configure the Storage Daemon and File Daemon

The Storage Daemon (bacula-sd.conf) defines where volumes are written. The File Daemon (bacula-fd.conf) runs on each client and accepts connections from the Director.

# /etc/bacula/bacula-sd.conf
Storage {
    Name = bacula-sd
    SDPort = 9103
    WorkingDirectory = "/var/lib/bacula"
    Pid Directory = "/run"
    Maximum Concurrent Jobs = 10
}

Device {
    Name = FileStorage
    Media Type = File
    Archive Device = /backup/bacula
    LabelMedia = yes
    Random Access = Yes
    AutomaticMount = yes
    RemovableMedia = no
    AlwaysOpen = no
}

# /etc/bacula/bacula-fd.conf (on each client)
FileDaemon {
    Name = webserver-fd
    FDport = 9102
    WorkingDirectory = /var/lib/bacula
    Pid Directory = /run
    Maximum Concurrent Jobs = 10
}

Director {
    Name = bacula-dir
    Password = "client_password"
}

# Create the backup volume directory on the storage host
sudo mkdir -p /backup/bacula
sudo chown bacula:bacula /backup/bacula

Step 4 — Start Services and Open Firewall Ports

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

# Open required ports
sudo firewall-cmd --permanent --add-port=9101-9103/tcp
sudo firewall-cmd --reload

# Verify all three daemons are running
sudo systemctl status bacula-dir bacula-sd bacula-fd

Step 5 — Use bconsole to Label, Run, and Restore

The bconsole interactive shell is the primary operator interface for Bacula. The session below labels a new backup volume, triggers a job, checks its status, and initiates a restore.

sudo bconsole

# Label a new volume in the Default pool
*label
Enter new Volume name: Vol-001
Enter slot (0 or Enter for none): 0
Defined Storage resources: FileStorage
Select Storage resource (1-1): 1

# Run a backup job
*run
Automatically selected Job: BackupWebserver
OK to run? (yes/mod/no): yes

# Check job status
*status
Select daemon type: 1 (Director)

# List completed jobs
*list jobs

# Restore files interactively
*restore
Select item: 5 (Select the most recent backup for a client)
Select client: webserver-fd
Mark files to restore using "mark" and "done"
*done
OK to run? yes

Conclusion

You have installed and configured a complete Bacula backup infrastructure on RHEL 9, including Director, Storage Daemon, and File Daemon, and performed a full backup and restore cycle through bconsole. Compared to alternatives: Amanda uses a similar daemon model but stores data in standard tar format and is simpler to configure for small environments; BorgBackup is agent-less, deduplicating, and excellent for single-server or push-based backup scenarios but lacks Bacula’s centralised multi-client job scheduling. Bacula’s strengths are its fine-grained job/schedule/pool model and its suitability for large heterogeneous environments.

Next steps: How to Configure DRBD for High-Availability Storage on RHEL 9, How to Manage Disk Encryption with LUKS and cryptsetup on RHEL 9, and How to Set Up Rsync-Based Incremental Backups on RHEL 9.