Included in all faaleoleo plans

faaleoleo Log Audit

Cryptographically signed, hash-chained audit logs for Bacula

ed25519 Per-entry signature
SHA-256 Hash chain
6 Integration modes
0 Bacula changes required

What it is

Audit logs that prove they haven’t been touched

Bacula records what happened. faaleoleo Log Audit proves the record has not been altered.

Every event written by faaleoleo Log Audit carries two cryptographic guarantees. A SHA-256 hash chain links each entry to the one before it — deleting, inserting, or modifying any entry breaks every subsequent hash. An ed25519 signature over each entry’s hash proves authenticity: only the private key on the Bacula server could have produced it.

The result is a log where tampering is not just detectable — it is provably detectable by anyone holding the public key, offline, without any access to your infrastructure.

# Last 4 entries

  ● [1042] 2026-06-21 08:32  warning  system
            auth_failure    192.168.1.71
  ● [1043] 2026-06-21 08:33  warning  system
            auth_failure    192.168.1.71
  ● [1044] 2026-06-21 09:15  info     ops-team
            console_connect bacula-dir
  ● [1045] 2026-06-21 09:17  info     ops-team
            config_reload   bacula-dir

# Verifying the same log against the public key

✓ VERIFIED — 1,045 entries,
  chain intact, all signatures valid.

Compliance

What the standards actually require

Standard Bacula logging satisfies none of these protection requirements. faaleoleo Log Audit satisfies all of them.

NIS2 — Article 21

Essential and important entities must implement monitoring and detection measures and demonstrate they were in effect. A log that can be silently edited does not satisfy this requirement.

GDPR — Article 5(2) & 32

The accountability principle places the burden of proof on the controller. Records of backup access and restore operations must be indisputable to satisfy supervisory authority requests.

DORA — Article 9 & 10

Financial entities must maintain ICT event detection capabilities and trustworthy logs for incident investigations. Regulators expect those logs to be tamper-evident, not just present.

ISO 27001 — A.8.15

Event logs must be "produced, stored, protected, and analysed." Protection means the log cannot be altered without detection — exactly what the hash chain and signature guarantee.

Incident tracking

The log doesn’t just record events — it tracks your deadlines

Every entry at error/critical severity, or carrying a correlation ID, is grouped into a candidate incident. NIS2 (Article 23) and DORA (Article 17) reporting deadlines are computed against it automatically — early warning, notification, and final report windows, all tracked from the moment of detection.

An overdue tag is a clock check, not a verdict: the classifier is deliberately blunt, so every candidate still needs a human to read the entry behind it. Acknowledging a stage appends a permanent, signed, attributable entry to the same log — who reviewed it and why — so status is always recomputed from the signed record, never a separate database.

This closes a gap the standards themselves don’t stop at: NIS2, DORA, GDPR, and ISO 27001 all scope event detection and accountability across an organisation’s systems generally, not only the backup layer. See the July 2026 update for the full detail, including the security hardening pass covered below.

# Candidate incident, computed deadlines

seq-376  severity=error  entries=1
  detected=2026-07-11T19:52:09  [OVERDUE]
    actions:   ssh_event
    resources: bacula-dir
    nis2  early_warning=2026-07-12T19:52:09 (OVERDUE)
          notification=... (pending)  final=... (pending)
    dora  notification=2026-07-12T19:52:09 (OVERDUE)
          final=... (pending)

How it works

Two guarantees on every entry

faaleoleo Log Audit runs alongside Bacula without modifying it. It reads events, signs them, and writes to a separate append-only file.

Hash chain

Each entry carries the SHA-256 hash of the entry before it. Delete, insert, or reorder any entry and the chain breaks at that point — detectable on the very next verification run.

ed25519 signature

Each entry is signed with a private key that never leaves the Bacula server. Verification requires only the public key — auditors can verify offline with any ed25519 library.

Canonical JSON

The hash is computed over a deterministic JSON serialisation (sorted keys, no whitespace). Cross-tool verification is possible in any language without faaleoleo tooling.

Monotonic sequence numbers

Every entry is numbered. Gaps are detected immediately during verification — a log with entries 1–99 and 101 onwards proves entry 100 was deleted.

Append-only JSONL

One event per line. Human-readable and parseable by any JSON tool, SIEM, or log aggregator. No proprietary format, no vendor lock-in.

Non-intrusive

All integration modes are strictly read-only with respect to Bacula. No configuration changes to the Director are required for the community edition.

Multi-source intake

A host-wide socket intake mode lets any other service write signed entries into the same chain without ever holding the private key, and a systemd journal bridge folds any unit’s log straight in — one tamper-evident trail, not just for Bacula.

Hardened signing core

Private key pages locked into RAM and zeroized on drop, atomic key file creation, symlink-safe log access, and kernel-level sandboxing on every service unit.

In practice

What a verification run looks like

Two commands: tail to inspect the log, verify to prove it has not been altered. The auditor needs only the public key — no access to the Bacula server.

Clean log

1,045 entries spanning two weeks. Every hash matches, every signature is valid. Exit code 0.

# Last 8 entries

  ● [1038] 2026-06-21 01:00  info
            scheduler  job_complete
            NightlyFull / db01-fd
  ● [1042] 2026-06-21 08:32  warning
            system     auth_failure
            192.168.1.71
  ● [1044] 2026-06-21 09:15  info
            ops-team   console_connect
            bacula-dir
  ● [1045] 2026-06-21 09:17  info
            ops-team   config_reload
            bacula-dir

# Verifying against the public key

✓ VERIFIED — 1,045 entries,
  chain intact,
  all signatures valid.
  Timespan: 2026-06-07T00:00:01Z
         → 2026-06-21T09:17:33Z

Tampered log

Entry 3 was modified after signing. The hash mismatch is detected immediately, and the broken chain flags every subsequent entry.

# Verifying against the public key

✗ VERIFICATION FAILED
  2 error(s) found.
  Timespan: 2026-06-07T00:00:01Z
         → 2026-06-21T09:17:33Z

  Errors:
    ✗ [seq=3] Hash mismatch:
      stored=a1a279b8fd5e0654...
      computed=9f3c8b12d0e7a123...

    ✗ [seq=4] Hash chain broken:
      prev_hash=a1a279b8fd5e0654...
      expected=9f3c8b12d0e7a123...

Included in every faaleoleo plan — no add-on, no extra cost.

faaleoleo Log Audit is configured and running from day one on every managed Bacula deployment we operate. Every customer receives the public key for their installation at setup.

Talk to us