Skip to content

DirSourceAddress option causes "Error: bsockcore.c:400 Source address bind error. proto=2. ERR=Invalid argument"

Summary

Reproducibility Platform OS OS Version Product Version
always AMD64 Ubuntu Noble 13.0.4

Description

The director option DirSourceAddress causes errors to be logged during the backup:

27-Jan 14:12 XXXX-fd JobId 92959: Error: bsockcore.c:400 Source address bind error. proto=2. ERR=Invalid argument

Backups complete with "OK -- with warnings", but strace shows that bacula-dir tries to bind an AF_INET6 socket to an IPv4 address (regardless of whether DirSourceAddress is IPv4 or IPv6).

Steps to Reproduce

  1. Create Ubuntu 24.04 container or VM for director. apt-get install bacula-server bacula-console
  2. Configure as below. Test with "run BackupCatalog" at bconsole. Check that it ends with "Termination: Backup OK"
  3. Add to the Director{} block: DirSourceAddress = 10.65.5.21, where this is the external IP of the container or VM
    • (127.0.0.1 can also be used to demonstrate the problem, but the strace is clearer with a real IP address)
  4. systemctl restart bacula-director. Optional: strace -f -s 256 -p $(pidof bacula-dir) 2>/var/tmp/bacula.strace
  5. Re-run the BackupCatalog job

The following is logged:

27-Jan 16:23 director-dir JobId 7: shell command: run BeforeJob "/etc/bacula/scripts/make_catalog_backup.pl MyCatalog"
27-Jan 16:23 director-dir JobId 7: Start Backup JobId 7, Job=BackupCatalog.2025-01-27_16.23.06_03
27-Jan 16:23 director-dir JobId 7: Error: bsockcore.c:400 Source address bind error. proto=2. ERR=Invalid argument   <<<< NOTE <<<<
27-Jan 16:23 director-dir JobId 7: Connected to Storage "File1" at localhost:9103 with TLS
27-Jan 16:23 director-dir JobId 7: Using Device "FileChgr1-Dev2" to write.
27-Jan 16:23 director-dir JobId 7: Error: bsockcore.c:400 Source address bind error. proto=2. ERR=Invalid argument   <<<< NOTE <<<<
27-Jan 16:23 director-dir JobId 7: Connected to Client "director-fd" at localhost:9102 with TLS
27-Jan 16:23 director-fd JobId 7: Connected to Storage at localhost:9103 with TLS
27-Jan 16:23 director-sd JobId 7: Volume "Vol-0007" previously written, moving to end of data.
27-Jan 16:23 director-sd JobId 7: Ready to append to end of Volume "Vol-0007" size=210,237
27-Jan 16:23 director-sd JobId 7: Elapsed time=00:00:01, Transfer rate=76.83 K Bytes/second
27-Jan 16:23 director-sd JobId 7: Sending spooled attrs to the Director. Despooling 220 bytes ...
27-Jan 16:23 director-dir JobId 7: Bacula director-dir 13.0.4 (12Feb24):
...
  Termination:            Backup OK -- with warnings

Looking at the strace output:

