Bis jetzt gab es kein Audit-Device - also keinerlei Aufzeichnung, wer welches
Geheimnis gelesen hat. Bei der Fehlersuche an der Identitaet "claude" am
2026-10-03 haette ein Blick ins Audit-Log die Ursache sofort gezeigt, weil die
beim Login vergebenen Policies darin stehen.
Deklarativ in openbao.hcl statt per `bao audit enable`: OpenBAO 2.x lehnt den
API-Weg ausdruecklich ab ("cannot enable audit device via API; use declarative,
config-based audit device management instead") - anders als Vault. Der Block
wird bei Neustart und bei SIGHUP uebernommen, der Reload lief daher ohne
Ausfall und ohne Entsiegeln.
log_raw bleibt auf dem Standard false: sensible Werte werden gehasht. Im Log
steht nachgeprueft ein HMAC statt des client_token, dazu Operation, Pfad,
display_name, policies und entity_id.
Dazu zwei Dinge, die das betriebssicher machen:
- /openbao/logs war ein ANONYMES Volume aus dem Image, nicht in der compose
deklariert. Es haette ein `docker compose down -v` nicht ueberlebt. Jetzt ein
Bind-Mount auf ./logs (uid 100 = openbao im Container). Der Pfad im Container
bleibt gleich, der audit-Block muss dafuer nicht angepasst werden. Greift beim
naechsten `docker compose up -d openbao`.
- logrotate: taeglich, 30 Generationen, zusaetzlich maxsize 100M. Das ist
Pflicht, nicht Komfort - Audit-Devices sind blockierend, bei voller Platte
weist OpenBAO Anfragen ab. SIGHUP im postrotate statt copytruncate, damit
keine Zeilen verloren gehen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FXUoNtUh1qEdZXSzQeSos4
Beim ersten Neustart seit 106 Tagen (2026-09-20) zeigte sich: der Unsealer kommt
versiegelt hoch, die Hauptinstanz startet daraufhin endlos neu und nichts kann mehr
Secrets lesen - Backups, Traefik-Zertifikate, Skripte. Bisher musste das jemand
von Hand entsiegeln.
- scripts/unseal-unsealer.sh + systemd/openbao-auto-unseal.service: entsiegelt die
Sidecar nach docker.service, startet die Hauptinstanz nach und schreibt die Metrik
openbao_unsealer_unsealed (cp1 alarmiert darauf). Idempotent.
Zwei Fallstricke, die das Skript umgeht: `bao operator unseal -` (Schluessel ueber
stdin) wird abgelehnt, und `bao status` liefert Exit 2 bei versiegelt - was trotzdem
heisst, dass der Container antwortet.
Der Schluessel liegt in /etc/openbao-unsealer.key (root, 0400), nicht im Repo.
- scripts/renew-gitea-cert.sh + systemd/gitea-cert-renew.*: gitea.famfi.home bekommt
ein Zertifikat aus der eigenen PKI (90 Tage, Erneuerung ab 21 Tagen Restlaufzeit),
Aufbau wie bei renew-openbao-cert.sh.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The main node's transit seal token (config/seal.hcl) lives on the unsealer
and was never renewed. It lapsed, and after the 2026-09-17 reboot main
crash-looped with 403 on transit/encrypt/autounseal even once the unsealer
was unsealed. renew-app-tokens.sh now parses it out of seal.hcl and renews
it via the same docker-exec path as the unsealer backup token.
Also widen .gitignore to config/seal.hcl* so timestamped backups of the
file (which contain the token) cannot be committed.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Generalize the .26 rollout into a reusable template:
- authorize the host principal on ssh/roles/host (allowlist, merged)
- sign the host certificate (ssh/sign/host)
- emit a self-contained installer (user-CA TrustedUserCAKeys + HostCertificate)
to artifacts/, additive and lockout-safe
- add @cert-authority for the host to the client's known_hosts
Needs no SSH access to the target (ssh-keyscan). README updated.
Also gitignore .claude/ (local harness settings).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Turn the ssh/ engine into an SSH CA for cert-based access:
- ssh/ roles: "user" (8h user certs, principal-restricted) and "host"
(long-lived host certs); mount max-lease-ttl raised for host certs
- scripts/ssh-login.sh: sign a fresh user cert via a scoped ssh/sign/user
token (API, no bao binary) and connect — no authorized_keys on targets
- ca/openbao-ssh-ca.pub: the SSH CA public key (for TrustedUserCAKeys and
client @cert-authority trust)
- README: usage, host onboarding, client trust
- gitignore generated per-host artifacts/
First host wired + verified end-to-end: 192.168.0.26 (pifour) — lutz cert
login and host-cert verification both confirmed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Build out the home-lab OpenBAO deployment beyond the basic node:
- docker-compose: add openbao-unsealer sidecar; main node now transit
auto-unseals against it (seal config kept in gitignored config/seal.hcl)
- policies/admin.hcl: non-root admin policy; per-engine rules for
ssh/pki/pki_int/totp/transit
- Internal two-tier CA (pki/ root + pki_int/ intermediate) issues the
openbao.famfi.home leaf Traefik serves; root CA published under ca/
- scripts/ + systemd/: daily cert renewal and Raft snapshot backups
(both instances), with scoped tokens stored outside the repo
- README: full runbook (auto-unseal, PKI, renewal, backups, DR/restore)
Secrets (init/unsealer keys, tokens, seal stanza) stay gitignored.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>