Storage AWS

Bacula on AWS User Guide

| Product: Bacula on AWS

Overview

This guide covers the deployment and use of Bacula on AWS using cloudimg's preconfigured Amazon Machine Image. Bacula is a mature, enterprise grade open source suite for backing up, restoring and verifying data across a network of machines. It is built from cooperating daemons: a Director (bacula-dir) that schedules and coordinates every job; a Storage Daemon (bacula-sd) that writes backup data to disk, tape or a virtual autochanger; and File Daemons (bacula-fd) that run on each protected machine. A catalog database records every job, file, volume and client so restores can be browsed and performed precisely, and everything is driven from the bconsole management console.

The image installs Bacula 13.0.4 and runs the Director, a Storage Daemon writing to a file based volume, a local File Daemon and a PostgreSQL 16 catalog together on one instance. It is a self contained backup appliance: it backs itself up out of the box (a ready to run BackupClient1 job), and you point the File Daemons of your other servers at it to protect them too.

Dedicated data volumes. The PostgreSQL catalog lives on its own EBS volume mounted at /var/lib/postgresql, and the backup volumes and restore staging live on a second EBS volume mounted at /var/lib/bacula, both kept separate from the operating system disk and mounted by filesystem UUID. You can grow, snapshot or move your backup storage independently of the OS.

Secure by default - no shipped credentials. The Bacula packages bake per install passwords into the daemon config files and the catalog. cloudimg replaces every one of them on the first boot of every instance with unique per instance secrets written to a root only file, so no two instances ever share a login and no upstream default survives into the image. All daemons and the catalog are bound to loopback only, and the backup daemon ports are not open in the shipped Security Group.

What is included:

  • Bacula 13.0.4 (Director, Storage Daemon, File Daemon, bconsole), run under systemd
  • A PostgreSQL 16 catalog, built fresh with a unique password on each instance's first boot, on a dedicated EBS volume
  • A ready to run BackupClient1 backup job writing to a file based Storage volume in /var/lib/bacula/backups on a dedicated EBS volume
  • Per instance Director, Storage, File daemon and catalog passwords generated on first boot, written 0600 to /root/bacula-credentials.txt
  • All daemons and the catalog bound to loopback, and the backup ports closed in the shipped Security Group, for a secure default

Connecting to your instance

Connect over SSH on TCP port 22 using your EC2 key pair. The login user depends on the operating system variant you launched:

OS variant SSH login user
Ubuntu 24.04 ubuntu
ssh -i /path/to/your-key.pem ubuntu@<public-ip>

Prerequisites

Before you deploy this image you need:

  • An Amazon Web Services account where you can launch EC2 instances
  • IAM permissions to launch instances, create security groups, and subscribe to AWS Marketplace products
  • An EC2 key pair in the target Region for administrator SSH access to the instance
  • A VPC and subnet in the target Region, with a Security Group allowing inbound TCP port 22 from your administrator network. No product ports need to be open to the internet for the single node appliance; backing up remote clients uses the daemon ports you open deliberately (see Step 8)
  • The AWS CLI version 2 installed locally if you plan to deploy from the command line

Recommended instance type: m5.large is a sensible starting point for the Director, daemons and catalog on a single node. Size up for large catalogs, many concurrent jobs, or a heavy backup workload.

Step 1: Launch the Instance from the AWS Marketplace

Subscribe to the product in AWS Marketplace, then choose Continue to Launch. Select your instance type (an m5.large is a sensible starting point), your VPC and subnet, and your EC2 key pair. Attach a Security Group that allows inbound TCP 22 from your administrator network. You do not need to open any other ports to launch.

The image provisions the dedicated catalog and backup data volumes automatically, so you do not need to attach them manually. If you want larger backup storage, increase the size of the backup data volume at launch or grow it later.

Step 2: Launch the Instance from the AWS CLI

You can also launch from the command line. Replace the AMI id, key name, subnet, and security group with your own values.

aws ec2 run-instances \
  --image-id ami-xxxxxxxxxxxxxxxxx \
  --instance-type m5.large \
  --key-name your-key \
  --subnet-id subnet-xxxxxxxx \
  --security-group-ids sg-xxxxxxxx \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=bacula-01}]'

Step 3: First boot

On the first boot of every instance, bacula-firstboot.service generates unique per instance daemon and catalog passwords, renders the /etc/bacula configuration from placeholder templates, builds a fresh PostgreSQL catalog on the dedicated data volume, and starts the Director, Storage Daemon and File Daemon. First boot completes in a few seconds. The unique credentials for this instance are written to /root/bacula-credentials.txt.

Step 4: Confirm the daemons are running

SSH in and confirm the three Bacula daemons and the catalog are active, then open the console and check the Director's status:

systemctl is-active bacula-director bacula-sd bacula-fd postgresql
echo 'status director' | sudo bconsole

You should see all four services report active, and the Director report its version, resources and scheduled jobs.

All four services (bacula-director, bacula-sd, bacula-fd and postgresql) report active, and bconsole status director shows the Director version 13.0.4, its resources and the scheduled BackupClient1 and BackupCatalog jobs

Step 5: Run a backup and restore

The appliance ships a ready to run backup job, BackupClient1, that backs up the local File Daemon to the file based Storage on the dedicated backup volume. Run it now and wait for it to finish:

printf 'run job=BackupClient1 yes\nwait\nmessages\nquit\n' | sudo bconsole

Bacula queues the job, connects the Director to the Storage Daemon and File Daemon over TLS, writes the data to a volume, and reports Termination: Backup OK with the number of files and bytes written.