[pid  8817] socket(AF_INET6, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_IP) = 9
[pid  8817] bind(9, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("10.65.5.21")}, 16) = -1 EINVAL (Invalid argument)
[pid  8817] openat(AT_FDCWD, "/usr/share/locale/en_US.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid  8817] openat(AT_FDCWD, "/usr/share/locale/en_US.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid  8817] openat(AT_FDCWD, "/usr/share/locale/en_US/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid  8817] openat(AT_FDCWD, "/usr/share/locale/en.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid  8817] openat(AT_FDCWD, "/usr/share/locale/en.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid  8817] openat(AT_FDCWD, "/usr/share/locale/en/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid  8817] openat(AT_FDCWD, "/usr/share/locale-langpack/en_US.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid  8817] openat(AT_FDCWD, "/usr/share/locale-langpack/en_US.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid  8817] openat(AT_FDCWD, "/usr/share/locale-langpack/en_US/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid  8817] openat(AT_FDCWD, "/usr/share/locale-langpack/en.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid  8817] openat(AT_FDCWD, "/usr/share/locale-langpack/en.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid  8817] openat(AT_FDCWD, "/usr/share/locale-langpack/en/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid  8817] fstat(1, {st_mode=S_IFSOCK|0777, st_size=0, ...}) = 0
[pid  8817] write(1, "director-dir: message.c:1835-7 bsockcore.c:400 Source address bind error. proto=2. ERR=Invalid argument\n", 104) = 104
[pid  8817] write(1, "director-dir: bsockcore.c:402-7 Source address bind error. proto=2. ERR=Invalid argument\n", 89) = 89
[pid  8817] close(9)                    = 0
...
[pid  8817] socket(AF_INET6, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_IP) = 10
[pid  8817] bind(10, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("10.65.5.21")}, 16) = -1 EINVAL (Invalid argument)
[pid  8817] write(1, "director-dir: message.c:1835-7 bsockcore.c:400 Source address bind error. proto=2. ERR=Invalid argument\n", 104) = 104
[pid  8817] write(1, "director-dir: bsockcore.c:402-7 Source address bind error. proto=2. ERR=Invalid argument\n", 89) = 89
[pid  8817] close(10)                   = 0

It has twice created an AF_INET6 socket, but tried to bind an IPv4 address to it!

Next, repeat this experiment with DirSourceAddress = fd42:81e:c751:8c26:216:3eff:fe39:87e7 (the IPv6 address of the container, and again you can use ::1 if you prefer). This time you get the same Source address bind error, with the following strace:

[pid  8918] socket(AF_INET6, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_IP) = 9
[pid  8918] bind(9, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("0.0.0.0")}, 16) = -1 EINVAL (Invalid argument)
[pid  8918] openat(AT_FDCWD, "/usr/share/locale/en_US.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid  8918] openat(AT_FDCWD, "/usr/share/locale/en_US.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid  8918] openat(AT_FDCWD, "/usr/share/locale/en_US/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid  8918] openat(AT_FDCWD, "/usr/share/locale/en.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid  8918] openat(AT_FDCWD, "/usr/share/locale/en.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid  8918] openat(AT_FDCWD, "/usr/share/locale/en/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid  8918] openat(AT_FDCWD, "/usr/share/locale-langpack/en_US.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid  8918] openat(AT_FDCWD, "/usr/share/locale-langpack/en_US.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid  8918] openat(AT_FDCWD, "/usr/share/locale-langpack/en_US/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid  8918] openat(AT_FDCWD, "/usr/share/locale-langpack/en.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid  8918] openat(AT_FDCWD, "/usr/share/locale-langpack/en.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid  8918] openat(AT_FDCWD, "/usr/share/locale-langpack/en/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid  8918] fstat(1, {st_mode=S_IFSOCK|0777, st_size=0, ...}) = 0
[pid  8918] write(1, "director-dir: message.c:1835-8 bsockcore.c:400 Source address bind error. proto=2. ERR=Invalid argument\n", 104) = 104
[pid  8918] write(1, "director-dir: bsockcore.c:402-8 Source address bind error. proto=2. ERR=Invalid argument\n", 89) = 89
[pid  8918] close(9)                    = 0
...
[pid  8918] socket(AF_INET6, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_IP) = 10
[pid  8918] bind(10, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("0.0.0.0")}, 16) = -1 EINVAL (Invalid argument)
[pid  8918] write(1, "director-dir: message.c:1835-8 bsockcore.c:400 Source address bind error. proto=2. ERR=Invalid argument\n", 104) = 104
[pid  8918] write(1, "director-dir: bsockcore.c:402-8 Source address bind error. proto=2. ERR=Invalid argument\n", 89) = 89
[pid  8918] close(10)                   = 0

This time it has correctly opened an AF_INET6 socket, but it tries to bind the IPv4 address 0.0.0.0, instead of the IPv6 address given.

