This episode covers Bacula scaling: many File Daemons to one Director and Storage Daemon, per-tenant configuration using Client resources and ACLs, and high-availability strategies with Director HA and SD clustering for enterprise deployments.

Up to episode 14 we managed a single client. Now let's level up: tens, hundreds, even thousands of clients. The question is no longer "how to add a client", but "how to keep the system organized and alive as it scales". In episode 15 we answer both: horizontal scaling (many clients) and availability (HA).
The pattern we'll build: one Director managing many FDs and several SDs, configuration organized per tenant with Client resources and ACLs, then high-availability options for the Director and Storage.
There's no hard limit on clients per Director — the limit is configuration discipline and performance. Each client needs a Client resource + at least one Job:
Client {
Name = app-01-fd
Address = 10.0.0.21
FDPort = 9103
Password = "pwd-app-01"
}
Job {
Name = "Backup app-01"
Type = Backup
Client = app-01-fd
FileSet = "Set Server"
Schedule = WeeklyCycle
Storage = FileStorage
Pool = FilePool
}With hundreds of clients, this pattern becomes repetitive. The real solution: generate the configuration from an inventory (Ansible templates, scripts, or CMDB) — not handwriting. Generated config is also easier to audit.
Note
Some Bacula resources allow defining multiple resources in one block — but for audit clarity, one client = one separate Client block is far easier to read and debug than combining client names in a single block.
One Director can use several SDs at once — for example SDs in two geographic locations. The Storage resource in bacula-dir.conf points to each SD, and each job chooses its target Storage:
Storage {
Name = StorageJakarta
Address = 10.0.0.5
SDPort = 9102
Password = "rahasia-sd-jkt"
Device = FileStorage
MediaType = File
}
Storage {
Name = StorageSurabaya
Address = 10.0.0.15
SDPort = 9102
Password = "rahasia-sd-sby"
Device = FileStorage
MediaType = File
}This pattern enables strategies like: back up locally to the nearest SD, then Copy/Migration jobs move data to another location's SD for DR.
For multi-tenancy (several departments/clients sharing one Bacula system), the isolation key is in three resources: Client (who), Pool (where the data goes), and FileSet (what's allowed). Each tenant gets its own pool:
Pool {
Name = PoolDepartemenA
Pool Type = Backup
Recycle = yes
AutoPrune = yes
Volume Retention = 30 days
}
Pool {
Name = PoolDepartemenB
Pool Type = Backup
Recycle = yes
AutoPrune = yes
Volume Retention = 90 days
}Volumes are separated per pool — tenant A never overwrites tenant B's volumes, and retention can differ per contract.
Bacula supports ACLs in the Console resource to limit which commands a console may run. Example: a special console that can only run certain jobs:
Console {
Name = operator-a
Password = "pwd-operator-a"
CommandACL = status, list
JobACL = BackupDeptA-*
ClientACL = dept-a-fd-*
StorageACL = StorageJakarta
PoolACL = PoolDepartemenA
FileSetACL = "Set Dept A"
}With ACLs, department A operators cannot see department B's jobs, clients, or pools — the operational isolation needed in shared environments. This feature is what sets Bacula apart from simple backup tools.
Warning
ACLs restrict the console, not the daemons. Anyone with root access to the config files or the catalog database can bypass them. For true security isolation between tenants, use several separate Directors — ACLs are an operational control, not a hard security control.
The Director is a single point of failure: if it dies, all scheduled backups stop. HA options:
+--------------------+
| VIP 10.0.0.50:9101 |
+--------------------+
| |
+--------+ +--------+
| Dir A | | Dir B |
| (active)| |(passive)|
+--------+ +--------+
\ /
PostgreSQL (shared/replicated)The critical part of this pattern: clients and SDs must point to the VIP, not a specific host IP, and the catalog must be shared safely.
The Storage Daemon can scale with multiple SDs handling different devices. Bacula Enterprise supports SD clustering with managed failover. In Community, the practical pattern:
Job {
Name = "Backup app-02"
Type = Backup
Client = app-02-fd
FileSet = "Set Server"
Storage = StorageSurabaya
Pool = FilePool
}Tip
Don't make an SD the home of the catalog. Keep the catalog database on a standalone host/replica — if the SD dies, the catalog survives and restore is still possible from another SD; if the catalog dies, everything needs recovery (episode 16).
Key takeaways:
Console ACLs for operational isolation.In the next episode, episode 16, we'll cover troubleshooting and debug — the bacula-dir -d 100 debug mode, logs in /var/log/bacula/, status via bconsole, common cases (failed authentication, full tape, catalog lock), plus catalog recovery and restore from tape. These are the skills that define your reputation when production goes wrong.