Restore is driven from the same console. This restores everything from the most recent backup job into /var/lib/bacula/restores and waits for it to finish, then counts the restored files:

JID=$(printf 'list jobs\nquit\n' | sudo bconsole | awk '/BackupClient1/ {j=$1} END{print j}')
printf "restore jobid=$JID where=/var/lib/bacula/restores all done\nyes\nwait\nmessages\nquit\n" | sudo bconsole
echo "restored files: $(sudo find /var/lib/bacula/restores -type f | wc -l)"

The appliance restores the volume back through the Storage Daemon and writes the files under the where directory, reporting Termination: Restore OK. The screenshot below shows a full round trip: a known file is backed up, deleted, restored from the catalog, and confirmed identical by SHA-256.

A real Bacula backup job terminating Backup OK with the files and bytes written, followed by a restore of the same file that terminates Restore OK, and a SHA-256 comparison showing the restored file matches the source byte-for-byte

For a selective restore, run restore interactively in bconsole and use the file tree browser (mark, unmark, estimate, done) to pick exactly which files or directories to recover, and set where=/ to restore in place.

Step 6: Inspect the catalog

Every job and volume is recorded in the catalog on the dedicated database volume. List the completed jobs and the backup volumes:

printf 'list jobs\nquit\n' | sudo bconsole
printf 'list volumes\nquit\n' | sudo bconsole

list jobs shows each job with its status: T means the job terminated normally. list volumes shows the file based volumes the Storage Daemon has written, with their sizes.

Step 7: Review the security posture

The per instance Director, Storage, File daemon and catalog passwords generated on first boot are stored in a root only file. You do not need them for day to day console use (bconsole reads its own configured password), but they are there when you need to connect to the catalog directly or reconfigure a daemon. Confirm the file permissions and that every daemon is bound to loopback:

sudo stat -c '%a %U:%G %n' /root/bacula-credentials.txt
ss -tln | grep -E '9101|9102|9103|5432'

The credentials file is 0600 root:root, and the Director (9101), File Daemon (9102), Storage Daemon (9103) and PostgreSQL catalog (5432) are all bound to 127.0.0.1 only. Nothing backup related is reachable off the instance until you deliberately open it.

The per instance credentials file is 0600 root owned and holds unique Director and catalog passwords (values masked), the Director, File Daemon, Storage Daemon and PostgreSQL catalog are all bound to 127.0.0.1 loopback only, and the catalog and backup volumes are on separate dedicated EBS data volumes

Step 8: Back up your own servers (remote File Daemons)

To protect other machines, install bacula-fd on each one and add a matching Client and Job to this Director. For security the appliance binds every daemon to loopback by default; to accept connections from remote File Daemons, bind the Storage Daemon to the instance's address and open the daemon ports (9101-9103) only to your backup network. The following is illustrative - adapt the names, addresses and passwords to your environment:

# 1. On THIS Director, add a Client + Job in /etc/bacula/bacula-dir.conf:
Client {
  Name = webserver-fd
  Address = 10.0.0.20        # the remote server's address
  FDPort = 9102
  Catalog = MyCatalog
  Password = "<a-strong-shared-password>"   # must match the remote bacula-fd.conf
}
Job {
  Name = "Backup-webserver"
  JobDefs = "DefaultJob"
  Client = webserver-fd
}

# 2. On the REMOTE server (bacula-fd installed), in /etc/bacula/bacula-fd.conf,
#    add a Director resource with the SAME name + password as this Director.

# 3. Bind this appliance's SD to the instance address so remote FDs can reach it:
#    edit SDAddress in /etc/bacula/bacula-sd.conf, then restart, and open
#    ports 9101-9103 to your backup network only in the EC2 Security Group.

After editing the configuration, apply it:

printf 'reload\nquit\n' | sudo bconsole

Step 9: Retrieve this instance's unique credentials

You can query the catalog directly with the per instance database password over loopback. This reads the unique password from the credentials file at runtime, so no secret is ever typed on the command line:

DBPW=$(sudo grep '^BACULA_DB_PASSWORD=' /root/bacula-credentials.txt | cut -d= -f2-)
PGPASSWORD="$DBPW" psql -h 127.0.0.1 -U bacula -d bacula \
  -c "SELECT jobid, name, level, jobstatus FROM job ORDER BY jobid DESC LIMIT 5;"

Step 10: Security recommendations

  • Keep the Bacula daemons and the PostgreSQL catalog bound to loopback. Only expose the Storage and File daemon ports (9101-9103) to your backup network, via a tightly scoped Security Group rule, when you add remote clients.
  • The per instance passwords in /root/bacula-credentials.txt are unique to this instance. Treat that file as sensitive and keep it 0600.
  • The catalog and backup volumes are already on dedicated EBS data volumes separate from the OS disk. Grow the backup volume as your footprint increases, and snapshot it for off instance retention.
  • Keep the OS patched. The image ships fully updated with unattended security upgrades enabled.

Step 11: Support and Licensing

Bacula is free and open source software distributed under the GNU Affero General Public License, version 3 (AGPL-3.0). This image bundles Bacula unmodified; your use of Bacula is governed by its license. The verbatim licence text and a written offer for the corresponding source are baked into the image under /usr/local/share/cloudimg-bacula (LICENSE.AGPL-3.0 and SOURCE_OFFER.txt). The corresponding source is also available directly on the instance with apt-get source bacula-director and from the Bacula project at bacula.org.

cloudimg images include 24/7 support. If you need help deploying or configuring Bacula on AWS, contact us.

Need Help?

Email support@cloudimg.co.uk and our team will help you get up and running.