I believe the correct behaviour should be:

  • If DirSourceAddress is IPv4, then open an AF_INET socket (not AF_INET6) and bind it to the given IPv4 address
  • If DirSourceAddress is IPv6, then open an AF_INET6 socket and bind it to the given IPv6 address (not 0.0.0.0)

It looks like a mixup of address families.

Additional Information

Aside: the reason I want to use this option is to force a Bacula director running on a dual-stack host to originate outbound connections to remote bacula-fd over IPv4, by binding outgoing connections to the local IPv4 network address.

director setup:

mkdir -p /backup/bacula /backup/restore
chown -R bacula:bacula /backup

config files: only minimal differences from ubuntu defaults

==> bacula-dir.conf <==
#
# Default Bacula Director Configuration file
#
#  The only thing that MUST be changed is to add one or more
#   file or directory names in the Include directive of the
#   FileSet resource.
#
#  You might also want to change the default email address
#   from root to your address.  See the "mail" and "operator"
#   directives in the Messages resource.
#
# Copyright (C) 2000-2022 Kern Sibbald
# License: BSD 2-Clause; see file LICENSE-FOSS
#

Director {                            # define myself
  Name = director-dir
  DIRport = 9101                # where we listen for UA connections
  QueryFile = "/etc/bacula/scripts/query.sql"
  WorkingDirectory = "/var/lib/bacula"
  PidDirectory = "/run/bacula"
  Maximum Concurrent Jobs = 20
  Password = "Cvd08HohGuuFZ1ZiY2tv_FXR-fO3DLWHk"         # Console password
  Messages = Daemon
  DirAddress = 127.0.0.1
  #DirSourceAddress = 127.0.0.1  # THIS IS THE REPRODUCER
}

JobDefs {
  Name = "DefaultJob"
  Type = Backup
  Level = Incremental
  Client = director-fd
  FileSet = "Full Set"
  Schedule = "WeeklyCycle"
  Storage = File1
  Messages = Standard
  Pool = File
  SpoolAttributes = yes
  Priority = 10
  Write Bootstrap = "/var/lib/bacula/%c.bsr"
}


#
# Define the main nightly save backup job
#   By default, this job will back up to disk in /nonexistent/path/to/file/archive/dir
Job {
  Name = "BackupClient1"
  JobDefs = "DefaultJob"
}

#Job {
#  Name = "BackupClient2"
#  Client = director2-fd
#  JobDefs = "DefaultJob"
#}

#Job {
#  Name = "BackupClient1-to-Tape"
#  JobDefs = "DefaultJob"
#  Storage = LTO-4
#  Spool Data = yes    # Avoid shoe-shine
#  Pool = Default
#}

#}

# Backup the catalog database (after the nightly save)
Job {
  Name = "BackupCatalog"
  JobDefs = "DefaultJob"
  Level = Full
  FileSet="Catalog"
  Schedule = "WeeklyCycleAfterBackup"
  # This creates an ASCII copy of the catalog
  # Arguments to make_catalog_backup.pl are:
  #  make_catalog_backup.pl <catalog-name>
  RunBeforeJob = "/etc/bacula/scripts/make_catalog_backup.pl MyCatalog"
  # This deletes the copy of the catalog
  RunAfterJob  = "/etc/bacula/scripts/delete_catalog_backup"
  Write Bootstrap = "/var/lib/bacula/%n.bsr"
  Priority = 11                   # run after main backup
}

#
# Standard Restore template, to be changed by Console program
#  Only one such job is needed for all Jobs/Clients/Storage ...
#
Job {
  Name = "RestoreFiles"
  Type = Restore
  Client=director-fd
  Storage = File1
# The FileSet and Pool directives are not used by Restore Jobs
# but must not be removed
  FileSet="Full Set"
  Pool = File
  Messages = Standard
  Where = /bacula/restore
}


