This page looks best with JavaScript enabled

Backups with Bacula

 ·  🎃 kr0m

Bacula is a free, scalable, and highly configurable remote backup system. Its greatest strengths are the definition of different backup policies, execution of pre/post backup scripts, data encryption, and data compression.

In Bacula, there are several elements:

  • Director: It is responsible for coordinating the operations performed by the sysadmin.
  • Catalog: Database where the files to be backed up, the date on which the backup was performed, and information about the backups are stored.
  • File daemon/client: The part that runs on the servers, this client will send the data to the Storage server.
  • Bconsole: Interface to interact with the Director.
  • Jobs: Scheduled jobs.
  • Storage: Servers responsible for storing the information itself.
  • Pool: Grouping of volumes to apply common configuration parameters.
  • Volume: Storage unit, a disk, tape, etc.
  • Label: Reusable storage chunk of a volume (configured in the director), as the backup retention is met, these chunks are released and reused.

In the client config, the Storage-server and the Pool are specified, so it is stored on a specific server with specific options.

All services are paired, meaning that the configuration will be done at both ends:

  • Director config -> Director config on the client.
  • Director config-Storages -> Storage config on the Storage server.
  • Director config-File -> File config on the client.

INSTALLATION:

We install MySQL:

vi /etc/portage/package.use/mysql

dev-db/mysql latin1 -ssl
emerge -av dev-db/mysql
emerge --config =dev-db/mysql-5.6.26
/etc/init.d/mysql start
mysql_secure_installation
rc-update add mysql default

We install Bacula:

vi /etc/portage/package.use/bacula

app-backup/bacula -X acl -bacula-clientonly -bacula-nodir -bacula-nosd examples -ipv6 logwatch mysql -postgres python -qt4 readline -sqlite ssl -static tcpd vim-syntax
emerge -av app-backup/bacula
/usr/libexec/bacula/create_mysql_database -uroot -p
mysql -uroot -p
mysql> use mysql
mysql> grant all privileges on bacula.* to bacula@localhost identified by 'bacula_pass';
mysql> flush privileges;
mysql> exit
/usr/libexec/bacula/make_mysql_tables -ubacula -p’bacula_pass'
/usr/libexec/bacula/grant_mysql_privileges -uroot -p$(</root/.myp)

DIRECTOR CONFIGURATION:

cp /etc/bacula/bacula-dir.conf /etc/bacula/bacula-dir.conf.ori
vi /etc/bacula/bacula-dir.conf

# Configuracion del director
Director { # define myself
 Name = ovh-bacula00-dir
 DIRport = 9101 # where we listen for UA connections
 QueryFile = "/usr/libexec/bacula/query.sql"
 WorkingDirectory = "/var/lib/bacula"
 PidDirectory = "/var/run"
 Maximum Concurrent Jobs = 20
 Password = "director_pass" # Console password
 Messages = ovh-bacula00_messages
}

# Configuramos la bconsole:
Console {
 Name = ovh-bacula00-mon
 Password = "console_pass"
 CommandACL = status, .status
}

Messages {
 Name = "ovh-bacula00_messages"
 Console = all, !skipped, !saved
 Append = "/var/log/bacula/ovh-bacula00_director.log" = all, !skipped
 Catalog = all
}

# Configuramos el job para poder restaurar backups desde el propio server de bacula
Job {
 Name = "Restore"
 Client = "ovh-bacula00"
 Type = Restore
 FileSet = Catalog
 Storage = "StorageServer00"
 Pool = "StorageServer00"
 Messages = "ovh-bacula00_messages"
 Where = "/tmp"
}

# Definimos una politica de backups:
# Full -> Domingos a las 00:05
# Incremental -> Lunes-Sabado a la 01:00
Schedule {
 Name = "WeeklyCycle"
 Run = Level=Full First Sun at 00:05
 Run = Level=Incremental Mon-Sat at 01:00
}

