# 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= 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 ```