Files
Jonas MenzelandClaude Opus 5 998d5867df
CI / backend (push) Successful in 2m33s
Images bauen / build (backend) (push) Successful in 3m45s
Images bauen / build (frontend) (push) Successful in 4m23s
CI / frontend (push) Successful in 6m38s
fix: stille Anmeldeschleife bei Secure-Cookie über HTTP erklären
Bei COOKIE_SECURE=true und Zugriff über HTTP verwirft der Browser das
Sitzungs-Cookie. Die Anmeldung selbst meldet Erfolg, die nächste Anfrage gilt
aber als nicht angemeldet – der Nutzer landet ohne jede Meldung wieder auf der
Anmeldemaske und hält es für ein falsches Passwort.

- Das Frontend prüft die Sitzung unmittelbar nach der Anmeldung und nennt bei
  einem Fehlschlag die Ursache samt beider Auswege
- Das Backend protokolliert dieselbe Kombination als Warnung und wertet dabei
  X-Forwarded-Proto aus, weil hinter einem Reverse Proxy immer http ankommt
- docs/deployment.md beschreibt das Symptom wörtlich

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014e7t8UpmoVNMtWivY5LiSH
2026-09-10 00:00:29 +02:00

258 lines
7.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Betrieb auf docker-srv001
## Erstinstallation
```bash
mkdir -p /opt/moneyfy && cd /opt/moneyfy
# docker-compose.yml und .env.example aus dem Repository holen
curl -fsSLO https://git.menzel.center/menzeljonas/moneyfy/raw/branch/main/docker-compose.yml
curl -fsSLO https://git.menzel.center/menzeljonas/moneyfy/raw/branch/main/.env.example
cp .env.example .env
```
In `.env` mindestens setzen:
```bash
POSTGRES_PASSWORD=$(openssl rand -hex 24)
SECRET_KEY=$(openssl rand -hex 32)
MONEYFY_ADMIN_PASSWORD=<Startpasswort>
PUBLIC_BASE_URL=https://moneyfy.menzel.center
TAG=latest
```
Das externe Proxy-Netz muss existieren NPMplus bringt es üblicherweise mit:
```bash
docker network inspect proxy >/dev/null 2>&1 || docker network create proxy
```
An der Registry anmelden und starten:
```bash
docker login git.menzel.center
docker compose up -d
docker compose logs -f moneyfy-backend
```
Das Backend wartet auf die Datenbank, spielt die Migrationen ein und legt beim
allerersten Start den Kategoriebaum an. Danach ist die Oberfläche unter
`http://127.0.0.1:8087` erreichbar.
Beim ersten Anmelden gelten `MONEYFY_ADMIN_USER` und `MONEYFY_ADMIN_PASSWORD`;
die Anwendung verlangt sofort ein neues Passwort. Danach kann
`MONEYFY_ADMIN_PASSWORD` aus der `.env` entfernt werden.
## NPMplus konfigurieren
`moneyfy.menzel.center` als **Proxy Host** anlegen:
| Feld | Wert |
|---|---|
| Domain Names | `moneyfy.menzel.center` |
| Scheme | `http` |
| Forward Hostname / IP | `moneyfy-frontend` |
| Forward Port | `8080` |
| Cache Assets | aus der Container setzt die Cache-Kopfzeilen selbst |
| Block Common Exploits | an |
| Websockets Support | aus die Anwendung braucht keine |
Unter *SSL*: Zertifikat über Let's Encrypt anfordern, **Force SSL** und **HTTP/2**
einschalten, **HSTS** aktivieren.
Damit NPMplus den Container über seinen Namen erreicht, müssen beide im Netz
`proxy` liegen. Das erledigt `docker-compose.yml` bereits; prüfen mit:
```bash
docker network inspect proxy --format '{{range .Containers}}{{.Name}} {{end}}'
```
Unter *Advanced* diese Zusatzkonfiguration eintragen. Sie sorgt dafür, dass die
Anwendung das richtige Schema sieht und Exporte nicht in einen Timeout laufen:
```nginx
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
client_max_body_size 4m;
proxy_read_timeout 120s;
```
> Die Anmeldung setzt `Secure`-Cookies. Ohne HTTPS also ohne Zugriff über
> NPMplus kommt keine Sitzung zustande. Für einen Test über
> `http://127.0.0.1:8087` muss `COOKIE_SECURE=false` gesetzt werden.
## Aktualisieren
Das Ausrollen passiert bewusst von Hand; die CI baut nur die Images.
```bash
cd /opt/moneyfy
# Bei fester Version: TAG in .env auf die neue Version setzen.
docker compose pull
docker compose up -d
docker compose logs -f moneyfy-backend
```
Die Migrationen laufen beim Start des Backends automatisch. Ein Blick in die
Ausgabe zeigt, welche Revision eingespielt wurde.
Zurückrollen: `TAG` auf die vorherige Version setzen und erneut
`docker compose up -d`. **Achtung:** Migrationen werden dabei nicht rückgängig
gemacht. Vor einem Update mit Schemaänderung immer erst sichern.
## Sicherung
Zwei Dinge müssen gesichert werden: die Datenbank und das Volume mit den Logos.
### Datenbank
```bash
docker compose exec -T moneyfy-db \
pg_dump -U moneyfy -d moneyfy --format=custom \
> /var/backups/moneyfy/db-$(date +%F).dump
```
Wiederherstellen:
```bash
docker compose stop moneyfy-backend
docker compose exec -T moneyfy-db \
pg_restore -U moneyfy -d moneyfy --clean --if-exists < /var/backups/moneyfy/db-2026-03-01.dump
docker compose start moneyfy-backend
```
### Logo-Volume
```bash
docker run --rm \
-v moneyfy-data:/data:ro \
-v /var/backups/moneyfy:/backup \
alpine tar czf /backup/logos-$(date +%F).tar.gz -C /data .
```
Wiederherstellen:
```bash
docker run --rm \
-v moneyfy-data:/data \
-v /var/backups/moneyfy:/backup \
alpine sh -c "rm -rf /data/* && tar xzf /backup/logos-2026-03-01.tar.gz -C /data"
```
Die Logos lassen sich zur Not auch neu beschaffen die Datenbank nicht.
### Tägliche Sicherung per Cron
`/opt/moneyfy/backup.sh`:
```bash
#!/bin/sh
set -eu
ZIEL=/var/backups/moneyfy
TAG=$(date +%F)
mkdir -p "$ZIEL"
cd /opt/moneyfy
docker compose exec -T moneyfy-db \
pg_dump -U moneyfy -d moneyfy --format=custom > "$ZIEL/db-$TAG.dump"
docker run --rm \
-v moneyfy-data:/data:ro \
-v "$ZIEL:/backup" \
alpine tar czf "/backup/logos-$TAG.tar.gz" -C /data .
# Älteres als 30 Tage entfernen.
find "$ZIEL" -name 'db-*.dump' -mtime +30 -delete
find "$ZIEL" -name 'logos-*.tar.gz' -mtime +30 -delete
```
```cron
30 3 * * * /opt/moneyfy/backup.sh >> /var/log/moneyfy-backup.log 2>&1
```
Die Sicherungen anschließend auf ein anderes System spiegeln eine Kopie auf
demselben Host hilft bei einem Plattenausfall nicht.
## Fehlersuche
**Backend startet nicht, Log endet bei „Warte auf die Datenbank“**
Die Datenbank ist nicht gesund. `docker compose ps` und
`docker compose logs moneyfy-db` prüfen; meist stimmt `POSTGRES_PASSWORD` in der
`.env` nicht mit dem im Volume hinterlegten Passwort überein. Ein bereits
angelegtes Volume übernimmt kein neues Passwort.
**`SECRET_KEY ist nicht gesetzt`**
Die Anwendung verweigert in Produktion den Start mit dem Platzhalterwert.
`openssl rand -hex 32` erzeugt einen passenden Schlüssel. Wird er später
geändert, sind alle Sitzungen ungültig das ist beabsichtigt.
**Anmeldung schlägt fehl**
Drei Ursachen kommen in Frage, in dieser Reihenfolge prüfen:
1. **Der Benutzer wurde mit einem anderen Passwort angelegt.** Die Erstanlage
greift nur, solange die Benutzertabelle leer ist. Wer `.env.example` zuerst
unverändert übernimmt und startet, bekommt einen Benutzer mit dem Platzhalter
ein späteres Ändern von `MONEYFY_ADMIN_PASSWORD` bleibt dann wirkungslos.
Abhilfe:
```bash
docker compose exec moneyfy-backend python -m app.scripts.reset_password \
--username admin --password "neues-passwort"
```
2. **Der Container kennt den neuen Wert noch nicht.** `docker compose restart`
behält die alte Umgebung. Nach einer Änderung an der `.env` muss der
Container neu erstellt werden:
```bash
docker compose up -d --force-recreate moneyfy-backend
docker compose exec moneyfy-backend printenv MONEYFY_ADMIN_PASSWORD
```
3. **Kein HTTPS.** Die Cookies sind `Secure` gesetzt; über eine reine
HTTP-Verbindung verwirft der Browser sie. Typisches Bild: **der Bildschirm
flackert kurz und die Anmeldemaske erscheint erneut, ohne Fehlermeldung.**
Seit 0.1.2 erklärt die Oberfläche das ausdrücklich, und im Log steht:
> `Anmeldung über … ohne HTTPS bei COOKIE_SECURE=true der Browser verwirft
> das Sitzungs-Cookie …`
Abhilfe: über NPMplus mit HTTPS zugreifen, oder für einen Test auf HTTP:
```bash
# in der .env
COOKIE_SECURE=false
```
```bash
# restart genügt nicht nur up -d übernimmt die geänderte Umgebung
docker compose up -d --force-recreate moneyfy-backend
```
Welcher Fall vorliegt, verrät das Log:
```bash
docker compose logs moneyfy-backend | grep -iE "administrator|MONEYFY_ADMIN"
```
**Firmen bekommen kein Logo**
Ohne Netzzugang findet nur der lokale Markenkatalog etwas; unbekannte Firmen
erhalten einen erzeugten Avatar. Das ist so gewollt. Mit
`docker compose exec moneyfy-backend python -c "from app.services.logos import simple_icon_index; print(simple_icon_index().version)"`
lässt sich prüfen, ob der Katalog im Image liegt.
**Keine Benachrichtigungen**
`SCHEDULER_ENABLED` und `NOTIFICATIONS_ENABLED` prüfen, dann in der Oberfläche
unter *Einstellungen → Benachrichtigungen* den Einrichtungsstand ansehen und
eine Testnachricht schicken. Das Versandprotokoll steht auf derselben Seite.
**Speicherplatz**
```bash
docker system df
docker compose exec moneyfy-db psql -U moneyfy -d moneyfy -c "\l+"
docker run --rm -v moneyfy-data:/data:ro alpine du -sh /data
```