# Configuracion del catalogo(base de datos con los jobs):
Catalog {
 Name = ovh-bacula00_catalog
 dbname = "bacula"; dbuser = "bacula"; dbpassword = "bacula_pass"
}

# Definimos los Storage-Servers a los que accedera el director:
Storage {
 Name = StorageServer00
# Do not use "localhost" here
 Address = IP_STORAGE_SERVER # N.B. Use a fully qualified name here
 SDPort = 9103
 Password = "storageserver00_pass" # Authentication password against StorageServer
 Device = FileStorage00 # Device to use in StorageServer
 Media Type = StorageVolume
 Maximum Concurrent Jobs = 10 # run up to 10 jobs a the same time
}

# Config de los pools:
Pool {
 Name = "StorageServer00"
 Label Format = "StorageServer00.${Year}-${Month:p/2/0/r}-${Day:p/2/0/r}_${Hour:p/2/0/r}:${Minute:p/2/0/r}"
 Pool Type = Backup
 Recycle = Yes
 Auto Prune = Yes
 Volume Retention = 6 Month
 Volume Use Duration = 1 Week
 Maximum Volume Bytes = 900G
 Maximum Volumes = 24
}

FileSet {
 Name = "Catalog"
 Include {
 Options {
 Signature = SHA1
 Compression = GZIP
 }
 File = "/var/lib/bacula/backup/bacula.sql"
 }
}

# Incluimos todos los ficheros de clientes localizados en /etc/bacula/client.d:
@|"find /etc/bacula/client.d -name '*.conf' -type f -exec echo @{} ;"
mkdir /var/log/bacula/

STORAGE-SERVER CONFIGURATION:

cp /etc/bacula/bacula-sd.conf /etc/bacula/bacula-sd.conf.ori
vi /etc/bacula/bacula-sd.conf

# Config del StorageServer
Storage { # definition of myself
 Name = StorageServer00
 SDPort = 9103 # Director's port
 WorkingDirectory = "/var/lib/bacula"
 Pid Directory = "/var/run"
 Maximum Concurrent Jobs = 20
}

# Indicamos desde que Director debe obedecer ordenes:
Director {
 Name = ovh-bacula00-dir
 Password = "storageserver00_pass"
}

# Definimos donde guardar los backups:
Device {
 Name = FileStorage00
 Media Type = StorageVolume
 Archive Device = /var/backups
 LabelMedia = yes; # lets Bacula label unlabeled media
 Random Access = Yes;
 AutomaticMount = yes; # when device opened, read it
 RemovableMedia = no;
 AlwaysOpen = yes;
 Maximum Concurrent Jobs = 5;
 Requires Mount = no
}
mkdir -p /var/backups
vi /etc/init.d/bacula-dir
#!/sbin/runscript
# Copyright 1999-2011 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Id$

depend() {
 need net
 if [ "${LOCAL_DB}" -eq 1 ]; then
 need mysql
 fi
 use dns bacula-fd bacula-sd
}

start() {
 ebegin "Starting bacula director"
 start-stop-daemon --start --quiet --exec /usr/sbin/bacula-dir 
 -- ${DIR_OPTIONS}
 eend $?
}

stop() {
 ebegin "Stopping bacula director"
 start-stop-daemon --stop --quiet --pidfile /var/run/bacula-dir.*.pid
 eend $?
}

GENERATE CONFIGURATION FOR CLIENTS:

mkdir -p /etc/bacula/client.d/
vi /etc/bacula/client.d/ovh-bacula00.conf

# Config del cliente
Client {
 Name = ovh-bacula00
 Address = IP_BACULADIR
 FDPort = 9102
 Catalog = ovh-bacula00_catalog
 Password = "ovh-bacula00_pass"
 File Retention = 6 months
 Job Retention = 6 months
 AutoPrune = yes
}

# Config del Job
Job {
Name = "ovh-bacula00"
Type = Backup
Priority = 10
Client = ovh-bacula00
FileSet = "ovh-bacula00"
Schedule = "WeeklyCycle"
Messages = ovh-bacula00_messages
Pool = StorageServer00
Storage = StorageServer00
Write Bootstrap = "/var/lib/bacula/%n.bsr"
}