# List of files to be backed up
FileSet {
  Name = "Full Set"
  Include {
    Options {
      signature = MD5
    }
#
#  Put your list of files here, preceded by 'File =', one per line
#    or include an external list with:
#
#    File = <file-name
#
#  Note: / backs up everything on the root partition.
#    if you have other partitions such as /usr or /home
#    you will probably want to add them too.
#
#  By default this is defined to point to the Bacula binary
#    directory to give a reasonable FileSet to backup to
#    disk storage during initial testing.
#
    File = /usr/sbin
  }

#
# If you backup the root directory, the following two excluded
#   files can be useful
#
  Exclude {
    File = /var/lib/bacula
    File = /bacula
    File = /proc
    File = /tmp
    File = /sys
    File = /.journal
    File = /.fsck
  }
}

#
# When to do the backups, full backup on first sunday of the month,
#  differential (i.e. incremental since full) every other sunday,
#  and incremental backups other days
Schedule {
  Name = "WeeklyCycle"
  Run = Full 1st sun at 23:05
  Run = Differential 2nd-5th sun at 23:05
  Run = Incremental mon-sat at 23:05
}

# This schedule does the catalog. It starts after the WeeklyCycle
Schedule {
  Name = "WeeklyCycleAfterBackup"
  Run = Full sun-sat at 23:10
}

# This is the backup of the catalog
FileSet {
  Name = "Catalog"
  Include {
    Options {
      signature = MD5
    }
    File = "/var/lib/bacula/bacula.sql"
  }
}

# Client (File Services) to backup
Client {
  Name = director-fd
  Address = localhost
  FDPort = 9102
  Catalog = MyCatalog
  Password = "-4GrFizRjkYcMd48t_v2fwnBHSeo2-j_U"          # password for FileDaemon
  File Retention = 60 days            # 60 days
  Job Retention = 6 months            # six months
  AutoPrune = yes                     # Prune expired Jobs/Files
}

#
# Second Client (File Services) to backup
#  You should change Name, Address, and Password before using
#
#Client {
#  Name = director2-fd
#  Address = localhost2
#  FDPort = 9102
#  Catalog = MyCatalog
#  Password = "-4GrFizRjkYcMd48t_v2fwnBHSeo2-j_U2"        # password for FileDaemon 2
#  File Retention = 60 days           # 60 days
#  Job Retention = 6 months           # six months
#  AutoPrune = yes                    # Prune expired Jobs/Files
#}


# Definition of file Virtual Autochanger device
Autochanger {
  Name = File1
# Do not use "localhost" here
  Address = localhost                # N.B. Use a fully qualified name here
  SDPort = 9103
  Password = "YoXVo2bL7nHJQVKBp0y3JY1Ho7ZsCARuJ"
  Device = FileChgr1
  Media Type = File1
  Maximum Concurrent Jobs = 10        # run up to 10 jobs a the same time
  Autochanger = File1                 # point to ourself
}

# Definition of a second file Virtual Autochanger device
#   Possibly pointing to a different disk drive
Autochanger {
  Name = File2
# Do not use "localhost" here
  Address = localhost                # N.B. Use a fully qualified name here
  SDPort = 9103
  Password = "YoXVo2bL7nHJQVKBp0y3JY1Ho7ZsCARuJ"
  Device = FileChgr2
  Media Type = File2
  Autochanger = File2                 # point to ourself
  Maximum Concurrent Jobs = 10        # run up to 10 jobs a the same time
}

# Definition of LTO-4 tape Autochanger device
#Autochanger {
#  Name = LTO-4
#  Do not use "localhost" here
#  Address = localhost               # N.B. Use a fully qualified name here
#  SDPort = 9103
#  Password = "YoXVo2bL7nHJQVKBp0y3JY1Ho7ZsCARuJ"         # password for Storage daemon
#  Device = LTO-4                     # must be same as Device in Storage daemon
#  Media Type = LTO-4                 # must be same as MediaType in Storage daemon
#  Autochanger = LTO-4                # enable for autochanger device
#  Maximum Concurrent Jobs = 10
#}

