# Bacula FileSets for Etminan disaster recovery. # # EXAMPLE / REFERENCE ONLY — this is not installed by the etminan package and is # not part of the deliverable. Copy it onto your Bacula Director and adapt the # paths and the "<-- site resource" names to your own deployment. # # A generic backup config for an Etminan deployment — Etminan has exactly two # installable parts, so there are two installation FileSets: # * Etminan-Verifier-FileSet — the verifier install (the trust store; the only # catastrophic-loss host). # * Etminan-Agent-FileSet — an agent install, per monitored host; mostly # re-derivable. Cloned per host in the Jobs file. # # Plus one OPTIONAL, off-host FileSet that is not an installation but is a # critical operator secret: # * Etminan-Operator-Keys-FileSet — the operator's baseline-approval signing # key(s), held on an operator workstation. # Security-sensitive: read the warning above # that FileSet before enabling it. # # NOTE: nothing here is created by any install script — an Etminan deployment is # installed from the package; the operator hand-creates the real config, TLS # identity, and (on the verifier) the DB/state. That operator-created state is # exactly what these FileSets capture, since the package ships only *.example # templates and empty directories. # # IMPORTANT — pair the verifier FileSet with the snapshot pre-job. baseline.db # is SQLite/WAL; this FileSet backs up the *snapshot* produced by # etminan-verifier-snapshot.sh, never the live DB. The Jobs, Schedules, Pools, # and the ClientRunBeforeJob wiring live in the companion etminan-jobs.conf. # Include both from your Director config, FileSets first: # # @/etc/bacula/etminan/etminan-filesets.conf # example path — put them # @/etc/bacula/etminan/etminan-jobs.conf # wherever your Director reads FileSet { Name = "Etminan-Verifier-FileSet" Include { Options { signature = SHA256 compression = GZIP9 # Never back up the live SQLite DB or its sidecars — the snapshot below # is the consistent copy. Excluding these avoids a corrupt/stale restore. WildFile = "/var/lib/etminan-verifier/baseline.db" WildFile = "/var/lib/etminan-verifier/baseline.db-wal" WildFile = "/var/lib/etminan-verifier/baseline.db-shm" WildFile = "/var/lib/etminan-verifier/baseline.db.audit-head" Exclude = yes } Options { signature = SHA256 compression = GZIP9 } # --- The trust store (CATASTROPHIC if lost) --------------------------- # WAL-safe SQLite snapshot + its consistent audit-chain anchor, produced by # ClientRunBeforeJob = etminan-verifier-snapshot.sh. Restore: copy # baseline.db.snapshot -> baseline.db and baseline.db.snapshot.audit-head -> # baseline.db.audit-head (see the exclude block above — never the live DB). File = /var/backups/etminan/baseline.db.snapshot File = /var/backups/etminan/baseline.db.snapshot.audit-head # Per-host enrollment + replay state: pinned AK/EK/TLS fingerprints, PCR10 # cursor, signed enrollment/rotation accountability. Written atomically # (temp+fsync+rename) so a live copy is always consistent — safe as-is. # Losing it forces re-enrollment of every host from scratch. File = /var/lib/etminan-verifier/state.json # This verifier's mTLS identity. Its fingerprint is pinned into every agent # (ETMINAN_VERIFIER_CERT_FINGERPRINT). Losing it forces keygen-tls + re-pin # on every agent by hand. File = /var/lib/etminan-verifier/tls # --- Config + plugin allowlists (recoverable, but back up) ------------ # verifier.env holds plaintext integration secrets (RT/FreeITSM/PagerDuty/ # Slack/webhook). The two *-plugins.conf files carry the SHA256 pins that # authorize plugin execution; the *-plugins/ dirs hold the pinned binaries. # The conf pins and the binaries must restore together. File = /etc/etminan-verifier # --- Convenience: fast-restore binary (re-installable from package) --- WildFile = "/usr/bin/etminan-verifier" File = /usr/bin # --- NOT captured here (off-host / out of band): -------------------------- # * Operator baseline-approval signing keys — no default path; created by # `keygen --out `, held per-operator OFF the verifier host. Their # private halves sign approve/reject/enroll; a lost key cannot re-sign # existing baseline_batches. Back up per operator (their responsibility). # * Plugin-catalog signing key (~/.etminan-catalog-signing.key) — offline, # never on a verifier host (HANDBOOK §5). # * The host TPM is the irreplaceable factor for AGENTS: a TPM clear/reset # invalidates the AK/EK pinned in state.json and forces re-enroll. TPM # key material cannot be backed up. } } FileSet { Name = "Etminan-Agent-FileSet" Include { Options { signature = SHA256 compression = GZIP9 } # Agent mTLS identity — fingerprint is pinned in the verifier's state.json. # Loss requires re-enroll or rotate-tls (verifier-side action), not fatal. File = /var/lib/etminan-agent/tls # Last profile pushed by assign-profile; re-derivable (authoritative record # is in the verifier's state.json + audit_log), included for a clean restore. File = /var/lib/etminan-agent/assigned_profile # agent.env (holds ETMINAN_VERIFIER_CERT_FINGERPRINT, the pin) + profiles.conf File = /etc/etminan-agent WildFile = "/usr/bin/etminan-agent" File = /usr/bin # NOTE: TPM AK/EK are in-TPM only — nothing on disk to back up. A TPM clear # forces re-enrollment regardless of this backup. } } # ── Etminan-Operator-Keys-FileSet — OFF-HOST, read this before enabling ─────── # The crown-jewel private keys that are deliberately NOT stored on any verifier # or agent (that separation is the whole point — a compromised verifier host must # not also yield the keys that authorize its baselines): # # * Operator baseline-approval signing key(s) — sign enroll/rotate/approve/ # reject/assign-profile. No default path; created per-operator with # `etminan-verifier keygen --out ` (writes + .pub). A # lost private half cannot re-sign existing baseline_batches. This is the # key a customer deployment actually has. # * (Only if you run your OWN private plugin catalog) a catalog signing key # from `etminan-verifier plugins keygen-catalog`. Most deployments don't — # they consume the vendor catalog, whose public half is compiled in and # whose private half never exists on a customer host at all. Skip unless # you self-sign a catalog. # # SECURITY — do NOT undo the separation this design relies on: # * Back these up ONLY from the operator workstation that legitimately holds # them, into their OWN pool (EtminanOperatorKeysPool in etminan-jobs.conf) — # NEVER the verifier pool. A single pool restore must never hand someone both # the baselines AND the keys that authorize them. # * Prefer an encrypted, offline medium. If you do use Bacula, enable client- # side Data Encryption (PKI Encryption/PKI Keypair on the operator # workstation's FileDaemon) so the keys are encrypted at rest in the volume. # * This FileSet is the Bacula option for shops that already back up operator # workstations — not a recommendation to put signing keys on the same tape # as everything else. FileSet { Name = "Etminan-Operator-Keys-FileSet" Include { Options { signature = SHA256 compression = GZIP9 # See the SECURITY note above — configure PKI Encryption on this client's # FileDaemon so these private keys are encrypted at rest in the volume. } # Fill in the ACTUAL paths on this operator's workstation. Operator signing # keys have no default location (keygen --out ) — these are examples: File = /home//.etminan/operator-signing.key File = /home//.etminan/operator-signing.key.pub # Only if you self-sign your own plugin catalog (uncommon — see above): # File = /home//.etminan-catalog-signing.key } }