# Directorios a backupear
FileSet {
 Name = "ovh-bacula00"

 Include {
 Options {
 signature = MD5
 compression = GZIP6
 onefs = No
 }
 File = "/etc"
 File = "/root"
 }
}
vi /etc/bacula/client.d/Cliente00.conf
# Config del cliente
Client {
 Name = Cliente00
 Address = IP_CLIENTE00
 FDPort = 9102
 Catalog = ovh-bacula00_catalog
 Password = "Cliente00_pass"
 File Retention = 6 months
 Job Retention = 6 months
 AutoPrune = yes
}

# Config del Job
Job {
Name = "Cliente00"
Type = Backup
Priority = 10
Client = Cliente00
FileSet = "Cliente00"
Schedule = "WeeklyCycle"
Messages = ovh-bacula00_messages
Pool = StorageServer00
Storage = StorageServer00
Write Bootstrap = "/var/lib/bacula/%n.bsr"
}

# Directorios a backupear
FileSet {
 Name = "Cliente00"

 Include {
 Options {
 signature = MD5
 compression = GZIP6
 onefs = No
 }
 File = "/etc"
 File = "/root"
 }
}

We start the services and add them to the startup:

/etc/init.d/bacula-sd start
/etc/init.d/bacula-dir start
/etc/init.d/bacula-fd start

rc-update add bacula-sd default
rc-update add bacula-dir default
rc-update add bacula-fd default

CLIENT CONFIGURATION:
We compile Bacula on all clients with the bacula-clientonly use-flag.

vi /etc/portage/package.use/bacula

app-backup/bacula bacula-clientonly
emerge -av app-backup/bacula

We configure the Bacula FileDaemon on the client:

cp /etc/bacula/bacula-fd.conf /etc/bacula/bacula-fd.conf.ori
vi /etc/bacula/bacula-fd.conf

Director {
 Name = ovh-bacula00-dir
 Password = "Cliente00_pass"
}

FileDaemon {
 Name = Cliente00-fd
 FDport = 9102
 FDAddress = IP_CLIENTE00
 WorkingDirectory = /var/lib/bacula
 Pid Directory = /var/run
 Maximum Concurrent Jobs = 20
}

Messages {
 Name = Standard
 director = atila-dir = all, !skipped, !restored
}

We configure the bconsole on the client:

cp /etc/bacula/bconsole.conf /etc/bacula/bconsole.conf.ori
vi /etc/bacula/bconsole.conf

# Config de acceso a la consola del propio cliente:
Director {
 Name = Cliente00-dir
 DIRport = 9101
 address = IP_CLIENTE00
 Password = "client00bconsole_pass"
}
/etc/init.d/bacula-fd start
rc-update add bacula-fd default

Now, Bacula itself:

cp /etc/bacula/bacula-fd.conf /etc/bacula/bacula-fd.conf.ori
vi /etc/bacula/bacula-fd.conf

Director {
 Name = ovh-bacula00-dir
 Password = "ovh-bacula00_pass"
}

FileDaemon {
 Name = ovh-bacula00-fd
 FDport = 9102
 FDAddress = IP_BACULADIR
 WorkingDirectory = /var/lib/bacula
 Pid Directory = /var/run
 Maximum Concurrent Jobs = 20
}

Messages {
 Name = Standard
 director = atila-dir = all, !skipped, !restored
}
/etc/init.d/bacula-fd start
rc-update add bacula-fd default

BAT: Bacula Administration Tool:
We compile BAT, the graphical administration tool for Bacula. We could also choose to use bconsole, but I find the graphical interface much more intuitive ;)

vi /etc/portage/package.use/bacula

app-backup/bacula bacula-clientonly X acl qt4 readline sqlite ssl tcpd
emerge -av app-backup/bacula
vi /etc/bacula/bat.conf
#
# Bacula User Agent (or Console) Configuration File
#

