8.9 KiB
Betrieb, Updates und Datensicherung
Voraussetzungen und Erststart
Docker Engine und Compose v2+, empfohlen mindestens 2 CPU-Kerne und 2 GB RAM (Builds benötigen zeitweise mehr). Unterstützt werden die von Node 24 und PostgreSQL 17 angebotenen Linux-Architekturen; der konkrete ARM64-Test ist im Prüfbericht vermerkt.
cp .env.example .env
openssl rand -hex 32
# Ergebnis als POSTGRES_PASSWORD in .env eintragen.
docker compose up -d --build
docker compose ps
docker compose logs --tail=100 app
docker compose exec app npm run admin:create -- deinname
Passwort wird interaktiv verborgen abgefragt. Der Benutzername besteht aus 3–80 Zeichen (a-z, 0-9, ., _, -); das Passwort hat 12–200 Zeichen. Doppelte Benutzernamen werden abgewiesen. Weitere Administratoren werden ebenfalls über dieses CLI angelegt. Über die CLI kann der Serverbetreiber neue Zugänge erstellen, wenn ein Passwort verloren geht.
App läuft als unprivilegierter Benutzer node, PID-1-Verwaltung über tini. PostgreSQL ist nur intern erreichbar. database und images sind persistente Named Volumes. Startup-Migrationen laufen in einer Transaktion unter einem PostgreSQL-Advisory-Lock. HTTP-Healthcheck prüft auch die Datenbankverbindung. Logs gehen nach stdout/stderr. docker compose down behält Daten; down -v löscht sie.
DATABASE_URL aus .env wird für lokale CLI/Entwicklung verwendet; Compose setzt die interne URL aus POSTGRES_PASSWORD zusammen. Deshalb ein URL-sicheres Passwort wählen (z. B. Hex). Der Wert CHANGE_ME muss ersetzt werden.
Adresse und Reverse Proxy
HOST_PORT=3000konfiguriert den Host-Port.APP_ORIGINist exakt die Browseradresse inklusive Scheme und ggf. Port, ohne Pfad; z. B.https://rezepte.example.org. Diese Einstellung ist für die Origin-basierte CSRF-Prüfung erforderlich.COOKIE_SECURE=truehinter HTTPS. Für ausschließlich lokales HTTPfalse.- Proxy muss
HostundX-Forwarded-Protokorrekt setzen; WebSocket-Unterstützung wird in Produktion nicht benötigt. TRUST_PROXY=truenur, wenn ausschließlich der vertrauenswürdige Proxy auf den App-Port zugreifen kann undX-Forwarded-Forüberschreibt, statt einen beliebigen Clientwert zu übernehmen. Ansonsten werden direkte Zugriffe in einem gemeinsamen IP-Limit zusammengefasst. Zusätzlich gilt immer ein benutzerbezogenes Limit.- Uploadlimit am Proxy mindestens 10 MB, Importanfragen maximal 2 MB nach JSON-Verpackung; sinnvoller Proxy-Gesamtgrenzwert 11 MB. App prüft die gelesenen Bytes selbst.
- Kein öffentliches Caching für
/admin,/api, dynamische HTML- oder RSC-Antworten. Bilder sind content-addressed-artig per zufälligem Dateinamen versioniert und dürfen langfristig gecacht werden. - HSTS nach erfolgreicher HTTPS-Einrichtung am vorhandenen Proxy setzen. Keine spezielle Proxysoftware erforderlich.
Session-Cookie: HTTP-only, SameSite Strict, 7 Tage absolute Gültigkeit, optional Secure. Datenbank enthält ausschließlich den SHA-256-Hash des zufälligen 256-Bit-Tokens. Passwortwechsel widerruft alle bisherigen Sessions. Origin-Prüfung gilt auch für Login und Uploads.
Admin-2FA und Mail
In .env ADMIN_EMAIL auf die Admin-Adresse setzen. Mit openssl rand -hex 32 einen separaten, dauerhaften AUTH_ENCRYPTION_KEY erzeugen und ebenfalls eintragen. Nach Änderungen docker compose up -d app ausführen. Der Schlüssel verschlüsselt Authenticator-Geheimnisse und SMTP-Passwörter mit AES-256-GCM; er darf bei Updates nicht neu erzeugt werden und gehört in das geschützte Konfigurationsbackup. Ohne den ursprünglichen Schlüssel lassen sich vorhandene Geheimnisse nicht entschlüsseln.
Unter Administration → Einstellungen → Zwei-Faktor-Anmeldung das aktuelle Passwort eingeben, QR-Code mit einer TOTP-App scannen und den sechsstelligen Code bestätigen. Erst dann wird 2FA aktiviert. Die zehn Wiederherstellungscodes werden nur einmal angezeigt; herunterladen und sicher aufbewahren. Jeder Code ersetzt einmal den App-Code. Neue Codes machen die bisherigen ungültig. Aktivierung, Deaktivierung und Code-Neugenerierung beenden andere Sitzungen. Für sicherheitsrelevante Änderungen werden Passwort und bei aktiver 2FA ein frischer App- oder Wiederherstellungscode benötigt.
Nach der Passwort-Anmeldung gilt die zweite Stufe fünf Minuten und erlaubt höchstens fünf Fehlversuche. App-Codes gelten im 30-Sekunden-Takt mit einer Periode Toleranz und können nur einmal verwendet werden. Server und Smartphone sollten die Uhrzeit automatisch synchronisieren. Bei Verlust des Telefons einen Wiederherstellungscode verwenden; sind beide verloren, kann der Serverbetreiber über das bestehende Admin-CLI einen weiteren Zugang anlegen.
Unter Mail & Benachrichtigungen Admin-Adresse, SMTP-Host, Port, TLS-Verfahren, Benutzername, Passwort und Absender hinterlegen. Unterstützt werden implizites TLS (üblicherweise 465) und verpflichtendes STARTTLS (üblicherweise 587). Leeres SMTP-Passwort behält das gespeicherte Passwort bei; zum Löschen dient die eigene Checkbox. Anschließend speichern und Testmail senden. Die Option E-Mail bei erfolgreicher Anmeldung aktiviert Login-Benachrichtigungen. Ein Versandfehler sperrt die Anmeldung nicht; der Status ist im Loginverlauf sichtbar.
Benachrichtigungen enthalten Zeitpunkt (UTC), gemeldete IP-Adresse und User-Agent, keine geografische Ortung. Ohne TRUST_PROXY=true werden Proxy-IP-Angaben ausdrücklich als nicht verifiziert gekennzeichnet. Die rechte Adresse aus X-Forwarded-For wird verwendet; die oben beschriebenen Proxy-Voraussetzungen bleiben erforderlich. Der Loginverlauf speichert erfolgreiche Anmeldungen für bis zu 90 Tage (Bereinigung bei der nächsten Anmeldung), angezeigt werden die letzten 20. SMTP-Zugang und 2FA-Geheimnisse werden nicht über die Einstellungs-API zurückgegeben.
Backup
Ein konsistentes Backup umfasst Datenbank und Bilder. Für ein kleines Haushaltskochbuch ist eine kurze Schreibpause am einfachsten:
mkdir -p backups
docker compose stop app
docker compose exec -T db pg_dump -U hamham -d hamham -Fc > backups/hamham.dump
docker compose run --rm --no-deps --entrypoint tar app -C /app/uploads -czf - . > backups/images.tar.gz
docker compose start app
Zusätzlich .env sicher und separat sichern. Dumps enthalten Passwort-Hashes und aktive Session-Hashes und sind vertraulich. Backups verschlüsselt außerhalb des Hosts aufbewahren, regelmäßig rotieren und Restore testen. JSON-Export ist ein portables Rezeptformat, aber ersetzt kein vollständiges Backup (keine Bildbytes oder Authentifizierungsdaten).
Restore
Auf einem Host mit kompatiblem Release und korrekter .env:
docker compose up -d db
docker compose stop app
docker compose exec -T db pg_restore -U hamham -d hamham --clean --if-exists < backups/hamham.dump
docker compose run --rm -T --no-deps --entrypoint tar app -C /app/uploads -xzf - < backups/images.tar.gz
docker compose exec -T db psql -U hamham -d hamham -c 'DELETE FROM sessions;'
docker compose up -d app
Vor dem Restore auf bereits benutzten Volumes alte Bilddateien bei Bedarf in ein separates Archiv verschieben. Keine nicht zugeordneten fremden Daten löschen. Anschließend Anmeldung, Bilder, Rezeptzahl und /api/health kontrollieren.
Update und Migrationen
- Releasehinweise lesen, Backup erstellen.
git pull --ff-onlyauf dem gewünschten Release-Branch.docker compose build --pull app.docker compose up -d.docker compose logs --tail=100 appund Healthchecks prüfen.
Migrationen sind nummerierte, unveränderliche SQL-Dateien in migrations/. Bereits angewendete Namen stehen in migrations. Neue Migrationen müssen vor Auslieferung auf leerer Datenbank und einer Kopie vorhandener Daten getestet werden. Schemaänderungen möglichst additiv und abwärtskompatibel. Kein automatisches destruktives Downgrade: für inkompatible Rückkehr vorheriges Image plus dazugehöriges Datenbank-/Bildbackup wiederherstellen.
Offline und Timer
Die PWA cached lokale statische Ressourcen und online geöffnete, veröffentlichte Rezept-/Kochseiten. Auch nach clientseitiger Navigation wird eine vollständige Dokumentfassung für die Offline-Nutzung gespeichert. Bereits besuchte öffentliche Listenansichten werden ebenfalls gesichert. Nicht besuchte Seiten zeigen eine klare Offline-Ansicht. Admin- und API-Antworten werden vom Service Worker nicht gecacht. Browser können Cachedateien aus Platzgründen entfernen; offline ist deshalb eine Komfortfunktion, kein Verfügbarkeitsversprechen. Für einen zuverlässigen Kochabend die benötigte Kochseite vorab online öffnen.
Timer speichern absolute Endzeiten und korrigieren ihren Stand nach Navigation, Schlafmodus und Reload. Signalton benötigt eine Nutzeraktion („Ton an“); Betriebssysteme können Hintergrundseiten und Audio pausieren. Für zeitkritische Vorgänge zusätzlich einen Geräte-/Küchentimer verwenden. Wake Lock ist eine progressive Browserfunktion und wird im UI mit seinem tatsächlichen Status angezeigt.