# Generic catalog service
Catalog {
  Name = MyCatalog
  dbname = "bacula"; DB Address = "localhost"; dbuser = "bacula"; dbpassword = "abcd1234"
}

# Reasonable message delivery -- send most everything to email address
#  and to the console
Messages {
  Name = Standard
#
# NOTE! If you send to two email or more email addresses, you will need
#  to replace the %r in the from field (-f part) with a single valid
#  email address in both the mailcommand and the operatorcommand.
#  What this does is, it sets the email address that emails would display
#  in the FROM field, which is by default the same email as they're being
#  sent to.  However, if you send email to more than one address, then
#  you'll have to set the FROM address manually, to a single address.
#  for example, a 'no-reply@mydomain.com', is better since that tends to
#  tell (most) people that its coming from an automated source.

#
  mailcommand = "/usr/sbin/bsmtp -h localhost -f \"\(Bacula\) \<%r\>\" -s \"Bacula: %t %e of %c %l\" %r"
  operatorcommand = "/usr/sbin/bsmtp -h localhost -f \"\(Bacula\) \<%r\>\" -s \"Bacula: Intervention needed for %j\" %r"
  mail = root = all, !skipped
  operator = root = mount
  console = all, !skipped, !saved
#
# WARNING! the following will create a file that you must cycle from
#          time to time as it will grow indefinitely. However, it will
#          also keep all your messages if they scroll off the console.
#
  append = "/var/log/bacula/bacula.log" = all, !skipped
  catalog = all
}


#
# Message delivery for daemon messages (no job).
Messages {
  Name = Daemon
  mailcommand = "/usr/sbin/bsmtp -h localhost -f \"\(Bacula\) \<%r\>\" -s \"Bacula daemon message\" %r"
  mail = root = all, !skipped
  console = all, !skipped, !saved
  append = "/var/log/bacula/bacula.log" = all, !skipped
}

# Default pool definition
Pool {
  Name = Default
  Pool Type = Backup
  Recycle = yes                       # Bacula can automatically recycle Volumes
  AutoPrune = yes                     # Prune expired volumes
  Volume Retention = 365 days         # one year
  Maximum Volume Bytes = 50G          # Limit Volume size to something reasonable
  Maximum Volumes = 100               # Limit number of Volumes in Pool
}

# File Pool definition
Pool {
  Name = File
  Pool Type = Backup
  Recycle = yes                       # Bacula can automatically recycle Volumes
  AutoPrune = yes                     # Prune expired volumes
  Volume Retention = 365 days         # one year
  Maximum Volume Bytes = 50G          # Limit Volume size to something reasonable
  Maximum Volumes = 100               # Limit number of Volumes in Pool
  Label Format = "Vol-"               # Auto label
}


# Scratch pool definition
Pool {
  Name = Scratch
  Pool Type = Backup
}

#
# Restricted console used by tray-monitor to get the status of the director
#
Console {
  Name = director-mon
  Password = "-8NLUmrwYHNnRU_Fd_p5PxqQAr4HbWZjb"
  CommandACL = status, .status
}

==> bacula-fd.conf <==
#
# Default  Bacula File Daemon Configuration file
#
# There is not much to change here except perhaps the
# File daemon Name to
#
#
# Copyright (C) 2000-2022 Kern Sibbald
# License: BSD 2-Clause; see file LICENSE-FOSS
#

#
# List Directors who are permitted to contact this File daemon
#
Director {
  Name = director-dir
  Password = "-4GrFizRjkYcMd48t_v2fwnBHSeo2-j_U"
}

#
# Restricted Director, used by tray-monitor to get the
#   status of the file daemon
#
Director {
  Name = director-mon
  Password = "dQzPQf_wHP4M4cJLv4EQvK9VDlgCKuF1G"
  Monitor = yes
}

#
# "Global" File daemon configuration specifications
#
FileDaemon {                          # this is me
  Name = director-fd
  FDport = 9102                  # where we listen for the director
  WorkingDirectory = /var/lib/bacula
  Pid Directory = /run/bacula
  Maximum Concurrent Jobs = 20
  Plugin Directory = /usr/lib/bacula
  FDAddress = 127.0.0.1
}

