How to Self-Host Bacula with Docker Compose
What Is Bacula?
Bacula is an enterprise-grade backup framework that manages backup, recovery, and verification of data across a network. It uses a client-server architecture with three core components: the Director (schedules and coordinates), the Storage Daemon (manages backup media), and the File Daemon (runs on each client machine). Bacula is one of the oldest open-source backup systems (first released 2000) and is used in production at organizations managing petabytes of data.
Prerequisites
- A Linux server (Ubuntu 22.04+ recommended)
- Docker and Docker Compose installed (guide)
- 2 GB of free RAM (minimum)
- Sufficient disk space for backup storage
- Network access to all machines you want to back up
- A domain name (optional, for remote web UI access)
Docker Compose Configuration
Bacula’s architecture requires multiple communicating services. Create a docker-compose.yml file:
services:
bacula-director:
image: bacularis/bacularis-standalone:18.0.4
container_name: bacula-director
restart: unless-stopped
ports:
- "9097:9097" # Bacularis web UI
- "9101:9101" # Director daemon
volumes:
- bacula-config:/opt/bacula/etc # Bacula configuration
- bacula-data:/opt/bacula/archive # Backup storage
- bacula-catalog:/var/lib/pgsql/data # PostgreSQL catalog database
- bacula-logs:/opt/bacula/log # Bacula logs
environment:
DB_INIT: "true" # Initialize database on first run
DB_HOST: "localhost"
DB_PORT: "5432"
DB_NAME: "bacula"
DB_USER: "bacula"
DB_PASSWORD: "change-this-password" # CHANGE: strong database password
BACULARIS_API_USER: "admin" # CHANGE: web UI username
BACULARIS_API_PASSWORD: "change-this-too" # CHANGE: web UI password
networks:
- backup
bacula-storage:
image: bacularis/bacularis-standalone:18.0.4
container_name: bacula-storage
restart: unless-stopped
ports:
- "9103:9103" # Storage daemon
volumes:
- bacula-config:/opt/bacula/etc:ro
- bacula-data:/opt/bacula/archive
entrypoint: ["/opt/bacula/bin/bacula-sd", "-f", "-c", "/opt/bacula/etc/bacula-sd.conf"]
networks:
- backup
networks:
backup:
driver: bridge
volumes:
bacula-config:
bacula-data:
bacula-catalog:
bacula-logs:
Note: The bacularis/bacularis-standalone image bundles the Bacula Director, Storage Daemon, PostgreSQL catalog, and the Bacularis web UI in a single image. For production multi-server deployments, use separate bacula-dir, bacula-sd, and bacula-fd images.
Start the stack:
docker compose up -d
Initial Setup
- Open the Bacularis web UI at
http://your-server-ip:9097 - Log in with the credentials from your environment variables
- Navigate to Configuration → Director to review default job definitions
- The default configuration includes a self-backup job — verify it runs successfully
Add a Client Machine
Each machine you want to back up needs the Bacula File Daemon installed:
On the client (Debian/Ubuntu):
apt install bacula-fd
On the client (RHEL/Rocky):
dnf install bacula-client
Edit the client’s /etc/bacula/bacula-fd.conf:
Director {
Name = bacula-dir
Password = "shared-secret-password" # Must match Director's client config
}
FileDaemon {
Name = client-hostname-fd
Maximum Concurrent Jobs = 5
}
Then register the client in the Director’s configuration via the web UI or by editing the Director config.
Configuration
Job Definitions
Bacula uses jobs to define what to back up, when, and where. A minimal job includes:
- Client: which machine to back up
- FileSet: which directories to include/exclude
- Schedule: when to run (full, incremental, differential)
- Pool: which storage pool to target
- Level: Full, Incremental, or Differential
Retention Policies
| Setting | Recommended Value | Purpose |
|---|---|---|
| File Retention | 60 days | How long individual file records are kept in the catalog |
| Job Retention | 180 days | How long job records are kept |
| Volume Retention | 365 days | How long backup volumes are retained |
| Maximum Volume Bytes | 50 GB | Maximum size per backup volume file |
| Maximum Volumes | 100 | Maximum volumes per pool |
Backup Levels
| Level | Backs Up | Speed | Storage |
|---|---|---|---|
| Full | Everything in the FileSet | Slowest | Most |
| Differential | Changes since last Full | Medium | Medium |
| Incremental | Changes since last backup of any level | Fastest | Least |
A common schedule: Full weekly, Differential daily, Incremental hourly.
Reverse Proxy
To expose the Bacularis web UI securely:
server {
listen 443 ssl;
server_name bacula.example.com;
location / {
proxy_pass http://localhost:9097;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
See Reverse Proxy Setup for full configuration.
Backup
The Bacula catalog database is the most critical piece to protect — without it, you can’t restore from backup volumes. Back up:
/opt/bacula/etc/— configuration files- The PostgreSQL catalog database (dump regularly)
- SSH keys and certificates
Use a separate tool (Restic, BorgBackup) to back up the catalog to a different location than your Bacula storage.
Troubleshooting
”No Prior Full Backup” Error
Symptom: Incremental or Differential jobs fail with “No prior Full backup found”
Fix: Run a Full backup for the client first. Incremental and Differential jobs reference the last Full. Without one, they can’t calculate deltas.
Client Connection Refused
Symptom: Director reports “Connection refused” when contacting a client
Fix: Verify the File Daemon is running on the client:
systemctl status bacula-fd
Check that port 9102 is open on the client’s firewall and the password in the client’s bacula-fd.conf matches the Director’s client resource configuration.
Catalog Database Corruption
Symptom: Director fails to start with database errors
Fix: Check PostgreSQL logs in the container. If the catalog is corrupted, restore from your catalog backup:
docker exec -it bacula-director psql -U bacula -d bacula < catalog-backup.sql
Storage Daemon Full
Symptom: Jobs fail with “No appendable volumes” or “Catalog error”
Fix: Either add more disk space to the storage volume, prune expired volumes, or adjust retention policies to release old backup data:
# From bconsole inside the Director container
docker exec -it bacula-director /opt/bacula/bin/bconsole
*prune expired volumes
Resource Requirements
- RAM: 512 MB idle, 1-2 GB during active backup jobs
- CPU: Low to moderate (depends on compression and encryption settings)
- Disk: Depends on data volume. The catalog database grows with the number of files backed up — budget 1-5 GB for the catalog, plus backup storage.
Verdict
Bacula is the most powerful open-source backup system available, but it’s also the most complex. The three-daemon architecture, job/pool/schedule/FileSet configuration model, and catalog management create a steep learning curve. If you’re backing up 10+ machines in a structured environment and need enterprise features (media management, accurate scheduling, detailed reporting), Bacula is worth the investment.
For home servers or small setups (1-5 machines), BackupPC is simpler for centralized pull-based backups, and Restic or BorgBackup are better for individual machine backups. Bacula’s complexity is justified only when you need its enterprise capabilities.
Related
Get self-hosting tips in your inbox
Get the Docker Compose configs, hardware picks, and setup shortcuts we don't put in articles. Weekly. No spam.
Comments