diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md index b5c6a2b..3d76501 100644 --- a/DEPLOYMENT.md +++ b/DEPLOYMENT.md @@ -51,10 +51,12 @@ Docker-Compose-Start ignoriert. Zusätzlich eine leere Datei für die automatisch generierten Admin-Zugangsdaten anlegen, da sie per Bind-Mount in den Container -eingebunden wird: +eingebunden wird. Der App-Container läuft als nicht-root-Nutzer – +damit er die Datei beschreiben darf, muss sie für alle schreibbar sein: ```bash touch ZUGANGSDATEN.md +chmod 666 ZUGANGSDATEN.md ``` ## 3. App starten @@ -176,6 +178,42 @@ docker compose exec db psql -U postgres -c "ALTER USER postgres WITH PASSWORD '< docker compose --env-file .env.local up -d ``` +### `Error: connect ECONNREFUSED ...:5432` beim Start + +Normal beim allerersten Start: Der App-Container versucht sich zu +verbinden, bevor PostgreSQL im `db`-Container fertig hochgefahren ist. +Dank `restart: unless-stopped` startet der App-Container automatisch +neu und verbindet sich, sobald die Datenbank bereit ist (kann ein paar +Sekunden bis wenige Minuten dauern). Mit `docker compose logs app -f` +verfolgen – taucht der Fehler dauerhaft (mehrere Minuten) weiter auf, +`docker compose ps` prüfen, ob der `db`-Container tatsächlich dauerhaft +läuft. + +### `EACCES: permission denied, open '/app/ZUGANGSDATEN.md'` + +Die Datei wurde ohne Schreibrecht für alle angelegt (Schritt 2 oben, +`chmod 666` fehlte). Der Admin-Benutzer wurde in diesem Fall trotzdem +in der Datenbank angelegt, nur die Zugangsdaten konnten nicht in die +Datei geschrieben werden – sie stehen dann stattdessen im Log +(`docker compose logs app` nach `bootstrap-admin – Admin-Passwort:` +durchsuchen). Für zukünftige Deployments zusätzlich die Berechtigung +korrigieren: + +```bash +chmod 666 ZUGANGSDATEN.md +``` + +Falls das Passwort auch im Log nicht mehr auffindbar ist (z. B. weil +Logs schon rotiert wurden), Admin-Konto neu anlegen lassen: + +```bash +docker compose exec db psql -U postgres -d canteen_menu -c "delete from users;" +chmod 666 ZUGANGSDATEN.md +docker compose restart app +docker compose logs app --tail 20 +cat ZUGANGSDATEN.md +``` + ## Updates einspielen ```bash diff --git a/scripts/bootstrap-admin.mjs b/scripts/bootstrap-admin.mjs index a0ffdc7..032614e 100644 --- a/scripts/bootstrap-admin.mjs +++ b/scripts/bootstrap-admin.mjs @@ -58,19 +58,36 @@ async function main() { [email, passwordHash] ); + // Der Admin-Datensatz steht ab hier in der Datenbank – das darf durch + // ein Problem beim Ablegen der Zugangsdaten nicht mehr verloren gehen + // (sonst gibt es einen Benutzer, dessen Passwort niemand kennt). + // appendFileSync() also bewusst nicht mehr ungefangen werfen lassen, + // sondern im Fehlerfall die Zugangsdaten direkt ins Log schreiben. const zugangsdatenPath = join( dirname(dirname(fileURLToPath(import.meta.url))), "ZUGANGSDATEN.md" ); const entry = `\n## Admin-Zugang (automatisch angelegt, ${new Date().toISOString().slice(0, 10)})\n\n- E-Mail: \`${email}\`\n- Passwort: \`${password}\`\n\nBitte nach dem ersten Login ändern.\n`; - if (existsSync(zugangsdatenPath)) { - appendFileSync(zugangsdatenPath, entry); + let wroteFile = false; + try { + if (existsSync(zugangsdatenPath)) { + appendFileSync(zugangsdatenPath, entry); + wroteFile = true; + } + } catch (err) { + console.warn(`bootstrap-admin – Konnte ${zugangsdatenPath} nicht beschreiben: ${err.message}`); + } + + if (wroteFile) { + console.log(`bootstrap-admin – Admin angelegt: ${email} (Passwort siehe ZUGANGSDATEN.md)`); } else { console.warn( - `bootstrap-admin – ${zugangsdatenPath} existiert nicht, Zugangsdaten werden nur geloggt:` + `bootstrap-admin – ${zugangsdatenPath} existiert nicht oder ist nicht beschreibbar. ` + + `Zugangsdaten NUR HIER im Log, bitte sofort notieren:` ); + console.log(`bootstrap-admin – Admin-E-Mail: ${email}`); + console.log(`bootstrap-admin – Admin-Passwort: ${password}`); } - console.log(`bootstrap-admin – Admin angelegt: ${email} (Passwort siehe ZUGANGSDATEN.md)`); } finally { await client.end(); }