diff --git a/docs/todo.md b/docs/todo.md index f2e0e3d6..9df5dcd5 100644 --- a/docs/todo.md +++ b/docs/todo.md @@ -97,6 +97,24 @@ isolierte Instanz (keine Multi-Tenancy im Code), Provisioning + Abrechnung ## ✅ Erledigt +- [x] **🔧 Gegenbuch-Container: Rechte am Bind-Mount selbst geraderuecken** (2026-08-22) + - Fehlerbild aus dem echten Betrieb: `mkdir: cannot create directory + '/gegenbuch/schluessel': Permission denied`, Container in der + Neustart-Schleife. Ursache: Das Datenverzeichnis kommt als Bind-Mount vom + Host; der Betreiber hatte das Projekt als **root** geklont, der Container + lief aber direkt als UID 1000 und durfte dort nichts anlegen. + Mein `.gitkeep`-Ansatz hatte stillschweigend angenommen, dass als normaler + Benutzer geklont wird – auf einem Server ist root der Normalfall. + - Fix: Der Container startet als root, setzt `/gegenbuch` per `chown` auf den + Arbeitsbenutzer (`PUID`/`PGID`, Standard 1000) und startet sich per + `setpriv` als dieser neu. Die eigentliche Arbeit laeuft damit weiterhin + unprivilegiert. Schlaegt das `chown` fehl (z. B. rootless Docker), gibt es + einen Hinweis mit dem passenden Host-Befehl statt eines stummen Abbruchs. + - Verifiziert mit exakt der Ausgangslage: Datenverzeichnis auf `root:root` + gesetzt, Container gestartet → laeuft durch, Schluessel und Buch werden + angelegt, erzeugte Dateien gehoeren 1000:1000, der private Schluessel liegt + mit `0600`. + - [x] **🔑 Gegenbuch: Dienstkonto statt Token, .env mit gueltigen Werten** (2026-08-22) - **Blocker gefunden und behoben:** Ich hatte ein dauerhaftes API-Token vorausgesetzt – das gibt es in OpenCRM gar nicht. Zugangstoken leben diff --git a/tools/audit-notary/Dockerfile b/tools/audit-notary/Dockerfile index 63edeb5f..66563665 100644 --- a/tools/audit-notary/Dockerfile +++ b/tools/audit-notary/Dockerfile @@ -15,9 +15,13 @@ COPY notary.mjs /opt/notary/notary.mjs COPY entrypoint.sh /opt/notary/entrypoint.sh RUN chmod +x /opt/notary/entrypoint.sh -# Nicht als root laufen. Das Node-Image bringt bereits einen Benutzer mit -# UID 1000 mit ("node") – der passt zu Bind-Mounts unter ./data/. -USER node +# Der Container STARTET als root – aber nur, um die Rechte auf dem +# Datenverzeichnis geradezuziehen. Danach gibt der entrypoint die Privilegien +# ab und arbeitet als unprivilegierter Benutzer weiter. +# +# Grund: Das Datenverzeichnis kommt als Bind-Mount vom Host. Wer das Projekt +# als root geklont hat, hat dort root-eigene Verzeichnisse – ein Container, der +# direkt als UID 1000 startet, kann darin nichts anlegen. WORKDIR /gegenbuch ENTRYPOINT ["/opt/notary/entrypoint.sh"] diff --git a/tools/audit-notary/README.md b/tools/audit-notary/README.md index eaf8d7f8..6932f798 100644 --- a/tools/audit-notary/README.md +++ b/tools/audit-notary/README.md @@ -113,7 +113,14 @@ tools/audit-notary/data/prod/ ``` Der Inhalt ist vom Repository ausgenommen – der Signaturschlüssel gehört dort -nicht hinein. Die Verzeichnisse selbst sind über `.gitkeep` vorhanden, damit +nicht hinein. + +**Zu Dateirechten:** Der Container startet kurz als `root`, setzt das +Datenverzeichnis auf den Arbeitsbenutzer um und gibt die Privilegien dann ab. +Das ist nötig, weil das Verzeichnis vom Host kommt – wer das Projekt als `root` +geklont hat, hätte sonst ein Verzeichnis, in das der Container nicht schreiben +darf. Passiert automatisch, du musst nichts tun. Ein anderer Zielbenutzer geht +über `PUID`/`PGID`. Die Verzeichnisse selbst sind über `.gitkeep` vorhanden, damit sie nach einem `git clone` schon existieren und Docker sie nicht als `root` anlegt. diff --git a/tools/audit-notary/entrypoint.sh b/tools/audit-notary/entrypoint.sh index d58a509b..6f53c0d7 100755 --- a/tools/audit-notary/entrypoint.sh +++ b/tools/audit-notary/entrypoint.sh @@ -14,6 +14,22 @@ export NOTARY_STATE_FILE=/gegenbuch/beobachtungen.jsonl export NOTARY_ALLOW_LOCAL=true # Buch liegt auf dieser Maschine export NOTARY_PUSH=false # es gibt kein Ziel zum Pushen +# --- Rechte geraderuecken, dann Privilegien abgeben ------------------------ +# Laeuft der Container als root, gehoert das Bind-Mount-Verzeichnis vermutlich +# ebenfalls root (typisch, wenn das Projekt als root geklont wurde). Wir setzen +# es auf den Arbeitsbenutzer um und starten uns selbst als dieser neu. +BENUTZER_UID="${PUID:-1000}" +BENUTZER_GID="${PGID:-1000}" +if [ "$(id -u)" = "0" ]; then + if ! chown -R "$BENUTZER_UID:$BENUTZER_GID" /gegenbuch 2>/dev/null; then + echo "[$INSTANZ] HINWEIS: Rechte auf /gegenbuch liessen sich nicht setzen." >&2 + echo "[$INSTANZ] Falls es gleich an fehlenden Schreibrechten scheitert, auf dem Host:" >&2 + echo "[$INSTANZ] chown -R $BENUTZER_UID:$BENUTZER_GID " >&2 + fi + exec setpriv --reuid="$BENUTZER_UID" --regid="$BENUTZER_GID" --init-groups \ + --inh-caps=-all "$0" "$@" +fi + echo "[$INSTANZ] Gegenbuch startet – Quelle: $CRM_URL, Takt: ${INTERVALL}s" # --- Signaturschlüssel: einmalig auf DIESER Maschine erzeugen ---------------