.env.example belegte S3_ENDPOINT mit der Adresse eines externen
Anbieters. Gedacht war das als Beispiel - in der kopierten .env stand es
aber aktiv, und damit sprach die Anwendung mit einem fremden Host statt
mit dem Objektspeicher nebenan.
Verschaerfend: Die docker-compose.yml hatte laengst einen brauchbaren
Standard, ${S3_ENDPOINT:-http://minio:9000}. Der greift nur bei leerer
Variable - die Beispieldatei hebelte ihn aus. Der Mechanismus, der genau
diesen Fehler verhindern sollte, war durch die Beispieldatei wirkungslos.
Auf dem Livesystem hat das monatelang jede Ablage scheitern lassen, und
die Zugangs-ID des lokalen Speichers ging bei jedem Versuch nach draussen.
Die Zeile ist jetzt auskommentiert, mit einer Erklaerung, wann man sie
braucht.
Nebenbei stand dort SEED_ADMIN_EMAIL mit der Adresse des Betreibers. In
einer mitgelieferten Beispieldatei hat eine persoenliche Adresse nichts
zu suchen - jetzt leer.
Der Test prueft beides und dazu die allgemeine Regel: Kein aktiver Wert
in der Beispieldatei zeigt auf einen fremden Rechner. Er prueft auch,
dass ueberhaupt Zuweisungen gefunden werden - sonst staende er gruen da
und pruefte nichts.
Gegen zwei Mutationen geprueft: Endpunkt wieder aktiv, persoenliche
Adresse wieder eingetragen - beide werden rot.
Refs #45
146 lines
6.1 KiB
Bash
146 lines
6.1 KiB
Bash
# =============================================================================
|
|
# Betreuungs-Cockpit - Beispielkonfiguration
|
|
# Kopiere diese Datei nach .env und fuelle die Werte aus.
|
|
# Alle Geheimnisse erzeugst du mit: npm run schluessel
|
|
# =============================================================================
|
|
|
|
# --- Datenbank --------------------------------------------------------------
|
|
# Lokal (Docker Compose): Host ist der Servicename "db".
|
|
POSTGRES_USER=cockpit
|
|
POSTGRES_PASSWORD=bitte-aendern
|
|
POSTGRES_DB=betreuungs_cockpit
|
|
DATABASE_URL="postgresql://cockpit:bitte-aendern@localhost:5432/betreuungs_cockpit?schema=public"
|
|
|
|
# --- Auth.js ----------------------------------------------------------------
|
|
# 32 zufaellige Bytes, base64. Erzeugen: npm run schluessel
|
|
AUTH_SECRET=
|
|
# Oeffentliche Basis-URL der Anwendung (ohne abschliessenden Slash).
|
|
# Hinter einem Proxy die Adresse, die im Browser in der Adresszeile steht -
|
|
# nicht die interne. Passkeys pruefen dagegen.
|
|
AUTH_URL=http://localhost:3000
|
|
|
|
# Darf der Host-Kopf der Anfrage die Adresse bestimmen?
|
|
#
|
|
# Solange AUTH_URL gesetzt ist: nein, und die Zeile bleibt weg. Die Adresse
|
|
# ist dann bekannt und muss nicht aus einer Kopfzeile abgeleitet werden, die
|
|
# von aussen kommt. Ein "X-Forwarded-Host: fremde.example" schlaegt sonst in
|
|
# erzeugte Adressen durch.
|
|
# AUTH_TRUST_HOST=true
|
|
|
|
# --- Erreichbarkeit: HIER MUSST DU DICH ENTSCHEIDEN -------------------------
|
|
#
|
|
# Auf welcher Adresse soll die Anwendung erreichbar sein? Das haengt davon
|
|
# ab, WO dein Reverse Proxy laeuft. Waehl genau eine Zeile aus:
|
|
#
|
|
# Proxy auf DEMSELBEN Server
|
|
# APP_BIND=127.0.0.1
|
|
# Von aussen kommt niemand heran, nur der Proxy nebenan. Sicherste
|
|
# Variante - aber ein Proxy auf einem anderen Rechner erreicht die
|
|
# Anwendung damit NICHT.
|
|
#
|
|
# Proxy auf einem ANDEREN Server, privates Netz oder WireGuard vorhanden
|
|
# APP_BIND=10.0.0.5 <- die Adresse DIESES Servers in dem Netz
|
|
# Erste Wahl, wenn der Proxy woanders steht.
|
|
#
|
|
# Proxy auf einem ANDEREN Server, kein privates Netz
|
|
# APP_BIND=0.0.0.0
|
|
# Nur zusammen mit einer Firewallregel, die den Port ausschliesslich
|
|
# fuer die IP des Proxy-Servers oeffnet:
|
|
# ufw allow from <IP-des-Proxys> to any port 3000 proto tcp
|
|
# ufw deny 3000/tcp
|
|
#
|
|
# Zwischen Proxy und Anwendung laeuft unverschluesseltes HTTP - die
|
|
# Anwendung beendet kein TLS. Dieser Weg darf nie durchs offene Netz gehen.
|
|
# Einzelheiten: docs/INSTALLATION.md, Schritt 7.
|
|
APP_BIND=127.0.0.1
|
|
APP_PORT=3000
|
|
|
|
# Die Konsole des mitgelieferten Objektspeichers. Nur noetig, wenn auf dem
|
|
# Server schon etwas auf 9001 laeuft.
|
|
MINIO_KONSOLE_PORT=9001
|
|
|
|
# --- Anwendungsseitige Feldverschluesselung ---------------------------------
|
|
# AES-256-GCM. 32 Bytes, base64. OHNE DIESEN SCHLUESSEL SIND DIE VERSCHLUESSELTEN
|
|
# FELDER UNWIEDERBRINGLICH VERLOREN - unbedingt getrennt vom Backup sichern!
|
|
# Schluesselrotation: neuen Schluessel als ENC_KEY_V2 ergaenzen und
|
|
# ENC_KEY_AKTIV=2 setzen. Alte Schluessel bleiben zum Entschluesseln stehen.
|
|
ENC_KEY_V1=
|
|
ENC_KEY_AKTIV=1
|
|
|
|
# Separater Schluessel fuer Blind-Indizes (HMAC-SHA256).
|
|
# Erlaubt die Suche nach z.B. einer IBAN, ohne sie im Klartext zu speichern.
|
|
INDEX_KEY=
|
|
|
|
# --- Sicherheit -------------------------------------------------------------
|
|
# Leerlauf bis zur automatischen Abmeldung (Sekunden). 30 Minuten.
|
|
SESSION_MAX_AGE=1800
|
|
# Wie lange eine erneute Anmeldung fuer sensible Aktionen gilt (Sekunden).
|
|
REAUTH_MAX_AGE=300
|
|
# Login-Sperre: max. Fehlversuche pro Zeitfenster (Sekunden).
|
|
LOGIN_MAX_VERSUCHE=5
|
|
LOGIN_FENSTER_SEKUNDEN=900
|
|
LOGIN_SPERRE_SEKUNDEN=900
|
|
|
|
# Geheimnis fuer die Ersteinrichtung. OHNE DIESEN WERT LAESST SICH DER ERSTE
|
|
# ZUGANG NICHT ANLEGEN - das ist Absicht.
|
|
#
|
|
# Zwischen dem ersten Start und dem Anlegen des Zugangs stand die
|
|
# Einrichtungsseite sonst offen: Wer sie in diesem Fenster findet, wird
|
|
# Administrator. Erzeugen: npm run schluessel
|
|
ERSTEINRICHTUNG_GEHEIMNIS=
|
|
|
|
# Steht ein Reverse Proxy davor?
|
|
#
|
|
# Nur mit "true" wird "X-Forwarded-For" geglaubt - und dann von HINTEN
|
|
# gelesen, weil der vordere Teil der Liste vom Aufrufer selbst kommt.
|
|
# Ohne diese Zeile zaehlt die Anmeldesperre nur nach E-Mail-Adresse.
|
|
#
|
|
# Der dokumentierte Betrieb (Reverse Proxy davor) braucht sie also:
|
|
VERTRAUE_PROXY=true
|
|
# Bei mehreren gestaffelten Proxys deren Anzahl. Sonst weglassen.
|
|
# VERTRAUE_PROXY_STUFEN=1
|
|
|
|
# --- Objektspeicher (S3-kompatibel, EU!) ------------------------------------
|
|
# Wird ab Etappe 3 verwendet. Beispiel: Hetzner Object Storage, Falkenstein.
|
|
# ACHTUNG: Mit dem Anbieter muss ein AV-Vertrag nach Art. 28 DSGVO bestehen.
|
|
# Bleibt AUSKOMMENTIERT, solange das mitgelieferte MinIO benutzt wird.
|
|
#
|
|
# Die docker-compose.yml setzt dann von selbst http://minio:9000 - aber
|
|
# nur, wenn die Variable leer ist. Steht hier ein Wert, gewinnt er, und
|
|
# die Anwendung spricht mit einem fremden Host statt mit dem Speicher
|
|
# nebenan. Genau das ist am 31.08.2026 passiert: Jede Ablage scheiterte
|
|
# monatelang mit "NoSuchBucket", und die Zugangs-ID ging bei jedem Versuch
|
|
# nach draussen.
|
|
#
|
|
# Nur setzen, wenn ein EXTERNER Objektspeicher benutzt wird, z.B.:
|
|
# S3_ENDPOINT=https://fsn1.your-objectstorage.com
|
|
S3_REGION=eu-central
|
|
S3_BUCKET=betreuungs-cockpit
|
|
S3_ACCESS_KEY_ID=
|
|
S3_SECRET_ACCESS_KEY=
|
|
|
|
# Serverseitige Verschluesselung durch den Anbieter.
|
|
#
|
|
# Bleibt leer, und das ist die richtige Voreinstellung: Die Anwendung
|
|
# verschluesselt jede Datei selbst, bevor sie den Server verlaesst. Eine
|
|
# zweite Lage durch den Anbieter schuetzt vor nichts, was der eigene
|
|
# Umschlag nicht schon abdeckt.
|
|
#
|
|
# Das mitgelieferte MinIO kann sie ohnehin nicht - es laeuft ohne KMS und
|
|
# lehnt jede Ablage mit "NotImplemented" ab, sobald hier etwas steht.
|
|
#
|
|
# Nur setzen, wenn ein externer Anbieter sie ausdruecklich verlangt:
|
|
# S3_SSE=AES256
|
|
|
|
# --- E-Mail-Erinnerungen (optional, ab Etappe 2) ----------------------------
|
|
SMTP_HOST=
|
|
SMTP_PORT=587
|
|
SMTP_USER=
|
|
SMTP_PASSWORD=
|
|
SMTP_FROM="Betreuungs-Cockpit <cockpit@example.de>"
|
|
|
|
# --- Erstanmeldung ----------------------------------------------------------
|
|
# Wird nur vom Seed benutzt, um den ersten Betreuer-Zugang anzulegen.
|
|
SEED_ADMIN_EMAIL=
|
|
SEED_ADMIN_PASSWORT=
|