- Mehrstufige Dockerfiles je Dienst mit Stufen für Entwicklung und Betrieb, beide Images laufen als unprivilegierter Benutzer - Backend-Entrypoint wartet auf die Datenbank, migriert und seedt nur bei leerem Kategoriebaum (neues Flag --if-empty) - docker-compose.yml mit Netz-Trennung, Healthchecks und benannten Volumes; die Datenbank ist ausschließlich im internen Netz erreichbar - nginx liefert das Bundle aus und reicht /api weiter; index.html ungecacht, gehashte Assets ein Jahr - Gitea-Workflows: ci.yml für Lint, Tests und Bundle-Bau, build.yml für die Images nach linux/amd64 ohne Deploy-Schritt - docs/runner.md und docs/deployment.md, .dockerignore je Dienst Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014e7t8UpmoVNMtWivY5LiSH
6.4 KiB
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 überhttp://127.0.0.1:8087mussCOOKIE_SECURE=falsegesetzt 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, obwohl das Passwort stimmt
Meist fehlt HTTPS: Die Cookies sind Secure gesetzt und erreichen den Server
über eine reine HTTP-Verbindung nicht. Entweder über NPMplus zugreifen oder
COOKIE_SECURE=false setzen.
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