Files
moneyfy/docs/deployment.md
T
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

7.8 KiB
Raw Blame History

Betrieb auf docker-srv001

Erstinstallation

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:

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:

docker network inspect proxy >/dev/null 2>&1 || docker network create proxy

An der Registry anmelden und starten:

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:

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:

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.

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

docker compose exec -T moneyfy-db \
  pg_dump -U moneyfy -d moneyfy --format=custom \
  > /var/backups/moneyfy/db-$(date +%F).dump

Wiederherstellen:

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

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:

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:

#!/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
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:

    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:

    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:

    # in der .env
    COOKIE_SECURE=false
    
    # 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:

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

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