# Send all messages except skipped files back to Director
Messages {
  Name = Standard
  director = director-dir = all, !skipped, !restored, !verified, !saved
}

==> bacula-sd.conf <==
#
# Default Bacula Storage Daemon Configuration file
#
# You may need to change the name of your tape drive
#   on the "Archive Device" directive in the Device
#   resource.  If you change the Name and/or the
#   "Media Type" in the Device resource, please ensure
#   that dird.conf has corresponding changes.
#
#
# Copyright (C) 2000-2022 Kern Sibbald
# License: BSD 2-Clause; see file LICENSE-FOSS
#

Storage {                             # definition of myself
  Name = director-sd
  SDPort = 9103                  # Director's port
  WorkingDirectory = "/var/lib/bacula"
  Pid Directory = "/run/bacula"
  Plugin Directory = "/usr/lib/bacula"
  Maximum Concurrent Jobs = 20
  SDAddress = 127.0.0.1
}

#
# List Directors who are permitted to contact Storage daemon
#
Director {
  Name = director-dir
  Password = "YoXVo2bL7nHJQVKBp0y3JY1Ho7ZsCARuJ"
}

#
# Restricted Director, used by tray-monitor to get the
#   status of the storage daemon
#
Director {
  Name = director-mon
  Password = "DK7ZK-O_1wy3cYoMRmutX1aW-Cz5qz8E-"
  Monitor = yes
}

#
# Note, for a list of additional Device templates please
#  see the directory <bacula-source>/examples/devices
# Or follow the following link:
#  http://www.bacula.org/git/cgit.cgi/bacula/tree/bacula/examples/devices?h=Branch-7.4
#

#
# Devices supported by this Storage daemon
# To connect, the Director's bacula-dir.conf must have the
#  same Name and MediaType.
#

#
# Define a Virtual autochanger
#
Autochanger {
  Name = FileChgr1
  Device = FileChgr1-Dev1, FileChgr1-Dev2
  Changer Command = ""
  Changer Device = /dev/null
}

Device {
  Name = FileChgr1-Dev1
  Media Type = File1
  Archive Device = /backup/bacula
  LabelMedia = yes;                   # lets Bacula label unlabeled media
  Random Access = Yes;
  AutomaticMount = yes;               # when device opened, read it
  RemovableMedia = no;
  AlwaysOpen = no;
  Maximum Concurrent Jobs = 5
}

Device {
  Name = FileChgr1-Dev2
  Media Type = File1
  Archive Device = /backup/bacula
  LabelMedia = yes;                   # lets Bacula label unlabeled media
  Random Access = Yes;
  AutomaticMount = yes;               # when device opened, read it
  RemovableMedia = no;
  AlwaysOpen = no;
  Maximum Concurrent Jobs = 5
}

#
# Define a second Virtual autochanger
#
Autochanger {
  Name = FileChgr2
  Device = FileChgr2-Dev1, FileChgr2-Dev2
  Changer Command = ""
  Changer Device = /dev/null
}

Device {
  Name = FileChgr2-Dev1
  Media Type = File2
  Archive Device = /backup/bacula
  LabelMedia = yes;                   # lets Bacula label unlabeled media
  Random Access = Yes;
  AutomaticMount = yes;               # when device opened, read it
  RemovableMedia = no;
  AlwaysOpen = no;
  Maximum Concurrent Jobs = 5
}

Device {
  Name = FileChgr2-Dev2
  Media Type = File2
  Archive Device = /backup/bacula
  LabelMedia = yes;                   # lets Bacula label unlabeled media
  Random Access = Yes;
  AutomaticMount = yes;               # when device opened, read it
  RemovableMedia = no;
  AlwaysOpen = no;
  Maximum Concurrent Jobs = 5
}



