summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuilhem Moulin <guilhem@fripost.org>2015-06-03 21:13:10 +0200
committerGuilhem Moulin <guilhem@fripost.org>2015-06-07 02:54:20 +0200
commit00d6d904dc26592553ba93710c205603757e3faf (patch)
tree09ce9d1f3257da4303362317b04a596f4e0df741
parentab03c7c75d91667dbc30f9ce1f66fe343fb9f93b (diff)
Configure Bacula File Daemon / Storage Daemon / Director.
Using client-side data signing/encryption and wrapping inter-host communication into stunnel.
-rw-r--r--all.yml1
-rw-r--r--bacula.yml16
-rw-r--r--common.yml2
-rw-r--r--roles/bacula-dir/files/lib/systemd/system/bacula-director.service14
-rw-r--r--roles/bacula-dir/handlers/main.yml9
-rw-r--r--roles/bacula-dir/tasks/main.yml134
-rw-r--r--roles/bacula-dir/templates/etc/bacula/bacula-dir.conf.j2524
-rw-r--r--roles/bacula-dir/templates/etc/bacula/bconsole.conf.j210
-rw-r--r--roles/bacula-dir/templates/etc/stunnel/bacula-dir.conf.j270
-rw-r--r--roles/bacula-sd/files/lib/systemd/system/bacula-sd.service14
-rw-r--r--roles/bacula-sd/handlers/main.yml9
-rw-r--r--roles/bacula-sd/tasks/main.yml110
-rw-r--r--roles/bacula-sd/templates/etc/bacula/bacula-sd.conf.j256
-rw-r--r--roles/bacula-sd/templates/etc/stunnel/bacula-sd.conf.j253
-rwxr-xr-xroles/common-LDAP/files/usr/local/sbin/slapcat-all.sh18
-rw-r--r--roles/common-LDAP/tasks/main.yml6
-rw-r--r--roles/common/files/lib/systemd/system/bacula-fd.service12
-rw-r--r--roles/common/handlers/main.yml9
-rw-r--r--roles/common/tasks/bacula.yml150
-rw-r--r--roles/common/tasks/main.yml1
-rw-r--r--roles/common/templates/etc/bacula/bacula-fd.conf.j241
-rw-r--r--roles/common/templates/etc/iptables/services.j210
-rw-r--r--roles/common/templates/etc/stunnel/bacula-fd.conf.j262
23 files changed, 1330 insertions, 1 deletions
diff --git a/all.yml b/all.yml
index dbdc327..9bc36cb 100644
--- a/all.yml
+++ b/all.yml
@@ -11,3 +11,4 @@
- include: lists.yml
- include: git.yml
- include: wiki.yml
+- include: bacula.yml
diff --git a/bacula.yml b/bacula.yml
new file mode 100644
index 0000000..3b2eaa9
--- /dev/null
+++ b/bacula.yml
@@ -0,0 +1,16 @@
+---
+- name: Configure the Bacula Director
+ hosts: bacula-dir
+ tags:
+ - bacula
+ - bacula-dir
+ roles:
+ - bacula-dir
+
+- name: Configure the Bacula Storage Daemon
+ hosts: bacula-sd
+ tags:
+ - bacula
+ - bacula-sd
+ roles:
+ - bacula-sd
diff --git a/common.yml b/common.yml
index 3eade06..9593782 100644
--- a/common.yml
+++ b/common.yml
@@ -13,7 +13,7 @@
- common
- name: Common SQL tasks
- hosts: MDA:webmail:lists:backup
+ hosts: MDA:webmail:lists:bacula-dir
gather_facts: False
tags: mysql,sql
roles:
diff --git a/roles/bacula-dir/files/lib/systemd/system/bacula-director.service b/roles/bacula-dir/files/lib/systemd/system/bacula-director.service
new file mode 100644
index 0000000..7b34c8b
--- /dev/null
+++ b/roles/bacula-dir/files/lib/systemd/system/bacula-director.service
@@ -0,0 +1,14 @@
+[Unit]
+Description=Bacula Director service
+After=network.target
+
+[Service]
+Type=forking
+PIDFile=/var/run/bacula/bacula-dir.9101.pid
+StandardOutput=syslog
+User=bacula
+Group=tape
+ExecStart=/usr/sbin/bacula-dir -c /etc/bacula/bacula-dir.conf
+
+[Install]
+WantedBy=multi-user.target
diff --git a/roles/bacula-dir/handlers/main.yml b/roles/bacula-dir/handlers/main.yml
new file mode 100644
index 0000000..175dfb2
--- /dev/null
+++ b/roles/bacula-dir/handlers/main.yml
@@ -0,0 +1,9 @@
+---
+- name: systemctl daemon-reload
+ command: /bin/systemctl daemon-reload
+
+- name: Restart stunnel
+ service: name=stunnel4 pattern=/usr/bin/stunnel4 state=restarted
+
+- name: Restart bacula-director
+ service: name=bacula-director state=restarted
diff --git a/roles/bacula-dir/tasks/main.yml b/roles/bacula-dir/tasks/main.yml
new file mode 100644
index 0000000..7bcf239
--- /dev/null
+++ b/roles/bacula-dir/tasks/main.yml
@@ -0,0 +1,134 @@
+- name: Install stunnel
+ apt: pkg=stunnel4
+
+- name: Auto-enable stunnel
+ lineinfile: dest=/etc/default/stunnel4
+ regexp='^(\s*#)?\s*ENABLED='
+ line='ENABLED=1'
+ owner=root group=root
+ mode=0644
+
+- name: Create /etc/stunnel/certs
+ file: path=/etc/stunnel/certs
+ state=directory
+ owner=root group=root
+ mode=0755
+
+- name: Generate a private key and a X.509 certificate for Bacula Dir
+ command: genkeypair.sh x509
+ --pubkey=/etc/stunnel/certs/{{ inventory_hostname_short }}-dir.pem
+ --privkey=/etc/stunnel/certs/{{ inventory_hostname_short }}-dir.key
+ --ou=BaculaDir --cn={{ inventory_hostname }} --dns={{ inventory_hostname }}
+ -t rsa -b 4096 -h sha512
+ register: r1
+ changed_when: r1.rc == 0
+ failed_when: r1.rc > 1
+ notify:
+ - Restart stunnel
+ tags:
+ - genkey
+
+- name: Fetch Bacula Dir X.509 certificate
+ # Ensure we don't fetch private data
+ sudo: False
+ fetch: src=/etc/stunnel/certs/{{ inventory_hostname_short }}-dir.pem
+ dest=certs/bacula/
+ fail_on_missing=yes
+ flat=yes
+ tags:
+ - genkey
+
+- name: Copy Bacula SD X.509 certificates
+ copy: src=certs/bacula/{{ hostvars[item].inventory_hostname_short }}-sd.pem
+ dest=/etc/stunnel/certs/
+ owner=root group=root
+ mode=0644
+ with_items: groups['bacula-sd'] | difference([inventory_hostname]) | sort
+ register: r2
+ notify:
+ - Restart stunnel
+
+- name: Copy Bacula FD X.509 certificates
+ copy: src=certs/bacula/{{ hostvars[item].inventory_hostname_short }}-fd.pem
+ dest=/etc/stunnel/certs/
+ owner=root group=root
+ mode=0644
+ with_items: groups.all | difference([inventory_hostname]) | sort
+ register: r3
+ notify:
+ - Restart stunnel
+
+- name: Configure stunnel
+ template: src=etc/stunnel/bacula-dir.conf.j2
+ dest=/etc/stunnel/bacula-dir.conf
+ owner=root group=root
+ mode=0644
+ register: r4
+ notify:
+ - Restart stunnel
+
+- name: Start stunnel
+ service: name=stunnel4 pattern=/usr/bin/stunnel4 state=started
+ when: not (r1.changed or r2.changed or r3.changed or r4.changed)
+
+- meta: flush_handlers
+
+
+
+- name: Install bacula-director
+ apt: pkg={{ item }}
+ with_items:
+ - bacula-console
+ - bacula-director-mysql
+
+- name: Create a 'bacula' SQL user
+ mysql_user: name=bacula password= auth_plugin=auth_socket
+ state=present
+ notify:
+ - Restart bacula-director
+
+# Create with:
+# echo bconsole $(pwgen -sn 64 1) | sudo tee -a /etc/bacula/passwords-dir
+# echo $sd-sd $(pwgen -sn 64 1) | sudo tee -a /etc/bacula/passwords-dir
+# echo $fd-fd $(pwgen -sn 64 1) | sudo tee -a /etc/bacula/passwords-dir
+#
+# then add the password for each FD / SD:
+# echo $director-dir $password | sudo tee /etc/bacula/passwords-sd
+# echo $director-dir $password | sudo tee /etc/bacula/passwords-fd
+- name: Ensure /etc/bacula/passwords-dir exists
+ file: path=/etc/bacula/passwords-dir
+ state=file
+ owner=bacula group=bacula
+ mode=0600
+
+- name: Configure bconsole
+ template: src=etc/bacula/bconsole.conf.j2
+ dest=/etc/bacula/bconsole.conf
+ owner=root group=root
+ mode=0644
+
+- name: Configure bacula
+ template: src=etc/bacula/bacula-dir.conf.j2
+ dest=/etc/bacula/bacula-dir.conf
+ owner=root group=root
+ mode=0644
+ register: r
+ notify:
+ - Restart bacula-director
+
+- name: Copy bacula-director.service
+ copy: src=lib/systemd/system/bacula-director.service
+ dest=/lib/systemd/system/bacula-director.service
+ owner=root group=root
+ mode=0644
+ notify:
+ - systemctl daemon-reload
+ - Restart bacula-director
+
+- meta: flush_handlers
+
+- name: Enable bacula-director
+ service: name=bacula-director enabled=yes
+
+- name: Start bacula-director
+ service: name=bacula-director state=started
diff --git a/roles/bacula-dir/templates/etc/bacula/bacula-dir.conf.j2 b/roles/bacula-dir/templates/etc/bacula/bacula-dir.conf.j2
new file mode 100644
index 0000000..70712a6
--- /dev/null
+++ b/roles/bacula-dir/templates/etc/bacula/bacula-dir.conf.j2
@@ -0,0 +1,524 @@
+#
+# Default Bacula Director Configuration file
+# For Bacula release 5.2.6 (21 February 2012) -- debian jessie/sid
+#
+
+Director { # define myself
+ Name = {{ inventory_hostname_short }}-dir
+ @|"sed -n '/^bconsole\\s/ {s//Password = /p; q}' /etc/bacula/passwords-dir"
+ Messages = Daemon
+ Working Directory = /var/lib/bacula
+ Pid Directory = /var/run/bacula
+ QueryFile = "/etc/bacula/scripts/query.sql"
+ Maximum Concurrent Jobs = 1
+ DirAddress = 127.0.0.1
+ DirSourceAddress = 127.0.0.1
+ DirPort = 9101
+}
+
+
+JobDefs {
+ Name = DefaultJob
+ Type = Backup
+ Level = Incremental
+ Storage = {{ hostvars[ groups['bacula-sd'][0] ].inventory_hostname_short }}-sd
+ Messages = Standard
+ Accurate = yes
+ Reschedule On Error = yes
+ Reschedule Interval = 17m
+ Reschedule Times = 3
+ Pool = Default
+ Priority = 10
+ Write Bootstrap = "/var/lib/bacula/%n.bsr"
+}
+
+JobDefs {
+ Name = DefaultMySQLJob
+ Type = Backup
+ Level = Full
+ Storage = {{ hostvars[ groups['bacula-sd'][0] ].inventory_hostname_short }}-sd
+ Messages = Standard
+ FileSet = SQL
+ Schedule = WeeklyCycleAfterBackup
+ Reschedule On Error = yes
+ Reschedule Interval = 17m
+ Reschedule Times = 3
+ # This creates an ASCII copy of the databases
+ Client Run Before Job = "/usr/bin/mysqldump -r /var/lib/bacula/tmp/dump.sql --events --all-databases"
+ # This deletes the copy of the catalog
+ RunScript {
+ Runs On Client = yes
+ Runs On Success = yes
+ Runs On Failure = yes
+ Runs When = after
+ Command = "/bin/rm -f /var/lib/bacula/tmp/dump.sql"
+ }
+ Pool = database
+ Priority = 15
+ Write Bootstrap = "/var/lib/bacula/%n.bsr"
+}
+
+JobDefs {
+ Name = DefaultSlapdJob
+ Type = Backup
+ Level = Full
+ Storage = {{ hostvars[ groups['bacula-sd'][0] ].inventory_hostname_short }}-sd
+ Messages = Standard
+ FileSet = LDAP
+ Schedule = WeeklyCycleAfterBackup
+ Reschedule On Error = yes
+ Reschedule Interval = 17m
+ Reschedule Times = 3
+ # This creates an ASCII copy of the databases
+ Client Run Before Job = "/usr/local/sbin/slapcat-all.sh /var/lib/bacula/tmp"
+ # This deletes the copy of the catalog
+ RunScript {
+ Runs On Client = yes
+ Runs On Success = yes
+ Runs On Failure = yes
+ Runs When = after
+ Command = "/usr/bin/find /var/lib/bacula/tmp -type f -name '*.ldif' -delete"
+ }
+ Pool = database
+ Priority = 15
+ Write Bootstrap = "/var/lib/bacula/%n.bsr"
+}
+
+
+# Backup the director
+Job {
+ Name = {{ inventory_hostname_short }}-dir
+ Client = {{ inventory_hostname_short }}-fd
+ JobDefs = DefaultJob
+ FileSet = BaculaHome
+ Schedule = WeeklyCycle
+}
+
+# Backup the mailboxes
+{% for h in groups.IMAP | sort %}
+Job {
+ Name = {{ hostvars[h].inventory_hostname_short }}-mailboxes
+ Client = {{ hostvars[h].inventory_hostname_short }}-fd
+ JobDefs = DefaultJob
+ FileSet = Mailboxes
+ Pool = mailboxes-inc
+ Full Backup Pool = mailboxes-full
+ Schedule = Mailboxes13WeeksCycle
+ Max Start Delay = 50 min # To avoid too many overlaps
+ Max Full Interval = 15 weeks
+}
+{% endfor %}
+
+# Backup each machine
+{% for fd in groups.all | sort %}
+Job {
+ Name = {{ hostvars[fd].inventory_hostname_short }}
+ Client = {{ hostvars[fd].inventory_hostname_short }}-fd
+ JobDefs = DefaultJob
+ FileSet = FileSetRoot
+ Pool = {{ hostvars[fd].inventory_hostname_short }}
+ Priority = 15
+ Schedule = WeeklyCycle
+}
+{% endfor %}
+
+{% for fd in groups['MDA'] | union(groups['webmail']) | union(groups['lists']) | union(groups['bacula-dir']) | sort %}
+Job {
+ Name = {{ hostvars[fd].inventory_hostname_short }}-mysql
+ Client = {{ hostvars[fd].inventory_hostname_short }}-fd
+ JobDefs = DefaultMySQLJob
+}
+{% endfor %}
+
+{% for fd in groups['MDA'] | union(groups['MSA']) | union(groups['LDAP-provider']) | union(groups['MX']) | sort %}
+Job {
+ Name = {{ hostvars[fd].inventory_hostname_short }}-slapd
+ Client = {{ hostvars[fd].inventory_hostname_short }}-fd
+ JobDefs = DefaultSlapdJob
+}
+{% endfor %}
+
+
+#
+# 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= {{ inventory_hostname_short }}-fd
+ FileSet = FileSetRoot
+ Storage = {{ hostvars[ groups['bacula-sd'][0] ].inventory_hostname_short }}-sd
+ Pool = Default
+ Messages = Standard
+ # NOTE: Files are put on the client (FD) that is being restored.
+ Where = /tmp/bacula-restores
+}
+
+
+# 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
+}
+
+Schedule {
+ Name = Mailboxes13WeeksCycle
+ # Full backup every 3 months
+ Run = Level=Full Pool=mailboxes-full w04 mon at 03:00
+ Run = Level=Full Pool=mailboxes-full w17 mon at 03:00
+ Run = Level=Full Pool=mailboxes-full w30 mon at 03:00
+ Run = Level=Full Pool=mailboxes-full w43 mon at 03:00
+ # Hourly incremental backup otherwise
+ Run = Level=Incremental Pool=mailboxes-inc FullPool=mailboxes-full Messages=Quiet mon-sun at 01:00
+ Run = Level=Incremental Pool=mailboxes-inc FullPool=mailboxes-full Messages=Quiet mon-sun at 02:00
+ Run = Level=Incremental Pool=mailboxes-inc FullPool=mailboxes-full Messages=Quiet w05-w16 mon-sun at 03:00
+ Run = Level=Incremental Pool=mailboxes-inc FullPool=mailboxes-full Messages=Quiet w18-w29 mon-sun at 03:00
+ Run = Level=Incremental Pool=mailboxes-inc FullPool=mailboxes-full Messages=Quiet w31-w42 mon-sun at 03:00
+ Run = Level=Incremental Pool=mailboxes-inc FullPool=mailboxes-full Messages=Quiet w44-w03 mon-sun at 03:00
+ Run = Level=Incremental Pool=mailboxes-inc FullPool=mailboxes-full Messages=Quiet mon-sun at 04:00
+ Run = Level=Incremental Pool=mailboxes-inc FullPool=mailboxes-full Messages=Quiet mon-sun at 05:00
+ Run = Level=Incremental Pool=mailboxes-inc FullPool=mailboxes-full Messages=Quiet mon-sun at 06:00
+ Run = Level=Incremental Pool=mailboxes-inc FullPool=mailboxes-full Messages=Quiet mon-sun at 07:00
+ Run = Level=Incremental Pool=mailboxes-inc FullPool=mailboxes-full Messages=Quiet mon-sun at 08:00
+ Run = Level=Incremental Pool=mailboxes-inc FullPool=mailboxes-full Messages=Quiet mon-sun at 09:00
+ Run = Level=Incremental Pool=mailboxes-inc FullPool=mailboxes-full Messages=Quiet mon-sun at 10:00
+ Run = Level=Incremental Pool=mailboxes-inc FullPool=mailboxes-full Messages=Quiet mon-sun at 11:00
+ Run = Level=Incremental Pool=mailboxes-inc FullPool=mailboxes-full Messages=Quiet mon-sun at 12:00
+ Run = Level=Incremental Pool=mailboxes-inc FullPool=mailboxes-full Messages=Quiet mon-sun at 13:00
+ Run = Level=Incremental Pool=mailboxes-inc FullPool=mailboxes-full Messages=Quiet mon-sun at 14:00
+ Run = Level=Incremental Pool=mailboxes-inc FullPool=mailboxes-full Messages=Quiet mon-sun at 15:00
+ Run = Level=Incremental Pool=mailboxes-inc FullPool=mailboxes-full Messages=Quiet mon-sun at 16:00
+ Run = Level=Incremental Pool=mailboxes-inc FullPool=mailboxes-full Messages=Quiet mon-sun at 17:00
+ Run = Level=Incremental Pool=mailboxes-inc FullPool=mailboxes-full Messages=Quiet mon-sun at 18:00
+ Run = Level=Incremental Pool=mailboxes-inc FullPool=mailboxes-full Messages=Quiet mon-sun at 19:00
+ Run = Level=Incremental Pool=mailboxes-inc FullPool=mailboxes-full Messages=Quiet mon-sun at 20:00
+ Run = Level=Incremental Pool=mailboxes-inc FullPool=mailboxes-full Messages=Quiet mon-sun at 21:00
+ Run = Level=Incremental Pool=mailboxes-inc FullPool=mailboxes-full Messages=Quiet mon-sun at 22:00
+ Run = Level=Incremental Pool=mailboxes-inc FullPool=mailboxes-full Messages=Quiet mon-sun at 23:00
+ Run = Level=Incremental Pool=mailboxes-inc FullPool=mailboxes-full Messages=Quiet mon-sun at 00:00
+}
+
+# This schedule does the databases. It starts after the WeeklyCycle
+Schedule {
+ Name = WeeklyCycleAfterBackup
+ Run = Full sun-sat at 23:10
+}
+
+
+# List of files to be backed up
+FileSet {
+ Name = BaculaHome
+ Include {
+ Options {
+ signature = SHA1
+ compression = GZIP
+ verify = pins1
+ noatime = yes
+ }
+ File = /var/lib/bacula
+ }
+ Exclude {
+ File = /var/lib/bacula/tmp
+ }
+}
+
+FileSet {
+ Name = FileSetRoot
+ Include {
+ # The full /etc/ and /home/, zipped
+ Options {
+ WildDir = "/home/backup*"
+ WildDir = "/home/mail*"
+ WildFile = "*~"
+ WildFile = "*#"
+ Exclude = yes
+ }
+ Options {
+ signature = SHA1
+ compression = GZIP
+ }
+ File = /etc
+ File = /home
+ Exclude Dir Containing = .no-backup
+ }
+ Include {
+ # /var/lib, excluding databases that can be dumped and backed up separately
+ Options {
+ WildDir = /var/lib/amavis
+ WildDir = "/var/lib/apt*"
+ WildDir = /var/lib/aspell
+ WildDir = /var/lib/bacula
+ WildDir = /var/lib/clamav
+ WildDir = "/var/lib/drupal*"
+ WildDir = /var/lib/ldap
+ WildDir = /var/lib/mailman
+ WildDir = /var/lib/mlocate
+ WildDir = /var/lib/munin
+ WildDir = /var/lib/mysql
+ WildDir = /var/lib/postgresql
+ WildDir = /var/lib/postgrey
+ WildDir = /var/lib/rkhunter
+ WildDir = /var/lib/roundcube
+ WildDir = /var/lib/tor
+ WildDir = /var/lib/usbutils
+ WildFile = "*~"
+ WildFile = "*#"
+ Exclude = yes
+ }
+ Options {
+ signature = SHA1
+ compression = GZIP
+ }
+ File = /var/lib
+ Exclude Dir Containing = .no-backup
+ }
+ Include {
+ # Other interesting directories
+ Options {
+ WildDir = /var/cache
+ WildDir = "/var/backup*"
+ WildDir = /var/lib # processed earlier
+ WildDir = /var/spool
+ WildDir = "/var/log*"
+ WildDir = /var/tmp
+ WildFile = "*~"
+ WildFile = "*#"
+ Exclude = yes
+ }
+ Options {
+ signature = SHA1
+ }
+ File = /bin
+ File = /boot
+ File = /lib
+ File = /opt
+ File = /root
+ File = /sbin
+ File = /srv
+ File = /usr
+ File = /var
+ Exclude Dir Containing = .no-backup
+ }
+ Exclude {
+ File = /proc
+ File = /sys
+ File = /run
+ File = /tmp
+ File = /.journal
+ File = /.fsck
+ File = /.autofsck
+ File = /net
+ File = /mnt
+ File = /exports
+ File = /misc
+ File = /media
+ }
+}
+
+FileSet {
+ Name = SQL
+ Include {
+ Options {
+ signature = SHA1
+ compression = GZIP
+ verify = s1
+ }
+ File = /var/lib/bacula/tmp/dump.sql
+ }
+}
+
+FileSet {
+ Name = LDAP
+ Include {
+ Options {
+ signature = SHA1
+ compression = GZIP
+ verify = s1
+ WildFile = "*.ldif"
+ }
+ Options {
+ Wild = "*"
+ Exclude = yes
+ }
+ File = /var/lib/bacula/tmp
+ }
+}
+
+FileSet {
+ Name = Mailboxes
+ Include {
+ Options {
+ signature = SHA1
+ verify = pins1
+ }
+ File = /home/mail/virtual
+ File = /home/mail/spamspool
+ }
+}
+
+
+# Client (File Services) to backup
+{% set n = 0 %}
+{% for fd in groups.all | sort %}
+{% set n = n + 1 %}
+Client {
+ Name = {{ hostvars[fd].inventory_hostname_short }}-fd
+{% if fd == inventory_hostname %}
+ Address = 127.0.0.1
+{% else %}
+ Address = 127.0.{{ n }}.1
+{% endif %}
+ FDPort = 9112
+ Catalog = MyCatalog
+ @|"sed -n '/^{{ hostvars[fd].inventory_hostname_short }}-fd\\s/ {s//Password = /p; q}' /etc/bacula/passwords-dir"
+ File Retention = 4 months
+ Job Retention = 5 months
+ AutoPrune = yes
+ #Maximum Bandwidth = 1mb/s
+}
+{% endfor %}
+
+
+# Definition of file storage device
+Storage {
+ Name = {{ hostvars[ groups['bacula-sd'][0] ].inventory_hostname_short }}-sd
+ Address = 127.0.0.1
+ SDPort = 9113
+ @|"sed -n '/^{{ hostvars[ groups['bacula-sd'][0] ].inventory_hostname_short }}-sd\\s/ {s//Password = /p; q}' /etc/bacula/passwords-dir"
+ Device = FileStorage
+ Media Type = File
+}
+
+
+# Default pool definition
+Pool {
+ Name = Default
+ Pool Type = Backup
+ Recycle = yes
+ AutoPrune = yes
+ Volume Retention = 3 months
+ Maximum Volume Bytes = 5GB
+ Label Format = "Default-${NumVols:p/4/0/r}"
+}
+
+# Scratch pool definition
+Pool {
+ Name = Scratch
+ Pool Type = Backup
+ Maximum Volume Bytes = 5GB
+ Label Format = "Scratch-${NumVols:p/4/0/r}"
+}
+
+# System pools definition
+{% for h in groups.all | sort %}
+Pool {
+ Name = {{ hostvars[h].inventory_hostname_short }}
+ Pool Type = Backup
+ Recycle = yes
+ AutoPrune = yes
+ Volume Retention = 3 months
+ Maximum Volume Bytes = 5GB
+ Label Format = "{{ hostvars[h].inventory_hostname_short }}-${NumVols:p/4/0/r}"
+}
+{% endfor %}
+
+# Mailbox pool definition (full backup)
+Pool {
+ Name = mailboxes-full
+ Pool Type = Backup
+ Recycle = yes
+ AutoPrune = yes
+ Volume Retention = 26 weeks
+ Maximum Volume Bytes = 5GB
+ Label Format = "mailboxes-full-${NumVols:p/4/0/r}"
+}
+
+# Mailbox pool definition (inc backup)
+Pool {
+ Name = mailboxes-inc
+ Pool Type = Backup
+ Recycle = yes
+ AutoPrune = yes
+ Volume Retention = 26 weeks
+ Maximum Volume Bytes = 5GB
+ Label Format = "mailboxes-inc-${NumVols:p/4/0/r}"
+}
+
+# Database pool definition
+Pool {
+ Name = database
+ Pool Type = Backup
+ Recycle = yes
+ AutoPrune = yes
+ Volume Retention = 3 months
+ Maximum Volume Bytes = 5GB
+ Label Format = "database-${NumVols:p/4/0/r}"
+}
+
+
+# Generic catalog service
+Catalog {
+ Name = MyCatalog
+ Password = ""
+ DB Name = bacula
+ User = bacula
+}
+
+
+# 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:16132 -f \"\(Bacula\) \<%r\>\" -s \"Bacula: %t %e of %c %l\" %r"
+ Mail = admin@fripost.org = all, !skipped
+ OperatorCommand = "/usr/sbin/bsmtp -h localhost:16132 -f \"\(Bacula\) \<%r\>\" -s \"Bacula: Intervention needed for %j\" %r"
+ Operator = admin@fripost.org = 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
+}
+
+# Report upon error only
+Messages {
+ Name = Quiet
+ MailCommand = "/usr/sbin/bsmtp -h localhost:16132 -f \"\(Bacula\) \<%r\>\" -s \"Bacula [OK]: %t %e of %n %l\" %r"
+ Mail On Success = admin@fripost.org = all, !info, !fatal, !skipped, !notsaved, !restored
+ MailCommand = "/usr/sbin/bsmtp -h localhost:16132 -f \"\(Bacula\) \<%r\>\" -s \"Bacula [Fail]: %t %e of %n %l\" %r"
+ Mail On Error = admin@fripost.org = all, !skipped
+ OperatorCommand = "/usr/sbin/bsmtp -h localhost:16132 -f \"\(Bacula\) \<%r\>\" -s \"Bacula: Intervention needed for %j\" %r"
+ Operator = admin@fripost.org = mount
+ Console = all, !info, !restored, !skipped, !saved
+ Append = "/var/lib/bacula/log" = all, !skipped
+ Catalog = all
+}
+
+#
+# Message delivery for daemon messages (no job).
+Messages {
+ Name = Daemon
+ MailCommand = "/usr/sbin/bsmtp -h localhost:16132 -f \"\(Bacula\) \<%r\>\" -s \"Bacula daemon message\" %r"
+ Mail = admin@fripost.org = all, !skipped
+ Console = all, !skipped, !saved
+ Append = "/var/log/bacula/bacula.log" = all, !skipped
+}
diff --git a/roles/bacula-dir/templates/etc/bacula/bconsole.conf.j2 b/roles/bacula-dir/templates/etc/bacula/bconsole.conf.j2
new file mode 100644
index 0000000..e7f2726
--- /dev/null
+++ b/roles/bacula-dir/templates/etc/bacula/bconsole.conf.j2
@@ -0,0 +1,10 @@
+#
+# Bacula User Agent (or Console) Configuration File
+#
+
+Director {
+ Name = {{ inventory_hostname_short }}-dir
+ DirPort = 9101
+ Address = 127.0.0.1
+ @|"sed -n '/^bconsole\\s/ {s//Password = /p; q}' /etc/bacula/passwords-dir"
+}
diff --git a/roles/bacula-dir/templates/etc/stunnel/bacula-dir.conf.j2 b/roles/bacula-dir/templates/etc/stunnel/bacula-dir.conf.j2
new file mode 100644
index 0000000..aae49bc
--- /dev/null
+++ b/roles/bacula-dir/templates/etc/stunnel/bacula-dir.conf.j2
@@ -0,0 +1,70 @@
+; **************************************************************************
+; * Global options *
+; **************************************************************************
+
+; setuid()/setgid() to the specified user/group in daemon mode
+setuid = stunnel4
+setgid = stunnel4
+
+; PID is created inside the chroot jail
+pid = /var/run/stunnel4/bacula-dir.pid
+
+; Only log messages at severity warning (4) and higher
+debug = 4
+
+; **************************************************************************
+; * Service defaults may also be specified in individual service sections *
+; **************************************************************************
+
+; Certificate/key is needed in server mode and optional in client mode
+cert = /etc/stunnel/certs/{{ inventory_hostname_short }}-dir.pem
+key = /etc/stunnel/certs/{{ inventory_hostname_short }}-dir.key
+client = yes
+socket = a:SO_BINDTODEVICE=lo
+
+; Some performance tunings
+socket = l:TCP_NODELAY=1
+socket = r:TCP_NODELAY=1
+
+; Prevent MITM attacks
+verify = 4
+
+; Disable support for insecure protocols
+options = NO_SSLv2
+options = NO_SSLv3
+options = NO_TLSv1
+options = NO_TLSv1.1
+
+; These options provide additional security at some performance degradation
+options = SINGLE_ECDH_USE
+options = SINGLE_DH_USE
+
+; Select permitted SSL ciphers
+ciphers = EECDH+AES:EDH+AES:!MEDIUM:!LOW:!EXP:!aNULL:!eNULL:!SSLv2:!SSLv3:!TLSv1:!TLSv1.1
+
+; **************************************************************************
+; * Service definitions (remove all services for inetd mode) *
+; **************************************************************************
+
+{% if 'bacula-sd' not in group_names %}
+[{{ hostvars[ groups['bacula-sd'][0] ].inventory_hostname_short }}-sd]
+accept = 127.0.{{ n }}.1:9113
+connect = {{ groups['bacula-sd'][0] }}:9103
+delay = yes
+CAfile = /etc/stunnel/certs/{{ hostvars[ groups['bacula-sd'][0] ].inventory_hostname_short }}-sd.pem
+{% endif %}
+
+{% set n = 0 %}
+{% for fd in groups.all | sort %}
+{% set n = n + 1 %}
+{% if fd != inventory_hostname %}
+[{{ hostvars[fd].inventory_hostname_short }}-fd]
+accept = 127.0.{{ n }}.1:9112
+connect = {{ fd }}:9102
+delay = yes
+CAfile = /etc/stunnel/certs/{{ hostvars[fd].inventory_hostname_short }}-fd.pem
+{% endif %}
+
+{% endfor %}
+
+; vim:ft=dosini
diff --git a/roles/bacula-sd/files/lib/systemd/system/bacula-sd.service b/roles/bacula-sd/files/lib/systemd/system/bacula-sd.service
new file mode 100644
index 0000000..4c3f81d
--- /dev/null
+++ b/roles/bacula-sd/files/lib/systemd/system/bacula-sd.service
@@ -0,0 +1,14 @@
+[Unit]
+Description=Bacula Storage Daemon service
+After=network.target
+
+[Service]
+Type=forking
+PIDFile=/var/run/bacula/bacula-sd.9113.pid
+StandardOutput=syslog
+User=bacula
+Group=tape
+ExecStart=/usr/sbin/bacula-sd -c /etc/bacula/bacula-sd.conf
+
+[Install]
+WantedBy=multi-user.target
diff --git a/roles/bacula-sd/handlers/main.yml b/roles/bacula-sd/handlers/main.yml
new file mode 100644
index 0000000..ce391d2
--- /dev/null
+++ b/roles/bacula-sd/handlers/main.yml
@@ -0,0 +1,9 @@
+---
+- name: systemctl daemon-reload
+ command: /bin/systemctl daemon-reload
+
+- name: Restart stunnel
+ service: name=stunnel4 pattern=/usr/bin/stunnel4 state=restarted
+
+- name: Restart bacula-sd
+ service: name=bacula-sd state=restarted
diff --git a/roles/bacula-sd/tasks/main.yml b/roles/bacula-sd/tasks/main.yml
new file mode 100644
index 0000000..7a6c8c3
--- /dev/null
+++ b/roles/bacula-sd/tasks/main.yml
@@ -0,0 +1,110 @@
+- name: Install stunnel
+ apt: pkg=stunnel4
+
+- name: Auto-enable stunnel
+ lineinfile: dest=/etc/default/stunnel4
+ regexp='^(\s*#)?\s*ENABLED='
+ line='ENABLED=1'
+ owner=root group=root
+ mode=0644
+
+- name: Create /etc/stunnel/certs
+ file: path=/etc/stunnel/certs
+ state=directory
+ owner=root group=root
+ mode=0755
+
+- name: Generate a private key and a X.509 certificate for Bacula SD
+ command: genkeypair.sh x509
+ --pubkey=/etc/stunnel/certs/{{ inventory_hostname_short }}-sd.pem
+ --privkey=/etc/stunnel/certs/{{ inventory_hostname_short }}-sd.key
+ --ou=BaculaSD --cn={{ inventory_hostname }} --dns={{ inventory_hostname }}
+ -t rsa -b 4096 -h sha512
+ register: r1
+ changed_when: r1.rc == 0
+ failed_when: r1.rc > 1
+ notify:
+ - Restart stunnel
+ tags:
+ - genkey
+
+- name: Fetch Bacula SD X.509 certificate
+ # Ensure we don't fetch private data
+ sudo: False
+ fetch: src=/etc/stunnel/certs/{{ inventory_hostname_short }}-sd.pem
+ dest=certs/bacula/
+ fail_on_missing=yes
+ flat=yes
+ tags:
+ - genkey
+
+- name: Copy Bacula Dir/FD X.509 certificates
+ assemble: src=certs/bacula regexp="-(dir|fd)\.pem$" remote_src=no
+ dest=/etc/stunnel/certs/bacula-dir+fds.pem
+ owner=root group=root
+ mode=0644
+ register: r2
+ notify:
+ - Restart stunnel
+
+- name: Configure stunnel
+ template: src=etc/stunnel/bacula-sd.conf.j2
+ dest=/etc/stunnel/bacula-sd.conf
+ owner=root group=root
+ mode=0644
+ register: r3
+ notify:
+ - Restart stunnel
+
+- name: Start stunnel
+ service: name=stunnel4 pattern=/usr/bin/stunnel4 state=started
+ when: not (r1.changed or r2.changed or r3.changed)
+
+- meta: flush_handlers
+
+
+
+- name: Install bacula-sd
+ apt: pkg=bacula-sd
+
+# Create with:
+# echo $director-dir $(pwgen -sn 64 1) | sudo tee -a /etc/bacula/passwords-sd
+- name: Ensure /etc/bacula/passwords-sd exists
+ file: path=/etc/bacula/passwords-sd
+ state=file
+ owner=bacula group=bacula
+ mode=0600
+
+- name: Configure bacula
+ template: src=etc/bacula/bacula-sd.conf.j2
+ dest=/etc/bacula/bacula-sd.conf
+ owner=root group=root
+ mode=0644
+ notify:
+ - Restart bacula-sd
+
+- name: Copy bacula-sd.service
+ copy: src=lib/systemd/system/bacula-sd.service
+ dest=/lib/systemd/system/bacula-sd.service
+ owner=root group=root
+ mode=0644
+ notify:
+ - systemctl daemon-reload
+ - Restart bacula-sd
+
+- meta: flush_handlers
+
+- name: Enable bacula-sd
+ service: name=bacula-sd enabled=yes
+
+- name: Start bacula-sd
+ service: name=bacula-sd state=started
+
+# To avoid bacula creating archives under /mnt/backup/bacula when it's
+# not a mountpoint, use `chmod 0700 /mnt/backup; chown root:root /mnt/backup`
+# before mounting the disk.
+- name: Create /mnt/backup/bacula
+ file: path=/mnt/backup/bacula
+ state=directory
+ owner=bacula group=tape
+ mode=0750
diff --git a/roles/bacula-sd/templates/etc/bacula/bacula-sd.conf.j2 b/roles/bacula-sd/templates/etc/bacula/bacula-sd.conf.j2
new file mode 100644
index 0000000..7be783b
--- /dev/null
+++ b/roles/bacula-sd/templates/etc/bacula/bacula-sd.conf.j2
@@ -0,0 +1,56 @@
+#
+# Default Bacula Storage Daemon Configuration file
+#
+# For Bacula release 5.2.6 (21 February 2012) -- debian jessie/sid
+#
+# 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.
+#
+
+Storage { # define myself
+ Name = {{ inventory_hostname_short }}-sd
+ Working Directory = /var/lib/bacula
+ Pid Directory = /var/run/bacula
+ Maximum Concurrent Jobs = 20
+ SDAddress = 127.0.0.1
+ SDPort = 9113
+}
+
+#
+# List Directors who are permitted to contact Storage daemon
+#
+{% for dir in groups['bacula-dir'] | sort %}
+Director {
+ Name = {{ hostvars[dir].inventory_hostname_short }}-dir
+ @|"sed -n '/^{{ hostvars[dir].inventory_hostname_short }}-dir\\s/ {s//Password = /p; q}' /etc/bacula/passwords-sd"
+}
+
+#
+# Send all messages to the Director,
+# mount messages also are sent to the email address
+#
+Messages {
+ Name = Standard
+ director = {{ hostvars[dir].inventory_hostname_short }}-dir = all
+}
+{% endfor %}
+
+#
+# Devices supported by this Storage daemon
+# To connect, the Director's bacula-dir.conf must have the
+# same Name and MediaType.
+#
+
+Device {
+ Name = FileStorage
+ Media Type = File
+ Archive Device = /mnt/backup/bacula
+ LabelMedia = yes; # lets Bacula label unlabeled media
+ Random Access = Yes;
+ AutomaticMount = yes; # when device opened, read it
+ RemovableMedia = no;
+ AlwaysOpen = no;
+}
diff --git a/roles/bacula-sd/templates/etc/stunnel/bacula-sd.conf.j2 b/roles/bacula-sd/templates/etc/stunnel/bacula-sd.conf.j2
new file mode 100644
index 0000000..b193826
--- /dev/null
+++ b/roles/bacula-sd/templates/etc/stunnel/bacula-sd.conf.j2
@@ -0,0 +1,53 @@
+; **************************************************************************
+; * Global options *
+; **************************************************************************
+
+; setuid()/setgid() to the specified user/group in daemon mode
+setuid = stunnel4
+setgid = stunnel4
+
+; PID is created inside the chroot jail
+pid = /var/run/stunnel4/bacula-sd.pid
+
+; Only log messages at severity warning (4) and higher
+debug = 4
+
+; **************************************************************************
+; * Service defaults may also be specified in individual service sections *
+; **************************************************************************
+
+; Certificate/key is needed in server mode and optional in client mode
+cert = /etc/stunnel/certs/{{ inventory_hostname_short }}-sd.pem
+key = /etc/stunnel/certs/{{ inventory_hostname_short }}-sd.key
+
+; Some performance tunings
+socket = l:TCP_NODELAY=1
+socket = r:TCP_NODELAY=1
+
+; Prevent MITM attacks
+verify = 4
+
+; Disable support for insecure protocols
+options = NO_SSLv2
+options = NO_SSLv3
+options = NO_TLSv1
+options = NO_TLSv1.1
+
+; These options provide additional security at some performance degradation
+options = SINGLE_ECDH_USE
+options = SINGLE_DH_USE
+
+; Select permitted SSL ciphers
+ciphers = EECDH+AES:EDH+AES:!MEDIUM:!LOW:!EXP:!aNULL:!eNULL:!SSLv2:!SSLv3:!TLSv1:!TLSv1.1
+
+; **************************************************************************
+; * Service definitions (remove all services for inetd mode) *
+; **************************************************************************
+
+[{{ inventory_hostname_short }}-sd]
+client = no
+accept = 9103
+connect = 127.0.0.1:9113
+CAfile = /etc/stunnel/certs/bacula-dir+fds.pem
+
+; vim:ft=dosini
diff --git a/roles/common-LDAP/files/usr/local/sbin/slapcat-all.sh b/roles/common-LDAP/files/usr/local/sbin/slapcat-all.sh
new file mode 100755
index 0000000..4e5b5e4
--- /dev/null
+++ b/roles/common-LDAP/files/usr/local/sbin/slapcat-all.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+# Usage: slapcat-all.sh DIR
+# Save all LDAP databases in DIR: DIR/0.ldif, DIR/1.ldif, ...
+
+set -ue
+PATH=/usr/sbin:/sbin:/usr/bin:/bin
+
+target="$1"
+umask 0077
+
+slapcat -n0 -l"$target/0.ldif"
+n=$(grep -Ec '^dn:\s+olcDatabase={[1-9][0-9]*}' "$target/0.ldif")
+
+while [ $n -gt 0 ]; do
+ slapcat -n$n -l"$target/$n.ldif"
+ n=$(( $n - 1 ))
+done
diff --git a/roles/common-LDAP/tasks/main.yml b/roles/common-LDAP/tasks/main.yml
index aa2f721..2eb0dfb 100644
--- a/roles/common-LDAP/tasks/main.yml
+++ b/roles/common-LDAP/tasks/main.yml
@@ -127,3 +127,9 @@
- name: Remove the rootDN under the 'config' database
openldap: name="olcDatabase={0}config,cn=config" delete=olcRootDN,olcRootPW
+
+- name: Copy /usr/local/sbin/slapcat-all.sh
+ copy: src=usr/local/sbin/slapcat-all.sh
+ dest=/usr/local/sbin/slapcat-all.sh
+ owner=root group=root
+ mode=0755
diff --git a/roles/common/files/lib/systemd/system/bacula-fd.service b/roles/common/files/lib/systemd/system/bacula-fd.service
new file mode 100644
index 0000000..6e2bbd4
--- /dev/null
+++ b/roles/common/files/lib/systemd/system/bacula-fd.service
@@ -0,0 +1,12 @@
+[Unit]
+Description=Bacula File Daemon service
+After=network.target
+
+[Service]
+Type=forking
+PIDFile=/var/run/bacula/bacula-fd.9112.pid
+StandardOutput=syslog
+ExecStart=/usr/sbin/bacula-fd -c /etc/bacula/bacula-fd.conf
+
+[Install]
+WantedBy=multi-user.target
diff --git a/roles/common/handlers/main.yml b/roles/common/handlers/main.yml
index ddfe86b..b7ecaab 100644
--- a/roles/common/handlers/main.yml
+++ b/roles/common/handlers/main.yml
@@ -2,6 +2,9 @@
# corresponding state=restarted handler. (Register the task notifying
# the handler, and add a conditional.)
---
+- name: systemctl daemon-reload
+ command: /bin/systemctl daemon-reload
+
- name: Refresh hostname
service: name=hostname.sh state=restarted
@@ -35,5 +38,11 @@
- name: Reload Postfix
service: name=postfix state=reloaded
+- name: Restart stunnel
+ service: name=stunnel4 pattern=/usr/bin/stunnel4 state=restarted
+
+- name: Restart bacula-fd
+ service: name=bacula-fd state=restarted
+
- name: Update certificate
command: update-ca-certificates
diff --git a/roles/common/tasks/bacula.yml b/roles/common/tasks/bacula.yml
new file mode 100644
index 0000000..248d47d
--- /dev/null
+++ b/roles/common/tasks/bacula.yml
@@ -0,0 +1,150 @@
+- name: Install stunnel
+ apt: pkg=stunnel4
+
+- name: Auto-enable stunnel
+ lineinfile: dest=/etc/default/stunnel4
+ regexp='^(\s*#)?\s*ENABLED='
+ line='ENABLED=1'
+ owner=root group=root
+ mode=0644
+
+- name: Create /etc/stunnel/certs
+ file: path=/etc/stunnel/certs
+ state=directory
+ owner=root group=root
+ mode=0755
+
+- name: Generate a private key and a X.509 certificate for Bacula FD
+ command: genkeypair.sh x509
+ --pubkey=/etc/stunnel/certs/{{ inventory_hostname_short }}-fd.pem
+ --privkey=/etc/stunnel/certs/{{ inventory_hostname_short }}-fd.key
+ --ou=BaculaFD --cn={{ inventory_hostname }} --dns={{ inventory_hostname }}
+ -t rsa -b 4096 -h sha512
+ register: r1
+ changed_when: r1.rc == 0
+ failed_when: r1.rc > 1
+ notify:
+ - Restart stunnel
+ tags:
+ - genkey
+
+- name: Fetch Bacula FD X.509 certificate
+ # Ensure we don't fetch private data
+ sudo: False
+ fetch: src=/etc/stunnel/certs/{{ inventory_hostname_short }}-fd.pem
+ dest=certs/bacula/
+ fail_on_missing=yes
+ flat=yes
+ tags:
+ - genkey
+
+- name: Copy Bacula Dir X.509 certificates
+ assemble: src=certs/bacula regexp="-dir\.pem$" remote_src=no
+ dest=/etc/stunnel/certs/bacula-dirs.pem
+ owner=root group=root
+ mode=0644
+ register: r2
+ when: "'bacula-dir' not in group_names"
+ notify:
+ - Restart stunnel
+
+- name: Copy Bacula SD X.509 certificates
+ copy: src=certs/bacula/{{ hostvars[item].inventory_hostname_short }}-sd.pem
+ dest=/etc/stunnel/certs/
+ owner=root group=root
+ mode=0644
+ register: r3
+ with_items: groups['bacula-sd'] | difference([inventory_hostname])
+ notify:
+ - Restart stunnel
+
+- name: Configure stunnel
+ template: src=etc/stunnel/bacula-fd.conf.j2
+ dest=/etc/stunnel/bacula-fd.conf
+ owner=root group=root
+ mode=0644
+ register: r4
+ when: "'bacula-dir' not in group_names or 'bacula-sd' not in group_names"
+ notify:
+ - Restart stunnel
+
+- name: Start stunnel
+ service: name=stunnel4 pattern=/usr/bin/stunnel4 state=started
+ when: not (r1.changed or r2.changed or r3.changed or r4.changed)
+
+- meta: flush_handlers
+
+
+
+- name: Install bacula-fd
+ apt: pkg=bacula-fd
+
+- name: Create /var/lib/bacula/tmp
+ file: path=/var/lib/bacula/tmp
+ state=directory
+ owner=root group=root
+ mode=0700
+
+- name: Delete /etc/bacula/common_default_passwords
+ file: path=/etc/bacula/common_default_passwords state=absent
+
+# Create with:
+# echo $director-dir $(pwgen -sn 64 1) | sudo tee -a /etc/bacula/passwords-fd
+- name: Ensure /etc/bacula/passwords-fd exists
+ file: path=/etc/bacula/passwords-fd
+ state=file
+ owner=root group=root
+ mode=0600
+
+- name: Configure bacula
+ template: src=etc/bacula/bacula-fd.conf.j2
+ dest=/etc/bacula/bacula-fd.conf
+ owner=root group=root
+ mode=0644
+ notify:
+ - Restart bacula-fd
+
+- name: Create /etc/bacula/ssl
+ file: path=/etc/bacula/ssl
+ state=directory
+ owner=root group=root
+ mode=0755
+
+- name: Generate a keypair for data encryption
+ command: genkeypair.sh x509
+ --pubkey=/etc/bacula/ssl/{{ inventory_hostname_short }}.pem
+ --privkey=/etc/bacula/ssl/{{ inventory_hostname_short }}.pem
+ --ou=BaculaFD --cn={{ inventory_hostname }} --dns={{ inventory_hostname }}
+ -t rsa -b 4096 -h sha512
+ register: r
+ changed_when: r.rc == 0
+ failed_when: r.rc > 1
+ notify:
+ - Restart bacula-fd
+ tags:
+ - genkey
+
+- name: Copy the master public key for data encryption
+ copy: src=certs/bacula/data-master.pem
+ dest=/etc/bacula/ssl/master.pem
+ owner=root group=root
+ mode=0644
+ tags:
+ - genkey
+
+- name: Copy bacula-fd.service
+ copy: src=lib/systemd/system/bacula-fd.service
+ dest=/lib/systemd/system/bacula-fd.service
+ owner=root group=root
+ mode=0644
+ notify:
+ - systemctl daemon-reload
+ - Restart bacula-fd
+
+- meta: flush_handlers
+
+- name: Enable bacula-fd
+ service: name=bacula-fd enabled=yes
+
+- name: Start bacula-fd
+ service: name=bacula-fd state=started
diff --git a/roles/common/tasks/main.yml b/roles/common/tasks/main.yml
index 8f28b93..477bd34 100644
--- a/roles/common/tasks/main.yml
+++ b/roles/common/tasks/main.yml
@@ -30,6 +30,7 @@
- include: logging.yml tags=logging
- include: ntp.yml tags=ntp
- include: mail.yml tags=mail,postfix
+- include: bacula.yml tags=bacula-fd,bacula
- name: Install common packages
apt: pkg={{ item }}
diff --git a/roles/common/templates/etc/bacula/bacula-fd.conf.j2 b/roles/common/templates/etc/bacula/bacula-fd.conf.j2
new file mode 100644
index 0000000..a47bb90
--- /dev/null
+++ b/roles/common/templates/etc/bacula/bacula-fd.conf.j2
@@ -0,0 +1,41 @@
+#
+# Default Bacula File Daemon Configuration file
+#
+# For Bacula release 5.2.6 (21 February 2012) -- debian jessie/sid
+
+#
+# List Directors who are permitted to contact this File daemon
+#
+{% for dir in groups['bacula-dir'] | sort %}
+Director {
+ Name = {{ hostvars[dir].inventory_hostname_short }}-dir
+ @|"sed -n '/^{{ hostvars[dir].inventory_hostname_short }}-dir\\s/ {s//Password = /p; q}' /etc/bacula/passwords-fd"
+}
+
+# Send all messages except skipped files back to Director
+Messages {
+ Name = Standard
+ director = {{ hostvars[dir].inventory_hostname_short }}-dir = all, !skipped, !restored
+}
+{% endfor %}
+
+#
+# "Global" File daemon configuration specifications
+#
+FileDaemon { # define myself
+ Name = {{ inventory_hostname_short }}-fd
+ Working Directory = /var/lib/bacula
+ Pid Directory = /var/run/bacula
+ Maximum Concurrent Jobs = 20
+ FDAddress = 127.0.0.1
+ FDPort = 9112
+ FDSourceAddress = 127.0.0.1
+{% if 'bacula-dir' not in group_names or 'bacula-sd' not in group_names %}
+ Heartbeat Interval = 60s
+{% endif %}
+
+ PKI Signatures = Yes # Enable Data Signing
+ PKI Encryption = Yes # Enable Data Encryption
+ PKI Keypair = /etc/bacula/ssl/{{ inventory_hostname_short }}.pem # Public and Private Keys
+ PKI Master Key = /etc/bacula/ssl/master.pem # ONLY the Public Key
+}
diff --git a/roles/common/templates/etc/iptables/services.j2 b/roles/common/templates/etc/iptables/services.j2
index 187e588..a0bb714 100644
--- a/roles/common/templates/etc/iptables/services.j2
+++ b/roles/common/templates/etc/iptables/services.j2
@@ -59,6 +59,16 @@ in tcp 80,443 # HTTP/HTTPS
out tcp 993 # IMAP
out tcp 4190 # MANAGESIEVE
{% endif %}
+{% if 'bacula-dir' in group_names and groups.all | difference(groups['bacula-dir']) %}
+out tcp 9102 # BACULA-FD
+{% elif groups['bacula-dir'] | difference([inventory_hostname]) %}
+in tcp 9102 # BACULA-FD
+{% endif %}
+{% if 'bacula-sd' in group_names and groups.all | difference(groups['bacula-sd']) %}
+in tcp 9103 # BACULA-SD
+{% elif groups['bacula-sd'] | difference([inventory_hostname]) %}
+out tcp 9103 # BACULA-SD
+{% endif %}
{% if 'LDAP-provider' in group_names %}
out tcp 11371 # HKP
diff --git a/roles/common/templates/etc/stunnel/bacula-fd.conf.j2 b/roles/common/templates/etc/stunnel/bacula-fd.conf.j2
new file mode 100644
index 0000000..74364c9
--- /dev/null
+++ b/roles/common/templates/etc/stunnel/bacula-fd.conf.j2
@@ -0,0 +1,62 @@
+; **************************************************************************
+; * Global options *
+; **************************************************************************
+
+; setuid()/setgid() to the specified user/group in daemon mode
+setuid = stunnel4
+setgid = stunnel4
+
+; PID is created inside the chroot jail
+pid = /var/run/stunnel4/bacula-fd.pid
+
+; Only log messages at severity warning (4) and higher
+debug = 4
+
+; **************************************************************************
+; * Service defaults may also be specified in individual service sections *
+; **************************************************************************
+
+; Certificate/key is needed in server mode and optional in client mode
+cert = /etc/stunnel/certs/{{ inventory_hostname_short }}-fd.pem
+key = /etc/stunnel/certs/{{ inventory_hostname_short }}-fd.key
+
+; Some performance tunings
+socket = l:TCP_NODELAY=1
+socket = r:TCP_NODELAY=1
+
+; Prevent MITM attacks
+verify = 4
+
+; Disable support for insecure protocols
+options = NO_SSLv2
+options = NO_SSLv3
+options = NO_TLSv1
+options = NO_TLSv1.1
+
+; These options provide additional security at some performance degradation
+options = SINGLE_ECDH_USE
+options = SINGLE_DH_USE
+
+; Select permitted SSL ciphers
+ciphers = EECDH+AES:EDH+AES:!MEDIUM:!LOW:!EXP:!aNULL:!eNULL:!SSLv2:!SSLv3:!TLSv1:!TLSv1.1
+
+; **************************************************************************
+; * Service definitions (remove all services for inetd mode) *
+; **************************************************************************
+
+[{{ inventory_hostname_short }}-fd]
+client = no
+accept = 9102
+connect = 9112
+CAfile = /etc/stunnel/certs/bacula-dirs.pem
+
+{% if 'bacula-sd' not in group_names %}
+[{{ hostvars[ groups['bacula-sd'][0] ].inventory_hostname_short }}-sd]
+client = yes
+accept = 127.0.0.1:9113
+connect = {{ groups['bacula-sd'][0] }}:9103
+delay = yes
+CAfile = /etc/stunnel/certs/{{ hostvars[ groups['bacula-sd'][0] ].inventory_hostname_short }}-sd.pem
+{% endif %}
+
+; vim:ft=dosini