Director {
 Name = ovh-bacula00.net-dir
 DIRport = 9101
 address = IP_BACULADIR
 Password = "director_pass"
}

DATA ENCRYPTION:
Bacula allows us to encrypt data on the client, so it travels directly over the network protected (no tunnel is required).
Encryption works through PKI, the client encrypts with its private key and can only be decrypted with this or with the bacula-dir master key.

To confirm the identity of Bacula, a self-signed certificate is used, the pubkey is passed to the clients, and voila, we have encrypted data and are sure that we are sending it to the correct server.

We generate the certificate in the bacula-dir (FQDN-Cert: hostname -f) and pass it to the clients:

cd /etc/ssl
openssl genrsa -out master.key 2048
openssl req -new -key master.key -x509 -out master.cert -days 3650
scp /etc/ssl/master.cert root@Cliente00:/etc/ssl/

We generate the key pair on the client and combine them (FQDN-Cert: hostname -f):

cd /etc/ssl
openssl genrsa -out fd-Cliente00.key 2048
openssl req -new -key fd-Cliente00.key -x509 -out fd-Cliente00.cert -days 3650
cat fd-Cliente00.key fd-Cliente00.cert > fd-Cliente00.pem
vi /etc/bacula/bacula-fd.conf

Director {
 Name = ovh-bacula00-dir
 Password = "Cliente00_pass"
}

FileDaemon {
 Name = Cliente00-fd
 FDport = 9102
 FDAddress = IP_CLIENTE00
 WorkingDirectory = /var/lib/bacula
 Pid Directory = /var/run
 Maximum Concurrent Jobs = 20
 # Data Encryption
 PKI Signatures = Yes # Enable Data Signing
 PKI Encryption = Yes # Enable Data Encryption
 PKI Keypair = "/etc/ssl/fd-Cliente00.pem" # Public and Private Keys
 PKI Master Key = "/etc/ssl/master.cert" # ONLY the Public Key
}

Messages {
 Name = Standard
 director = atila-dir = all, !skipped, !restored
}
/etc/init.d/bacula-fd restart

If we execute the job, we can see in the logs:

Encryption: yes

DATA RESTORATION:
The easiest way to restore backups is through BAT. In the BRestore section, we select the client in question, the backup date to restore, the files, and click on restore.

If the server from which the backup was taken is completely crashed, we will have to restore the data on another server. If we do not modify the Bacula-FileDaemon configuration when restoring on a server WITHOUT the corresponding private key, the following message will appear:

Error: Missing private key required to decrypt encrypted backup data.

To be able to restore, we generate the “superkey” in the Bacula director. This is valid for any backup from any server:

cd /etc/ssl
cat master.cert master.key > superkey.pem
scp superkey.pem root@IP_CLIENTE01:/etc/ssl/

On the server where we want to restore:

vi /etc/bacula/bacula-fd.conf

Director {
 Name = ovh-bacula00-dir
 Password = "Cliente01_pass"
}

FileDaemon {
 Name = Cliente01-fd
 FDport = 9102
 FDAddress = IP_CLIENTE01
 WorkingDirectory = /var/lib/bacula
 Pid Directory = /var/run
 Maximum Concurrent Jobs = 20
 # Data Encryption
 PKI Signatures = Yes # Enable Data Signing
 PKI Encryption = Yes # Enable Data Encryption
 #PKI Keypair = "/etc/ssl/fd-Cliente01.pem" # Public and Private Keys
 PKI Keypair = "/etc/ssl/superkey.pem" # Public and Private Keys
 PKI Master Key = "/etc/ssl/master.cert" # ONLY the Public Key
}

Messages {
 Name = Standard
 director = atila-dir = all, !skipped, !restored
}
/etc/init.d/bacula-fd restart

With this, we already have the basic Bacula usage procedure. I hope you find it useful.

If you liked the article, you can treat me to a RedBull here