#
# An autochanger device with two drives
#
#Autochanger {
#  Name = Autochanger
#  Device = Drive-1
#  Device = Drive-2
#  Changer Command = "/etc/bacula/scripts/mtx-changer %c %o %S %a %d"
#  Changer Device = /dev/sg0
#}

#Device {
#  Name = Drive-1                      #
#  Drive Index = 0
#  Media Type = DLT-8000
#  Archive Device = /dev/nst0
#  AutomaticMount = yes;               # when device opened, read it
#  AlwaysOpen = yes;
#  RemovableMedia = yes;
#  RandomAccess = no;
#  AutoChanger = yes
#  #
#  # New alert command in Bacula 9.0.0
#  #  Note: you must have the sg3_utils (rpms) or the
#  #        sg3-utils (deb) installed on your system.
#  #        and you must set the correct control device that
#  #        corresponds to the Archive Device
#  Control Device = /dev/sg?? # must be SCSI ctl for /dev/nst0
#  Alert Command = "/etc/bacula/scripts/tapealert %l"
#
#  #
#  # Enable the Alert command only if you have the mtx package loaded
#  # Note, apparently on some systems, tapeinfo resets the SCSI controller
#  #  thus if you turn this on, make sure it does not reset your SCSI
#  #  controller.  I have never had any problems, and smartctl does
#  #  not seem to cause such problems.
#  #
#  Alert Command = "sh -c 'tapeinfo -f %c |grep TapeAlert|cat'"
#  If you have smartctl, enable this, it has more info than tapeinfo
#  Alert Command = "sh -c 'smartctl -H -l error %c'"
#}

#Device {
#  Name = Drive-2                      #
#  Drive Index = 1
#  Media Type = DLT-8000
#  Archive Device = /dev/nst1
#  AutomaticMount = yes;               # when device opened, read it
#  AlwaysOpen = yes;
#  RemovableMedia = yes;
#  RandomAccess = no;
#  AutoChanger = yes
#  # Enable the Alert command only if you have the mtx package loaded
#  Alert Command = "sh -c 'tapeinfo -f %c |grep TapeAlert|cat'"
#  If you have smartctl, enable this, it has more info than tapeinfo
#  Alert Command = "sh -c 'smartctl -H -l error %c'"
#}

#
# A Linux or Solaris LTO-2 tape drive
#
#Device {
#  Name = LTO-2
#  Media Type = LTO-2
#  Archive Device = /dev/nst0
#  AutomaticMount = yes;               # when device opened, read it
#  AlwaysOpen = yes;
#  RemovableMedia = yes;
#  RandomAccess = no;
#  Maximum File Size = 3GB
## Changer Command = "/etc/bacula/scripts/mtx-changer %c %o %S %a %d"
## Changer Device = /dev/sg0
## AutoChanger = yes
#  # Enable the Alert command only if you have the mtx package loaded
## Alert Command = "sh -c 'tapeinfo -f %c |grep TapeAlert|cat'"
## If you have smartctl, enable this, it has more info than tapeinfo
## Alert Command = "sh -c 'smartctl -H -l error %c'"
#}

#
# A Linux or Solaris LTO-3 tape drive
#
#Device {
#  Name = LTO-3
#  Media Type = LTO-3
#  Archive Device = /dev/nst0
#  AutomaticMount = yes;               # when device opened, read it
#  AlwaysOpen = yes;
#  RemovableMedia = yes;
#  RandomAccess = no;
#  Maximum File Size = 4GB
# Changer Command = "/etc/bacula/scripts/mtx-changer %c %o %S %a %d"
# Changer Device = /dev/sg0
# AutoChanger = yes
#  #
#  # New alert command in Bacula 9.0.0
#  #  Note: you must have the sg3_utils (rpms) or the
#  #        sg3-utils (deb) installed on your system.
#  #        and you must set the correct control device that
#  #        corresponds to the Archive Device
#  Control Device = /dev/sg??  # must be SCSI ctl for /dev/nst0
#  Alert Command = "/etc/bacula/scripts/tapealert %l"
#
#  # Enable the Alert command only if you have the mtx package loaded
## Alert Command = "sh -c 'tapeinfo -f %c |grep TapeAlert|cat'"
## If you have smartctl, enable this, it has more info than tapeinfo
## Alert Command = "sh -c 'smartctl -H -l error %c'"
#}

