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:
dev-db/mysql latin1 -ssl
emerge --config =dev-db/mysql-5.6.26
/etc/init.d/mysql start
mysql_secure_installation
rc-update add mysql default
We install 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
/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/grant_mysql_privileges -uroot -p$(</root/.myp)
DIRECTOR CONFIGURATION:
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 @{} ;"
STORAGE-SERVER CONFIGURATION:
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
}
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:
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"
}
}
# 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-dir start
/etc/init.d/bacula-fd start
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.
app-backup/bacula bacula-clientonly
We configure the Bacula FileDaemon on the client:
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:
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"
}
rc-update add bacula-fd default
Now, Bacula itself:
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
}
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 ;)
app-backup/bacula bacula-clientonly X acl qt4 readline sqlite ssl tcpd
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:
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):
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
}
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:
cat master.cert master.key > superkey.pem
scp superkey.pem root@IP_CLIENTE01:/etc/ssl/
On the server where we want to restore:
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
}
With this, we already have the basic Bacula usage procedure. I hope you find it useful.