Gegenbuch als Docker-Setup, lokales Buch auf eigener Maschine

Betreiber-Entscheidung: Das Gegenbuch laeuft auf einer eigenen Maschine fuer
Prod und Staging; ein externes Git-Repository entfaellt, das Buch liegt lokal.
Die Trennung, auf die es ankommt, ist damit gegeben - wer OpenCRM uebernimmt,
kommt nicht ans Buch.

Richtung bewusst so herum: Das Gegenbuch holt ueber HTTPS mit einem Token, das
nur audit:read kann. OpenCRM kennt weder Adresse noch Schluessel des
Gegenbuchs. Kein SSH-Zugang zum CRM noetig.

tools/audit-notary/ enthaelt jetzt Dockerfile, entrypoint.sh,
docker-compose.yml und .env.example. Zwei Dienste (prod, staging) mit
getrennten Verzeichnissen und Schluesseln, gesteuert ueber COMPOSE_PROFILES -
dasselbe Muster wie beim Caddy-Profil im Hauptstack. Der Signaturschluessel
wird beim ersten Start auf der Gegenbuch-Maschine erzeugt.

Lokaler Betrieb ist jetzt ein vollwertiger Modus statt eines Testschalters. Die
Erfolgsmeldung benennt bei jedem Lauf, was abgedeckt ist und was nicht - statt
der frueheren pauschalen Formulierung "kein Manipulationsschutz", die im
Einsatz auf eigener Maschine schlicht falsch war.

Verifiziert mit echtem Docker-Build gegen eine CRM-Attrappe: Genesis ohne
Bestaetigung -> Code 4; mit Bestaetigung Normalbetrieb exit 0; Eintrag
veraendert -> Alarm exit 2; Eintraege geloescht -> Alarm exit 2; Siegel
verschwunden -> Alarm.

Behoben beim Bauen: useradd -u 1000 || true verschluckte, dass UID 1000 im
Node-Image vergeben ist - der Container startete gar nicht.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-22 18:51:45 +02:00
co-authored by Claude Opus 5
parent 773033936d
commit a62c51b7c7
7 changed files with 316 additions and 5 deletions
+55
View File
@@ -0,0 +1,55 @@
# Gegenbuch für OpenCRM
# =====================
# Gehört auf einen EIGENEN Rechner nicht dorthin, wo OpenCRM läuft.
#
# Richtung der Verbindung (das ist der eigentliche Schutz):
# Gegenbuch ──holt lesend──> OpenCRM (HTTPS, Token nur mit audit:read)
# OpenCRM ─────────────────> (kennt das Gegenbuch nicht)
#
# Wer OpenCRM übernimmt, kommt damit nicht an dieses Buch heran. Deshalb holt
# das Gegenbuch selbst, statt sich etwas schicken zu lassen.
#
# Start:
# cp .env.example .env # Werte eintragen
# docker compose up -d
#
# Zwei Bücher auf einer Maschine sind vorgesehen (Produktion und Test): zwei
# getrennte Dienste mit getrennten Verzeichnissen und getrennten Schlüsseln.
# Welche laufen, steuert COMPOSE_PROFILES in der .env.
services:
prod:
build: .
container_name: gegenbuch-prod
restart: unless-stopped
profiles: ["prod"]
environment:
INSTANZ: prod
CRM_URL: ${PROD_CRM_URL}
CRM_TOKEN: ${PROD_CRM_TOKEN}
NOTARY_INTERVAL: ${PROD_INTERVAL:-3600}
NOTAR_EMAIL: ${NOTAR_EMAIL:-gegenbuch@localhost}
# Nur beim allerersten Lauf einmalig auf true, danach wieder leeren:
NOTARY_GENESIS_ACK: ${PROD_GENESIS_ACK:-}
# Nur nach geklärtem Verlust des Beobachtungsspeichers, siehe README:
NOTARY_ADOPT_ACK: ${PROD_ADOPT_ACK:-}
volumes:
# Buch, Schlüssel, Beobachtungsspeicher und Statusdatei.
# Dieses Verzeichnis ist das Gegenbuch es gehört ins Backup.
- ${PROD_DIR:-./data/prod}:/gegenbuch
staging:
build: .
container_name: gegenbuch-staging
restart: unless-stopped
profiles: ["staging"]
environment:
INSTANZ: staging
CRM_URL: ${STAGING_CRM_URL}
CRM_TOKEN: ${STAGING_CRM_TOKEN}
NOTARY_INTERVAL: ${STAGING_INTERVAL:-3600}
NOTAR_EMAIL: ${NOTAR_EMAIL:-gegenbuch@localhost}
NOTARY_GENESIS_ACK: ${STAGING_GENESIS_ACK:-}
NOTARY_ADOPT_ACK: ${STAGING_ADOPT_ACK:-}
volumes:
- ${STAGING_DIR:-./data/staging}:/gegenbuch