This episode covers database and application backup: Enterprise plugins for VMware, Hyper-V, MSSQL, MySQL/PostgreSQL agents, and NDMP versus the script-based Community approach with pre-backup and post-cleanup hooks. You will also understand the importance of data consistency and snapshot strategies.

Backing up static files is easy: copy, done. But databases and applications have one big enemy: inconsistency. Copying .ibd or postgresql.conf files while the database is writing is the fastest way to make a backup that can't be restored. In episode 10 we learn how to back up live workloads correctly.
The approach varies by edition: integrated application plugins in Enterprise, or script-based pre/post patterns in Community. And behind both lies the same principle — make the data consistent first, then copy.
A database never writes one big file; it writes to many files with internal buffers and WAL (write-ahead log). Copying files while transactions are in progress produces an inconsistent snapshot: half a transaction saved, half not. When the database is opened from this copy, it fails.
There are two ways out:
Bacula Enterprise provides both via plugins; Community relies on scripts that call the database's native tools.
Bacula Enterprise provides plugins that communicate directly with applications to ensure consistency:
The plugin advantage: consistency is guaranteed, no manual scripts needed, and restore can be application-aware. The price: a commercial license and additional configuration on the application side.
Note
Bacula Enterprise plugins do not run in Community. If you need truly zero-script application backup, weigh the Enterprise license cost against the value of the protected data — we go deeper into this analysis in episode 18.
In Community, the standard strategy is pre/post hooks triggered by Bacula jobs. Bacula runs commands through the ClientRunBeforeJob and ClientRunAfterJob directives in the Job resource:
For PostgreSQL, the most reliable pattern: dump to a file first, then back up the dump file.
#!/bin/bash
set -euo pipefail
BACKUP_DIR=/var/backup/pg_dump
mkdir -p "$BACKUP_DIR"
PGPASSWORD=rahasia pg_dump -h 127.0.0.1 -U bacula myapp > "$BACKUP_DIR/myapp.sql"Job {
Name = "Backup PostgreSQL"
Type = Backup
Client = client-fd
FileSet = "Set PG Dump"
ClientRunBeforeJob = "/etc/bacula/scripts/pg_dump.sh"
ClientRunAfterJob = "/etc/bacula/scripts/pg_cleanup.sh"
Storage = FileStorage
Pool = FilePool
}The flow: Bacula runs pg_dump.sh before it starts reading files → the dump result is backed up along with the FileSet → pg_cleanup.sh removes old dumps afterwards.
MySQL uses mysqldump the same way:
mysqldump --single-transaction -u backup -p'rahasia' myapp > /var/backup/mysql_dump/myapp.sql--single-transaction is important: it takes a consistent snapshot without locking all tables.
Don't let dumps pile up on the client — dump files are large duplicates. ClientRunAfterJob cleans them up:
#!/bin/bash
find /var/backup -name "*.sql" -mtime +1 -deleteImportant
If ClientRunBeforeJob fails (script exits non-zero), Bacula cancels the job. This is correct behavior: better no backup than an inconsistent one. Make sure your scripts use set -e so dump failures are detected.
A pre-backup hook forces the application to "pause briefly" (making a dump). The snapshot approach differs: the application keeps running, but the filesystem photographs a consistent state (for example an LVM snapshot or VSS on Windows) that is then backed up.
lvcreate -L 10G -s -n snapsata /dev/vg0/dbdataThe snapshot that gets backed up is a static image; the application is never blocked. This is why Enterprise and VM vendors use snapshots: zero downtime, still consistent.
For Community without plugins, the ideal combination: pg_dump for databases + a regular FileSet for static files. For VMs, consider an Enterprise plugin or backup through an in-VM agent with dumps.
The complete pattern for a small application server:
FileSet {
Name = "Set Aplikasi"
Include {
Options { signature = SHA1 }
File = /opt/myapp
File = /var/backup/pg_dump
}
}The dump lives in /var/backup/pg_dump and gets backed up along with everything else. After the job finishes, cleanup removes the dump — but the dump's contents are already safe on the Bacula volumes.
Tip
Test restoring a backed-up dump: psql -f restore.sql in an empty database. An untested dump is just as dangerous as having no backup — the same lesson as the restore drill in episode 8, now applied to databases.
Key takeaways:
ClientRunBeforeJob/ClientRunAfterJob hooks + pg_dump/mysqldump.set -e in hook scripts so failures cancel the job instead of producing a defective backup.In the next episode, episode 11, we'll manage tape and storage — tape device configuration (LTO), autoloaders/changers, slot labeling and tape rotation, comparing them with disk storage, and dedup strategies (Enterprise plugin) versus file-based. These are the media that make Bacula excel in long-term enterprise environments.