Gegenbuch-Container: Rechte am Bind-Mount selbst geraderuecken
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. Der .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 weiterhin unprivilegiert. Schlaegt das chown fehl (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, erzeugte Dateien gehoeren 1000:1000, der private Schluessel liegt mit 0600. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -97,6 +97,24 @@ isolierte Instanz (keine Multi-Tenancy im Code), Provisioning + Abrechnung
|
|||||||
|
|
||||||
## ✅ Erledigt
|
## ✅ 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)
|
- [x] **🔑 Gegenbuch: Dienstkonto statt Token, .env mit gueltigen Werten** (2026-08-22)
|
||||||
- **Blocker gefunden und behoben:** Ich hatte ein dauerhaftes API-Token
|
- **Blocker gefunden und behoben:** Ich hatte ein dauerhaftes API-Token
|
||||||
vorausgesetzt – das gibt es in OpenCRM gar nicht. Zugangstoken leben
|
vorausgesetzt – das gibt es in OpenCRM gar nicht. Zugangstoken leben
|
||||||
|
|||||||
@@ -15,9 +15,13 @@ COPY notary.mjs /opt/notary/notary.mjs
|
|||||||
COPY entrypoint.sh /opt/notary/entrypoint.sh
|
COPY entrypoint.sh /opt/notary/entrypoint.sh
|
||||||
RUN chmod +x /opt/notary/entrypoint.sh
|
RUN chmod +x /opt/notary/entrypoint.sh
|
||||||
|
|
||||||
# Nicht als root laufen. Das Node-Image bringt bereits einen Benutzer mit
|
# Der Container STARTET als root – aber nur, um die Rechte auf dem
|
||||||
# UID 1000 mit ("node") – der passt zu Bind-Mounts unter ./data/.
|
# Datenverzeichnis geradezuziehen. Danach gibt der entrypoint die Privilegien
|
||||||
USER node
|
# 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
|
WORKDIR /gegenbuch
|
||||||
|
|
||||||
ENTRYPOINT ["/opt/notary/entrypoint.sh"]
|
ENTRYPOINT ["/opt/notary/entrypoint.sh"]
|
||||||
|
|||||||
@@ -113,7 +113,14 @@ tools/audit-notary/data/prod/
|
|||||||
```
|
```
|
||||||
|
|
||||||
Der Inhalt ist vom Repository ausgenommen – der Signaturschlüssel gehört dort
|
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`
|
sie nach einem `git clone` schon existieren und Docker sie nicht als `root`
|
||||||
anlegt.
|
anlegt.
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,22 @@ export NOTARY_STATE_FILE=/gegenbuch/beobachtungen.jsonl
|
|||||||
export NOTARY_ALLOW_LOCAL=true # Buch liegt auf dieser Maschine
|
export NOTARY_ALLOW_LOCAL=true # Buch liegt auf dieser Maschine
|
||||||
export NOTARY_PUSH=false # es gibt kein Ziel zum Pushen
|
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 <datenverzeichnis>" >&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"
|
echo "[$INSTANZ] Gegenbuch startet – Quelle: $CRM_URL, Takt: ${INTERVALL}s"
|
||||||
|
|
||||||
# --- Signaturschlüssel: einmalig auf DIESER Maschine erzeugen ---------------
|
# --- Signaturschlüssel: einmalig auf DIESER Maschine erzeugen ---------------
|
||||||
|
|||||||
Reference in New Issue
Block a user