Encrypted offsite backups on auto-mounted media with Bacula & vchanger

Configuring Bacula:

In the Bacula configuration files listed below, only the parts relevent to this tutorial are included. On Gentoo, the default location for Bacula's configuration files is /etc/bacula, but we keep ours one directory below in /etc/bacula/include so that we can allow Gentoo's dispatch-conf (configuration file updating tool) to keep the default Bacula config files up-to-date for reference while not touching our modified files.

Configuring Bacula's Director Daemon
To keep our configuration managable, each of the configuration sections have been pulled out of bacula-dir.conf and are stored in separate files which are pulled into the bacula-dir.conf file via the file include option:


Director {
  Name = backup-dir
  DIR port = 9101
  QueryFile = /usr/libexec/bacula/query.sql
  WorkingDirectory = /var/lib/bacula
  PidDirectory = /var/run
  Password = "verysecurepassword"
  Maximum Concurrent Jobs = 6
  Messages = Daemon


# Include Storage

# Include Pools

# Include Jobs


In the Storage file, a Storage definition block is configured. The Name = c0 is the same as the changer_name in our vchanger configuration.

The Device = eSATA-Changer is our changer device that will be configured later in the Autochanger definition block of the Bacula storage daemon confgiuration file.

The Autochanger = yes line must be present for this Storage resource, and the Media Type = Offsite-File needs to match the Pool defined next.


Storage {
  Name = c0
  Address = storagedaemon.example.com
  Password = "verysecurepassword"
  Device = eSATA-Changer
  Autochanger = yes
  Media Type = Offsite-File

In the Pools file a Pool resource named Offsite-eSATA is created with pretty basic options. The Storage = c0 line defines that this pool will use the c0 Storage resource defined above.


Pool {
  Name = Offsite-eSATA
  Storage = c0
  Pool Type = Backup
  Recycle = yes
  AutoPrune = yes
  Volume Retention = 4 weeks
  Recycle Oldest Volume = yes
  Volume Use Duration = 2 hours
  Maximum Volume Bytes = 10737418240  # Small (10GB) easy to move/transfer volume sizes

NOTE: The Volume Use Duration = 2 hours line should be enough to prevent Bacula from trying to use an already-written-to volume that has a status of "append" when/if a magazine is changed, while allowing enough time for consecutively run jobs to complete writing to the relatively small 10GB volume. For more details on this issue, see the vchanger docs, section 12.3, paragraph 3.

Since the vchanger "magazines" (the encrypted drives with multiple 10GB Bacula volumes) will be swapped in and out, we need a way for Bacula to know which volumes are available for use. That is, which 10GB volumes are on the drive(s) currently plugged into the system.

In the bconsole command line interface to Bacula, the command update slots instructs bacula to poll a specified tape library to see which volumes are available and which slots they are in. Bacula then updates the InChanger and Slot columns of the Media table in the database with this information. Now Bacula knows which volumes are currently available to it and in which slot of the library each of them is.

To automate this process so that no one needs to manually load bconsole and run the "update slots" command each time a magazine is plugged in or unplugged, a custom script that uses bconsole will be used. It will be scheduled to run via a special Bacula job type of Admin.

In the Jobs file, a job called UpdateSlots with a type of Admin is created. This purpose of this job is to run a script via Bacula's RunsScript definition. The script will call the bconsole program and run the "update slots" command. This job will use the same schedule as the other nightly jobs, but will have a higher priority (lower number) so that it will be the first job to run every night. This way, the magazine(s) may be swapped out each morning when all the backup jobs have finished. No other manual steps are required.


Job {
  Name = UpDateSlots
  Client = None
  Type = Admin
  FileSet = None
  Storage = c0
  Schedule = WeeklyToOffsiteDisk
  Messages = Standard
  Priority = 8   # Other nightly jobs have a priority of 10
  SpoolData = no
  Pool = Default

  RunScript {
    RunsWhen = Before
    RunsOnClient = no
    Fail Job On Error = no
    Command = "/etc/bacula/include/runbefore-updateslots.sh"

Here is the simple bash shell script that uses bconsole to run the "update slots" command:


DRIVE="0"   # If multiple drives are defined in the Changer
            # device bconsole will ask for a drive number

update slots storage=$STORAGE drive=$DRIVE

Configuring Bacula's Storage Daemon

In the Bacula storage daemon configuration file an Autochanger called eSATA-Changer is first defined. Per the vchanger documentation, the Changer Command points to the vchanger binary. vchanger is configured to run as the user bacula and group of bacula. Your configuration may differ, but the user configured here must have read/write access to the vchnager directories created during the vchanger installation as well as read/write access to the Bacula "file" volumes on the encrypted drives.

The rest of the parameters are the substitution variables that will be passed to the vchanger program and are defined in Bacula's documentation as follows:

  • %c - Changer Device Name
  • %o - Command (Loaded, Load or Unload)
  • %S - Autochanger slot to act on (base 1)
  • %a - Archive Device Name
  • %d - Changer drive index (base 0)

Autochanger {
  Name = eSATA-Changer
  Device = eSATA-1
  Changer Command = "/usr/local/bin/vchanger -u bacula -g bacula %c %o %S %a %d"
  Changer Device = /etc/bacula/include/vchanger.conf

Per the vchanger documentation, the Changer Device points to /etc/bacula/include/vchanger.conf, the vchanger configuration file.

The Device in the Autochanger definition block points to the name of a tape drive, or a filetape drive which needs to be defined in the badcula-sd.conf file as well:

Next in the Bacula storage daemon configuration file the eSATA-1 referenced in the eSATA-Changer Autochanger definition is configured:


Device {
  Name = eSATA-1
  DriveIndex = 0
  Autochanger = yes
  Device Type = File
  Media Type = Offsite-File
  Label Media = no
  Random Access = yes
  Removable Media = yes
  Automatic Mount = yes
  Archive Device = /var/lib/bacula/vchanger/c0/0/drive0

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Few Modifications

A few things I ran into running this on current versions of cryptsetup.

1. You can create the encrypted drive WITH key in one command now;
cryptsetup -v luksFormat /dev/sdb --key-file /etc/bacula/include/Bacula_Key_File

2. There is a new format for the arguments? for key-file. For example;
cryptsetup -v luksOpen --key-file /etc/bacula/include/Bacula_Key_File /dev/sdb tempcontainer

3. I had to install some requirements in my ubuntu server 12.04 x64.
sudo apt-get install libblkid-dev
sudo apt-get install uuid-dev

4. I had a lot of trouble with the Client = None and Fileset = None. I thought they were built in keywords, wasn't until I read http://blog.serverfault.com/2011/01/10/some-notes-on-setting-up-backups-... that I realized they were just dummy ones created.

Very informative ,well written.

Thank you, this tutorial helped a huge amount.I've been struggling to automate the decryption and mounting/unmounting. This tutorial enabled me to accomplish exactly what we needed.

Great job!

Hi! Great job with this howto!

I'm using Bacula since 2.4 releases and it's the first time I found a solution to encrypt all the Bacula volumes and get the 'perfect' OUT-OF-OFFICE solution.


Thanks so much for this!
Incredibly thorough. As a recent Bacula convert I've found it really useful.

Post new comment

  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <b> <i> <u> <strong> <cite> <code> <pre> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.

More information about formatting options

This question is for testing whether you are a human visitor and to prevent automated spam submissions.
Enter the code without spaces and pay attention to upper/lower case.