#
# A Linux or Solaris LTO-4 tape drive
#
#Device {
#  Name = LTO-4
#  Media Type = LTO-4
#  Archive Device = /dev/nst0
#  AutomaticMount = yes;               # when device opened, read it
#  AlwaysOpen = yes;
#  RemovableMedia = yes;
#  RandomAccess = no;
#  Maximum File Size = 5GB
# Changer Command = "/etc/bacula/scripts/mtx-changer %c %o %S %a %d"
# Changer Device = /dev/sg0
# AutoChanger = yes
#  #
#  # New alert command in Bacula 9.0.0
#  #  Note: you must have the sg3_utils (rpms) or the
#  #        sg3-utils (deb) installed on your system.
#  #        and you must set the correct control device that
#  #        corresponds to the Archive Device
#  Control Device = /dev/sg??  # must be SCSI ctl for /dev/nst0
#  Alert Command = "/etc/bacula/scripts/tapealert %l"
#
#  # Enable the Alert command only if you have the mtx package loaded
## Alert Command = "sh -c 'tapeinfo -f %c |grep TapeAlert|cat'"
## If you have smartctl, enable this, it has more info than tapeinfo
## Alert Command = "sh -c 'smartctl -H -l error %c'"
#}

#
# An HP-UX tape drive
#
#Device {
#  Name = Drive-1                      #
#  Drive Index = 0
#  Media Type = DLT-8000
#  Archive Device = /dev/rmt/1mnb
#  AutomaticMount = yes;               # when device opened, read it
#  AlwaysOpen = yes;
#  RemovableMedia = yes;
#  RandomAccess = no;
#  AutoChanger = no
#  Two EOF = yes
#  Hardware End of Medium = no
#  Fast Forward Space File = no
#  #
#  # New alert command in Bacula 9.0.0
#  #  Note: you must have the sg3_utils (rpms) or the
#  #        sg3-utils (deb) installed on your system.
#  #        and you must set the correct control device that
#  #        corresponds to the Archive Device
#  Control Device = /dev/sg??  # must be SCSI ctl for /dev/rmt/1mnb
#  Alert Command = "/etc/bacula/scripts/tapealert %l"
#
#  #
#  # Enable the Alert command only if you have the mtx package loaded
#  Alert Command = "sh -c 'tapeinfo -f %c |grep TapeAlert|cat'"
#  If you have smartctl, enable this, it has more info than tapeinfo
#  Alert Command = "sh -c 'smartctl -H -l error %c'"
#}

#
# A FreeBSD tape drive
#
#Device {
#  Name = DDS-4
#  Description = "DDS-4 for FreeBSD"
#  Media Type = DDS-4
#  Archive Device = /dev/nsa1
#  AutomaticMount = yes;               # when device opened, read it
#  AlwaysOpen = yes
#  Offline On Unmount = no
#  Hardware End of Medium = no
#  BSF at EOM = yes
#  Backward Space Record = no
#  Fast Forward Space File = no
#  TWO EOF = yes
#  #
#  # New alert command in Bacula 9.0.0
#  #  Note: you must have the sg3_utils (rpms) or the
#  #        sg3-utils (deb) installed on your system.
#  #        and you must set the correct control device that
#  #        corresponds to the Archive Device
#  Control Device = /dev/sg??  # must be SCSI ctl for /dev/nsa1
#  Alert Command = "/etc/bacula/scripts/tapealert %l"
#
#  If you have smartctl, enable this, it has more info than tapeinfo
#  Alert Command = "sh -c 'smartctl -H -l error %c'"
#}

#
# Send all messages to the Director,
# mount messages also are sent to the email address
#
Messages {
  Name = Standard
  director = director-dir = all
}
Edited by Brian Candler