Bacularis is a fully loaded Bacula CE suite that comes with a successor of highly popular Baculum GUI. It can be installed by a one-liner Docker command thereby short-cutting hours of tedious installation steps like the ones I described in one of my previous posts.
1 Creating the container
1.1 with docker run
By default, the docker container mounts six volumes that it labels with non-intuitive random alphanumeric uuids. To get meaningful volumes that we can later identify on the host machine, we add a set of --mount options so that volumes are not created with anonymous uuid labels.
Furthermore, we open not only the Bacularis port 9097 but also ports 9101-9103 which are needed for communication between the director, the file daemons and the storage daemons.
ilek@q556:~$ docker run -d -p 9097:9097 -p 9101-9103:9101-9103 \
--name bacuprod \
--mount source=bacuprod_etc,destination=/etc/bacula \
--mount source=bacuprod_archive,destination=/var/lib/bacula \
--mount source=bacuprod_postgre,destination=/var/lib/postgresql/data \
--mount source=bacuprod_api_conf,destination=/var/www/bacularis/protected/vendor/bacularis/bacularis-api/API/Config \
--mount source=bacuprod_api_log,destination=/var/www/bacularis/protected/vendor/bacularis/bacularis-api/API/Logs \
--mount source=bacuprod_web_conf,destination=/var/www/bacularis/protected/vendor/bacularis/bacularis-web/Web/Config \
--mount source=bacuprod_web_log,destination=/var/www/bacularis/protected/vendor/bacularis/bacularis-web/Web/Logs \
bacularis/bacularis-standalone
1.2 with docker compose
From my experience, it is more convenient to keep the container configuration in a docker-compose.yml file: The complete configuration is stored readily available on disk, so there is no need to look it up. Besides having to enter multi-line commands with dozens of parameters at the console is cumbersome and prone to syntax errors.
- Save the
docker-compose.ymlfile below in a directory like~/docker/bacuprod - Launch by issuing the command
docker compose up --detachfrom the directory - Stop by issuing the command
docker compose down
Failure to provide the hostname will result in slow DNS resolution, timeouts, and connection aborts both at the level of the bacularis web interface and bconsole level (even if executed from inside the container).
name: bacuprod
services:
bacuprod:
image: 'bacularis/bacularis-standalone:2.1.0-alpine'
container_name: 'bacuprod'
hostname: 'q556.fritz.box'
ports:
- '9097:9097'
- '9101:9101'
- '9102:9102'
- '9103:9103'
volumes:
- etc:/etc/bacula
- archive:/var/lib/bacula
- postgre:/var/lib/postgresql/data
- api_conf:/var/www/bacularis/protected/vendor/bacularis/bacularis-api/API/Config
- api_log:/var/www/bacularis/protected/vendor/bacularis/bacularis-api/API/Logs
- web_conf:/var/www/bacularis/protected/vendor/bacularis/bacularis-web/Web/Config
- web_log:/var/www/bacularis/protected/vendor/bacularis/bacularis-web/Web/Logs
volumes:
etc:
archive:
postgre:
api_conf:
api_log:
web_conf:
web_log:
2 Set meaningful daemon names
The default name of the director is simply the host name of the docker container’s Alpine Linux OS plus an appended -dir. So you get unintuitive names like build-3-16-x86_64-dir. To better identify the machine, …
… stop the Bacularis container, as sudo change to the host machine’s local bacula_etc volume (the path may differ on your machine, depending on the docker installation it might be /var/lib/docker/volumes while in my case it’s ~/.local/share/docker/volumes).
ilek@q556:~/bacuprod$ docker stop bacuprod
bacuprod
ilek@q556:~/bacuprod$ sudo su
[sudo] password for ilek:
root@q556:/home/ilek/bacuprod# cd /home/ilek/.local/share/docker/volumes/bacuprod_etc/_data
root@q556:/home/ilek/.local/share/docker/volumes/bacuprod_etc/_data# ls
bacula-dir.conf bacula-fd.conf bacula-sd.conf bconsole.conf scripts
root@q556:/home/ilek/.local/share/docker/volumes/bacuprod_etc/_data# vim bacula-dir.conf
First thing we have to edit is the bconsole.conf file. Replace Name and address directives as follows:
Director {
Name = q556_d-dir
DIRport = 9101
address = q556 # was localhost
Save and continue editing bacula-dir.conf as follows:
%s/build-3-16-x86_64-dir/q556_d-dir/gc (c option will have each substitution confirmed)Director { # define myself
Name = q556_d-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 = "yRtfeKlgyBI7lXuDRXJJ3XuE718Nz/M7cg2zeuSgUNuy" # Console password
Messages = Daemon
}
In the same file, we can already change the name of the local client (file daemon) in the JobDef Resource:
%s/build-3-16-x86_64-fd/q556_d-fd/gc which will also replace all of the three -fd occurences below in one shot.JobDefs {
Name = "DefaultJob"
Type = Backup
Level = Incremental
Client = q556_d-fd
FileSet = "Full Set"
Schedule = "WeeklyCycle"
Storage = File1
Messages = Standard
Pool = File
SpoolAttributes = yes
Priority = 10
Write Bootstrap = "/var/lib/bacula/%c.bsr"
}
Still in bacula-dir.conf we change the client name in the Job Resource for the Restore operation:
Job {
Name = "RestoreFiles"
Type = Restore
Client = q556_d-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 = /var/lib/bacula/archive/bacula-restores
}
And, still in bacula-dir.conf we change the client name in the Client Ressource:
# Client (File Services) to backup
Client {
Name = q556_d-fd
Address = localhost
FDPort = 9102
Catalog = MyCatalog
Password = "9jTOS+av7cVucWfwyVKSxKVFWF45xgArseso98h6EBO1" # password for FileDaemon
File Retention = 60 days # 60 days
Job Retention = 6 months # six months
AutoPrune = yes # Prune expired Jobs/Files
}For the sake of house-keeping, we also amend the Name directive of the Console resource in bacula-conf.dir:
Console {
Name = q556_d-mon
Password = "W2lr7PKwCsd2WRAXN8/rAGFXMGB6XplIyMXlamqfYwaU"
CommandACL = status, .status
}
Don’t forget that director name also needs to be set for any daemon which the director should talk to. In our default installation, this should be the local file daemon and the storage daemon.
Save the changes in bacula-dir.conf and continue with editing bacula-fd.conf:
%s/build-3-16-x86_64/q556_d/gcDirector {
Name = q556_d-dir
Password = "9jTOS+av7cVucWfwyVKSxKVFWF45xgArseso98h6EBO1"
}
[...]
Director {
Name = q556_d-mon
Password = "G+UhGCVuxrajBJAU0yyIDFY+KiUBlA/9n2u/qfJq84NW"
Monitor = yes
}
[...]
# Send all messages except skipped files back to Director
Messages {
Name = Standard
director = q556_d-dir = all, !skipped, !restored, !saved
}
Save and continue with editing bacula-sd.conf:
%s/build-3-16-x86_64/q556_d/gcStorage { # definition of myself
Name = q556_d-sd
SDPort = 9103 # Director's port
WorkingDirectory = "/var/lib/bacula"
Pid Directory = "/run/bacula"
Plugin Directory = "/usr/lib"
Maximum Concurrent Jobs = 20
}
[...]
# List Directors who are permitted to contact Storage daemon
#
Director {
Name = q556_d-dir
Password = "X2FRyPJvCMGw8phX2/GkvkTOUxcgfAkTjfILgYFWbIhP"
}
[...]
# Restricted Director, used by tray-monitor to get the
# status of the storage daemon
#
Director {
Name = q556_d-mon
Password = "V/dvYvy+gzV5dAiA7a8wptnVP/zfDFIejzoCkpMB2Ett"
Monitor = yes
}
Save and exit.
3 Further amendments
3.1 Add host ip and name to /etc/hosts
As we use host names instead of IP addresses we make sure that the q556 host’s IP address is known to bacularis. We therefore have to edit /etc/hosts inside the bacularis container.
For convenience we first install vim inside the bacularis container.
root@q556:/var/lib/docker/volumes/bacuprod_etc/_data# docker exec -it bacuprod bash
bash-5.1# apk add vim
fetch https://dl-cdn.alpinelinux.org/alpine/v3.16/main/x86_64/APKINDEX.tar.gz
fetch https://dl-cdn.alpinelinux.org/alpine/v3.16/community/x86_64/APKINDEX.tar.gz
OK: 114 MiB in 95 packages
We can then invoke vim /etc/hosts and add the host machine’s name and IP:
127.0.0.1 localhost
192.168.4.64 q556
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2 7abceb86cb26
/etc/hosts and reamend if necessary.3.2 Wrong database name in script of BackupCatalog job
In my case the default BackupCatalog failed when I tried to run it from the console:
ilek@q556:~/docker/bacudock$ docker exec -it bacutest bconsole
Connecting to Director localhost:9101
1000 OK: 10002 build-3-16-x86_64-dir Version: 11.0.6 (10 March 2022)
Enter a period to cancel a command.
*run
Automatically selected Catalog: MyCatalog
Using Catalog "MyCatalog"
A job name must be specified.
The defined Job resources are:
1: BackupClient1
2: BackupCatalog
3: RestoreFiles
Select Job resource (1-3): 2
Run Backup job
JobName: BackupCatalog
Level: Full
Client: build-3-16-x86_64-fd
FileSet: Catalog
Pool: File (From Job resource)
Storage: File1 (From Job resource)
When: 2022-09-19 15:46:09
Priority: 11
OK to run? (yes/mod/no): yes
Job queued. JobId=1
*messages
19-Sep 15:46 build-3-16-x86_64-dir JobId 1: shell command: run BeforeJob "/etc/bacula/scripts/make_catalog_backup MyCatalog"
19-Sep 15:46 build-3-16-x86_64-dir JobId 1: BeforeJob: pg_dump: error: connection to server on socket "/run/postgresql/.s.PGSQL.5432" failed: FATAL: database "MyCatalog" does not exist
For me the term ‘catalog’ is somewhat confusing. According to the Bacula MRG (Section 22.17), the terms catalog and database are apparently used as synonyms. The error message above FATAL: datatbase "MyCatalog" does not exist corroborates such an assumption.
This leads to two questions:
- What is the actual name of the Bacula database as set up by the Docker container? – Answer: The name of the Bacula PostgreSQL database is (unsurprisingly)
bacula. - In which Ressource(s) of which config file(s) has this ressource been incorrectly referred to as MyCatalog?
Looking at /etc/bacula-dir.conf, we realize that the Job Ressource BackupCatalog contains a directive that is passed MyCatalog as a command line argument.
# 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 are:
# make_catalog_backup <catalog-name>
RunBeforeJob = "/etc/bacula/scripts/make_catalog_backup 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
}Let’s check the content of the script that is called with MyCatalog. And here’s the relevant line:
# you could also add --compress for compression. See man pg_dump
exec ${BINDIR}/pg_dump -c $PGHOST -U $user $1 >$1.sql
;;
esac
Clearly, the pg_dump command expects the database name – which by default is bacula – and not some externally assigned label or alias from a config file.
So to fix the problem, we simply have to replace MyCatalog by bacula in the RunBeforeJob Directive of the Job Resource for BackupCatalog in bacula-dir.conf:
RunBeforeJob = "/etc/bacula/scripts/make_catalog_backup bacula"3.3 No contact to SD when backing up external clients
bacula-dir.conf of the Bacularis host features two Storage resources with an Address directive pointing to localhost. If you try to connect a client from outside the Docker container the job will stall / spin forever and can only be stopped by cancelling it. You will then get an error message that looks as follows:
q556_d-dir JobId 73: Fatal error: Bad response to Storage command: wanted 2000 OK storage
, got Jmsg JobId=73 type=4 level=1664154685 x220-fd JobId 73: Fatal error: job.c:2720 Failed to connect to Storage daemon: localhost:9103The solution is to replace the localhost Address directive in the Storage resource of bacula-dir.conf on host q556 by the host’s hostname – which is q556.
bacula-dir.conf file does not have any Storage resource, but this is directly included in the Autochanger sections.Storage {
Name = "File1"
SdPort = 9103
Address = q556
Password = "X2FRyPJvCMGw8phX2/GkvkTOUxcgfAkTjfILgYFWbIhP"
Device = "FileChgr1"
MediaType = "File1"
Autochanger = "File1"
MaximumConcurrentJobs = 10
}
Storage {
Name = "File2"
SdPort = 9103
Address = q556
Password = "X2FRyPJvCMGw8phX2/GkvkTOUxcgfAkTjfILgYFWbIhP"
Device = "FileChgr2"
MediaType = "File2"
Autochanger = "File2"
MaximumConcurrentJobs = 10
}
4 First test: running local jobs
We now access the Bacula director from the Docker host machine to start with local backups:
ilek@q556:~$ docker exec -it bacuprod bconsole4.1 Catalog backup
Connecting to Director localhost:9101
1000 OK: 10002 q556_d-dir Version: 11.0.6 (10 March 2022)
Enter a period to cancel a command.
*run
Automatically selected Catalog: MyCatalog
Using Catalog "MyCatalog"
A job name must be specified.
The defined Job resources are:
1: BackupClient1
2: BackupCatalog
3: RestoreFiles
Select Job resource (1-3): 2
Run Backup job
JobName: BackupCatalog
Level: Full
Client: q556_d-fd
FileSet: Catalog
Pool: File (From Job resource)
Storage: File1 (From Job resource)
When: 2022-09-22 13:09:43
Priority: 11
OK to run? (yes/mod/no): yes
Job queued. JobId=2
*message
22-Sep 13:09 q556_d-dir JobId 2: shell command: run BeforeJob "/etc/bacula/scripts/make_catalog_backup bacula"
*messages
22-Sep 13:09 q556_d-dir JobId 2: Start Backup JobId 2, Job=BackupCatalog.2022-09-22_13.09.45_03
22-Sep 13:09 q556_d-dir JobId 2: Using Device "FileChgr1-Dev1" to write.
22-Sep 13:09 q556_d-sd JobId 2: Volume "Vol-0001" previously written, moving to end of data.
22-Sep 13:09 q556_d-sd JobId 2: Ready to append to end of Volume "Vol-0001" size=61,640
22-Sep 13:09 q556_d-sd JobId 2: Elapsed time=00:00:01, Transfer rate=64.64 K Bytes/second
22-Sep 13:09 q556_d-sd JobId 2: Sending spooled attrs to the Director. Despooling 219 bytes ...
22-Sep 13:09 q556_d-dir JobId 2: Bacula q556_d-dir 11.0.6 (10Mar22):
Build OS: x86_64-alpine-linux-musl unknown unknown
JobId: 2
Job: BackupCatalog.2022-09-22_13.09.45_03
Backup Level: Full
Client: "q556_d-fd" 11.0.6 (10Mar22) x86_64-alpine-linux-musl,unknown,unknown
FileSet: "Catalog" 2022-09-22 11:50:13
Pool: "File" (From Job resource)
Catalog: "MyCatalog" (From Client resource)
Storage: "File1" (From Job resource)
Scheduled time: 22-Sep-2022 13:09:43
Start time: 22-Sep-2022 13:09:50
End time: 22-Sep-2022 13:09:51
Elapsed time: 1 sec
Priority: 11
FD Files Written: 1
SD Files Written: 1
FD Bytes Written: 64,532 (64.53 KB)
SD Bytes Written: 64,643 (64.64 KB)
Rate: 64.5 KB/s
Software Compression: None
Comm Line Compression: 76.1% 4.2:1
Snapshot/VSS: no
Encryption: no
Accurate: no
Volume name(s): Vol-0001
Volume Session Id: 1
Volume Session Time: 1663852175
Last Volume Bytes: 126,753 (126.7 KB)
Non-fatal FD errors: 0
SD Errors: 0
FD termination status: OK
SD termination status: OK
Termination: Backup OK
22-Sep 13:09 q556_d-dir JobId 2: Begin pruning Jobs older than 6 months .
22-Sep 13:09 q556_d-dir JobId 2: No Jobs found to prune.
22-Sep 13:09 q556_d-dir JobId 2: Begin pruning Files.
22-Sep 13:09 q556_d-dir JobId 2: No Files found to prune.
22-Sep 13:09 q556_d-dir JobId 2: End auto prune.
22-Sep 13:09 q556_d-dir JobId 2: shell command: run AfterJob "/etc/bacula/scripts/delete_catalog_backup"
4.2 Local FileSet backup
We now try to run a file backup job of the local client. Still in bconsole proceed as follows:
*run
A job name must be specified.
The defined Job resources are:
1: BackupClient1
2: BackupCatalog
3: RestoreFiles
Select Job resource (1-3): 1
Run Backup job
JobName: BackupClient1
Level: Incremental
Client: q556_d-fd
FileSet: Full Set
Pool: File (From Job resource)
Storage: File1 (From Job resource)
When: 2022-09-22 13:25:19
Priority: 10
OK to run? (yes/mod/no): yes
Job queued. JobId=3
You have messages.
*messages
22-Sep 13:25 q556_d-dir JobId 3: No prior or suitable Full backup found in catalog. Doing FULL backup.
22-Sep 13:25 q556_d-dir JobId 3: Start Backup JobId 3, Job=BackupClient1.2022-09-22_13.25.48_43
22-Sep 13:25 q556_d-dir JobId 3: Using Device "FileChgr1-Dev2" to write.
22-Sep 13:25 q556_d-sd JobId 3: Volume "Vol-0001" previously written, moving to end of data.
22-Sep 13:25 q556_d-sd JobId 3: Ready to append to end of Volume "Vol-0001" size=126,753
22-Sep 13:25 q556_d-sd JobId 3: Elapsed time=00:00:01, Transfer rate=12.04 M Bytes/second
22-Sep 13:25 q556_d-sd JobId 3: Sending spooled attrs to the Director. Despooling 9,909 bytes ...
22-Sep 13:25 q556_d-dir JobId 3: Bacula q556_d-dir 11.0.6 (10Mar22):
Build OS: x86_64-alpine-linux-musl unknown unknown
JobId: 3
Job: BackupClient1.2022-09-22_13.25.48_43
Backup Level: Full (upgraded from Incremental)
Client: "q556_d-fd" 11.0.6 (10Mar22) x86_64-alpine-linux-musl,unknown,unknown
FileSet: "Full Set" 2022-09-22 13:25:49
Pool: "File" (From Job resource)
Catalog: "MyCatalog" (From Client resource)
Storage: "File1" (From Job resource)
Scheduled time: 22-Sep-2022 13:25:19
Start time: 22-Sep-2022 13:25:52
End time: 22-Sep-2022 13:25:53
Elapsed time: 1 sec
Priority: 10
FD Files Written: 56
SD Files Written: 56
FD Bytes Written: 12,044,152 (12.04 MB)
SD Bytes Written: 12,049,525 (12.04 MB)
Rate: 12044.2 KB/s
Software Compression: None
Comm Line Compression: 57.8% 2.4:1
Snapshot/VSS: no
Encryption: no
Accurate: no
Volume name(s): Vol-0001
Volume Session Id: 2
Volume Session Time: 1663852175
Last Volume Bytes: 12,186,782 (12.18 MB)
Non-fatal FD errors: 0
SD Errors: 0
FD termination status: OK
SD termination status: OK
Termination: Backup OK
22-Sep 13:25 q556_d-dir JobId 3: Begin pruning Jobs older than 6 months .
22-Sep 13:25 q556_d-dir JobId 3: No Jobs found to prune.
22-Sep 13:25 q556_d-dir JobId 3: Begin pruning Files.
22-Sep 13:25 q556_d-dir JobId 3: No Files found to prune.
22-Sep 13:25 q556_d-dir JobId 3: End auto prune.
5 Adding an (external) client
Any client must have a Bacula File Daemon running on the system which allows to the machine to connect with the Bacula Director and the Storage Daemon.
5.1 Installing bacula-fd on a client machine
Why not Docker for external file daemons?
The fastest way to install bacula-fd on a client machine is to pull the bacularis-api-fd from Docker and run a container with the file daemon.
The disadvantage is though, that by default, such a file daemon can only see what is inside the container while we are typically interested in the data on the host which runs the container. Granting the container access to the host data comes with a lot of problems:
- We would need to come up with some NFS stunt to (ideally) mount the client’s complete file system as a volume into the container – but exclude the Docker container files it would produce some kind of “circular reference”.
- Even if this would work, we would have to worry about file ownership and access privileges in the backup process
- There may be older client machines that run a 32 bit OS, while Docker generally requires 64 bit architectures. (Still, Bacula’s deb packages are only provided for 64 bit machines, too).
Direct deployment
All this looks pretty nasty, so installing the file daemon on the client machine in a direct deployment from some deb packages (or whatever installs on the client machine’s OS) looks more suitable.
The first thing is to arm the GPG key and set up the repo information on the client machine. proceed as in section 2 of my post Bacula testing installation. Once you have pulled the apt update from the new repositories, you can install bacula-fd:
ilek@x220:/media/ramdisk$ sudo apt install bacula-client
Check if the client is already running:
ilek@x220:/media/ramdisk$ sudo service bacula-fd status
● bacula-fd.service - Bacula File Daemon service
Loaded: loaded (/lib/systemd/system/bacula-fd.service; enabled; vendor preset: enabled)
Active: active (running) since Sun 2022-09-18 12:27:03 CEST; 1 day 13h ago
Main PID: 1088 (bacula-fd)
Tasks: 3 (limit: 4484)
Memory: 960.0K
CPU: 501ms
CGroup: /system.slice/bacula-fd.service
└─1088 /opt/bacula/bin/bacula-fd -fP -c /opt/bacula/etc/bacula-fd.conf
Sep 18 12:27:03 x220 systemd[1]: Started Bacula File Daemon service.
5.2 Configuration of the client
We first make sure that the client has the bacula director machine’s IP address mapped to the director machine’s host name, so we check if /etc/hosts on the client has an entry with q556 192.196.4.64.
Next, edit the config file in /opt/bacula/etc/bacula-fd.conf (you need to be root to get access to that file).
In the Director Resource, set the correct Name directive by putting in the Name of the director that runs inside the Bacularis Docker container on our main Bacula Server (which is q556 in my case).
# List Directors who are permitted to contact this File daemon
#
Director {
Name = q556_d-dir
Password = "YSJfJkw_X9kfEOT8oFd0LvDgdjT-VoQjo"
}
[...]
# Send all messages except skipped files back to Director
Messages {
Name = Standard
director = q556_d-dir = all, !skipped, !restored, !verified, !saved
}
Todo: Clarify the role and function of the Bacula monitor.
Save and restart the client machine’s file daemon:
ilek@x220:/media/ramdisk$ sudo service bacula-fd restart
ilek@x220:/media/ramdisk$ sudo service bacula-fd status
5.3 Amending bacula-dir.conf on the Bacula director machine
Now change to the machine running the Bacula Director (our Bacularis container) and amend bacula-dir.conf as shown below. The Password directive must match the Password directive we set on the external client machine in the previous step.
# Second Client (File Services) to backup
# You should change Name, Address, and Password before using
#
Client {
Name = x220-fd
Address = x220
FDPort = 9102
Catalog = MyCatalog
Password = "YSJfJkw_X9kfEOT8oFd0LvDgdjT-VoQjo" # password for FileDaemon 2
File Retention = 60 days # 60 days
Job Retention = 6 months # six months
AutoPrune = yes # Prune expired Jobs/Files
}
Restart the Bacula director in the Docker container to activate the amendments:
ilek@q556:~$ docker restart bacuprod
bacuprod
ilek@q556:~$ docker exec -it bacuprod bconsole
Connecting to Director localhost:9101
1000 OK: 10002 q556_d-dir Version: 11.0.6 (10 March 2022)
Enter a period to cancel a command.
*status client
The defined Client resources are:
1: q556_d-fd
2: x220-fd
Select Client (File daemon) resource (1-2): 2
Connecting to Client x220-fd at x220:9102
x220-fd Version: 13.0.1 (05 August 2022) x86_64-pc-linux-gnu-bacula-enterprise ubuntu 22.04
Daemon started 22-Sep-22 15:58. Jobs: run=0 running=0.
Heap: heap=966,656 smbytes=197,860 max_bytes=197,877 bufs=101 max_bufs=101
Sizes: boffset_t=8 size_t=8 debug=0 trace=0 mode=0,0 bwlimit=0kB/s
Crypto: fips=N/A crypto=OpenSSL 3.0.2 15 Mar 2022
Plugin: bpipe-fd.so(2)
Running Jobs:
Director connected using TLS at: 22-Sep-22 16:13
No Jobs running.
====5.4 Opening and forwarding ports
Client side
On the client side, we the Bacula file daemon we installed will listen on port 9102. Use the netstat command to confirm that this port has already been opened when we installed the bacula-client package from the repository.
ilek@x220:~$ netstat -an | grep LISTEN
[..]
tcp 0 0 0.0.0.0:43457 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:43283 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:2049 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:9102 0.0.0.0:* LISTEN
tcp 0 0 10.126.44.1:53 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:631 0.0.0.0:* LISTEN
[...]Docker host side
While Docker usually takes care of opening and forwarding all necessary ports between a container and its host, we also have to make sure that the host machine for the docker container has ports 9101-9103 opened for traffic from and to file and storage daemons.
ilek@q556:~$ sudo netstat -tulpn | grep LISTEN
[...]
tcp 0 0 0.0.0.0:9101 0.0.0.0:* LISTEN 17542/rootlesskit
tcp 0 0 0.0.0.0:9103 0.0.0.0:* LISTEN 17542/rootlesskit
tcp 0 0 0.0.0.0:9102 0.0.0.0:* LISTEN 17542/rootlesskit
tcp 0 0 0.0.0.0:9097 0.0.0.0:* LISTEN 17542/rootlesskit
[...]
tcp6 0 0 :::9101 :::* LISTEN 17542/rootlesskit
tcp6 0 0 :::9103 :::* LISTEN 17542/rootlesskit
tcp6 0 0 :::9102 :::* LISTEN 17542/rootlesskit
tcp6 0 0 :::9097 :::* LISTEN 17542/rootlesskit
After making sure that the host machine is actually accepting traffic on ports 9101-9103, we have to ensure that this traffic is actually forwarded to the Docker container.
First we check if the host machine has activated port forwarding per se. Check if the file /etc/sysctl.conf on the Docker host has the following line uncommented. Detailed instructions on principally allowing port forwarding can be found in my Bacula testing installation post.
Next we check the ufw status:
ilek@q556:~$ sudo ufw status
Status: active
To Action From
-- ------ ----
9096 ALLOW Anywhere
9095 ALLOW Anywhere
22/tcp LIMIT Anywhere
9097 ALLOW Anywhere
9096 (v6) ALLOW Anywhere (v6)
9095 (v6) ALLOW Anywhere (v6)
22/tcp (v6) LIMIT Anywhere (v6)
9097 (v6) ALLOW Anywhere (v6)
Surprisingly, although the previous iptables command showed that the host is listening on ports 9101-9103, ufw does not list these ports under the allowed ports. We therefore allow these ports explicitly under ufw and remove ports 9095 and 9096 as these look like leftovers from a previous legacy Baculum installation:
ilek@q556:~$ sudo ufw delete allow 9095
Rule deleted
Rule deleted (v6)
ilek@q556:~$ sudo ufw delete allow 9096
Rule deleted
Rule deleted (v6)
ilek@q556:~$ sudo ufw allow 9101
Rule added
Rule added (v6)
ilek@q556:~$ sudo ufw allow 9102
Rule added
Rule added (v6)
ilek@q556:~$ sudo ufw allow 9103
Rule added
Rule added (v6)