feat: Phase 2 – Budget-Engine + Direktzugriff (http://IP:Port)
Budget: - Modelle + Migration 0003: budget_template_lines, planned_income_lines, budget_periods, budget_period_lines. - services/budget: Perioden-Grenzen (einstellbarer Starttag, Label nach Endmonat), Standard-Vorlage vs. Monats-Override (Snapshot-on-Customize), Soll/Ist inkl. budgetierter Sparen-Transfers, geplante Einnahmen (Soll/Ist). - routers/budgets: Vorlage, geplante Einnahmen (CRUD), Monats-Soll/Ist, Monats-Override, Zurücksetzen. pytest: Perioden, Soll/Ist, Override/Reset, Einnahmen. - Frontend: Budget-Seite (Monat + Standard-Budget), Fortschrittsbalken grün/rot, Monats-Navigation, editierbare Soll-Beträge; Sparen-Option im Transfer-Formular. Deployment-Fix (Nutzer-Anforderung: http://IP:Port muss funktionieren): - Dienst bindet an APP_BIND_HOST=0.0.0.0 (direkt im LAN erreichbar). - APP_COOKIE_SECURE=false als Standard (sonst kein Login über reines HTTP); für reinen HTTPS-Betrieb umstellbar. Doku + install.sh entsprechend angepasst. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+14
-4
@@ -15,9 +15,17 @@ erzeugt `/etc/certain-finance/env` (mit Zufallsgeheimnissen), legt den systemd-
|
||||
Dienst `certain-finance` an und startet ihn. Node wird **nur zum Bauen** gebraucht;
|
||||
der laufende Dienst ist reines Python.
|
||||
|
||||
## Nginx Proxy Manager
|
||||
## Direktzugriff (http://IP:Port)
|
||||
|
||||
Neuen **Proxy Host** anlegen:
|
||||
Standardmäßig lauscht der Dienst auf `0.0.0.0:<APP_PORT>` (Standard-Port `8071`) und
|
||||
ist damit direkt im LAN erreichbar: `http://<LXC-IP>:8071`. Dafür ist
|
||||
`APP_COOKIE_SECURE=false` gesetzt (sonst speichert der Browser die Sitzung über
|
||||
reines HTTP nicht). Möchtest du den Zugriff auf einen Reverse-Proxy **auf demselben
|
||||
Host** beschränken, setze `APP_BIND_HOST=127.0.0.1` in `/etc/certain-finance/env`.
|
||||
|
||||
## Optional: HTTPS über Nginx Proxy Manager
|
||||
|
||||
Wenn du von außen per HTTPS zugreifen willst, einen **Proxy Host** anlegen:
|
||||
|
||||
- **Domain Names:** deine (Sub-)Domain
|
||||
- **Scheme:** `http`
|
||||
@@ -30,8 +38,10 @@ Neuen **Proxy Host** anlegen:
|
||||
Für spätere CSV-/PDF-Uploads in den *Advanced*-Einstellungen des Hosts
|
||||
`client_max_body_size 20m;` setzen.
|
||||
|
||||
Da HTTPS extern terminiert, sind die Sitzungs-Cookies `Secure`
|
||||
(`APP_COOKIE_SECURE=true`). Der Dienst selbst lauscht nur auf `127.0.0.1`.
|
||||
Bei ausschließlichem HTTPS-Zugriff kannst du `APP_COOKIE_SECURE=true` in
|
||||
`/etc/certain-finance/env` setzen (danach `systemctl restart certain-finance`) –
|
||||
dann werden die Sitzungs-Cookies nur über HTTPS gesendet. Für gemischten Zugriff
|
||||
(HTTP im LAN **und** HTTPS von außen) belasse es bei `false`.
|
||||
|
||||
## Betrieb
|
||||
|
||||
|
||||
@@ -14,9 +14,10 @@ User=certain-finance
|
||||
Group=certain-finance
|
||||
WorkingDirectory=/opt/certain-finance/backend
|
||||
EnvironmentFile=/etc/certain-finance/env
|
||||
# Der Port kommt aus der EnvironmentFile (APP_PORT). Nur an 127.0.0.1 gebunden –
|
||||
# von außen ist der Dienst ausschließlich über den Nginx Proxy Manager erreichbar.
|
||||
ExecStart=/opt/certain-finance/backend/.venv/bin/uvicorn app.main:app --host 127.0.0.1 --port ${APP_PORT}
|
||||
# Adresse/Port kommen aus der EnvironmentFile. APP_BIND_HOST=0.0.0.0 macht den
|
||||
# Dienst direkt über http://<LXC-IP>:<APP_PORT> erreichbar; 127.0.0.1 beschränkt
|
||||
# ihn auf einen Reverse-Proxy auf demselben Host.
|
||||
ExecStart=/opt/certain-finance/backend/.venv/bin/uvicorn app.main:app --host ${APP_BIND_HOST} --port ${APP_PORT}
|
||||
Restart=on-failure
|
||||
RestartSec=3
|
||||
|
||||
|
||||
+10
-4
@@ -5,15 +5,21 @@
|
||||
# Ablageort für SQLite-Datenbank und Backups (muss dem Dienst-Benutzer gehören).
|
||||
APP_DATA_DIR=/var/lib/certain-finance
|
||||
|
||||
# Interner Port, auf dem der Dienst lauscht. Der Nginx Proxy Manager leitet
|
||||
# von außen (HTTPS) hierher weiter. Nur an 127.0.0.1 gebunden (siehe Unit).
|
||||
# Adresse + Port, auf denen der Dienst lauscht.
|
||||
# APP_BIND_HOST=0.0.0.0 macht die Web-UI direkt über http://<LXC-IP>:<APP_PORT>
|
||||
# im LAN erreichbar. Willst du NUR über einen Reverse-Proxy auf DEMSELBEN Host
|
||||
# zugreifen, setze 127.0.0.1.
|
||||
APP_BIND_HOST=0.0.0.0
|
||||
APP_PORT=8071
|
||||
|
||||
# Signiert/HMACt Sitzungen. UNBEDINGT zufällig setzen (install.sh macht das).
|
||||
APP_SESSION_SECRET=change-me-please
|
||||
|
||||
# Cookies nur über HTTPS senden. Hinter dem Nginx Proxy Manager: true.
|
||||
APP_COOKIE_SECURE=true
|
||||
# Cookies nur über HTTPS senden. Bei direktem HTTP-Zugriff (http://IP:Port) MUSS
|
||||
# das false sein, sonst speichert der Browser die Sitzung nicht (Login klappt dann
|
||||
# scheinbar, springt aber sofort zurück). Nur wenn du ausschließlich über HTTPS
|
||||
# zugreifst (z. B. Nginx Proxy Manager mit erzwungenem SSL), kannst du true setzen.
|
||||
APP_COOKIE_SECURE=false
|
||||
|
||||
# Erster Admin – wird NUR beim allerersten Start angelegt (wenn noch kein Nutzer da ist).
|
||||
APP_ADMIN_USERNAME=admin
|
||||
|
||||
+13
-8
@@ -95,6 +95,8 @@ if [[ -f "$ENV_FILE" ]]; then
|
||||
else
|
||||
echo "APP_GIT_SHA=$GIT_SHA" >> "$ENV_FILE"
|
||||
fi
|
||||
# Direktzugriff (http://IP:Port) für ältere Konfigurationen nachrüsten.
|
||||
grep -q '^APP_BIND_HOST=' "$ENV_FILE" || echo "APP_BIND_HOST=0.0.0.0" >> "$ENV_FILE"
|
||||
ADMIN_USER="$(grep -E '^APP_ADMIN_USERNAME=' "$ENV_FILE" | cut -d= -f2-)"
|
||||
GENERATED_PASS=""
|
||||
else
|
||||
@@ -110,9 +112,10 @@ else
|
||||
info "Erzeuge Konfiguration: $ENV_FILE"
|
||||
cat > "$ENV_FILE" <<EOF
|
||||
APP_DATA_DIR=$DATA_DIR
|
||||
APP_BIND_HOST=0.0.0.0
|
||||
APP_PORT=$local_port
|
||||
APP_SESSION_SECRET=$(rand 48)
|
||||
APP_COOKIE_SECURE=true
|
||||
APP_COOKIE_SECURE=false
|
||||
APP_ADMIN_USERNAME=$admin_user
|
||||
APP_ADMIN_PASSWORD=$admin_pass
|
||||
APP_DEFAULT_BASE_CURRENCY=EUR
|
||||
@@ -139,7 +142,7 @@ User=$SERVICE_USER
|
||||
Group=$SERVICE_USER
|
||||
WorkingDirectory=$REPO_DIR/backend
|
||||
EnvironmentFile=$ENV_FILE
|
||||
ExecStart=$REPO_DIR/backend/.venv/bin/uvicorn app.main:app --host 127.0.0.1 --port \${APP_PORT}
|
||||
ExecStart=$REPO_DIR/backend/.venv/bin/uvicorn app.main:app --host \${APP_BIND_HOST} --port \${APP_PORT}
|
||||
Restart=on-failure
|
||||
RestartSec=3
|
||||
NoNewPrivileges=true
|
||||
@@ -167,24 +170,26 @@ for _ in $(seq 1 30); do
|
||||
sleep 2
|
||||
done
|
||||
|
||||
LAN_IP="$(hostname -I 2>/dev/null | awk '{print $1}')"
|
||||
|
||||
echo
|
||||
if [[ "$ok" -eq 1 ]]; then
|
||||
info "Fertig – Certain Finance läuft. 🎉"
|
||||
else
|
||||
warn "Backend antwortet noch nicht. Logs: journalctl -u $APP_SLUG -e"
|
||||
fi
|
||||
echo " Interner Dienst: http://127.0.0.1:$PORT (nur lokal)"
|
||||
echo " Web-UI (direkt): http://${LAN_IP:-<LXC-IP>}:$PORT"
|
||||
echo " Admin-Login: ${ADMIN_USER:-admin}"
|
||||
if [[ -n "${GENERATED_PASS:-}" ]]; then
|
||||
echo " Admin-Passwort: ${GENERATED_PASS}"
|
||||
warn "Bitte dieses Passwort notieren – es wird nicht erneut angezeigt."
|
||||
fi
|
||||
echo
|
||||
echo " Nginx Proxy Manager: neuen Proxy-Host anlegen ->"
|
||||
echo " Forward Hostname/IP: <IP-dieses-LXC>"
|
||||
echo " Forward Port: $PORT"
|
||||
echo " SSL: Let's Encrypt aktivieren; 'Block Common Exploits' ok."
|
||||
echo " (Websockets nicht nötig. Für spätere Uploads client_max_body_size >= 20M.)"
|
||||
echo " Optional über HTTPS (Nginx Proxy Manager): neuen Proxy-Host ->"
|
||||
echo " Forward Hostname/IP: ${LAN_IP:-<LXC-IP>}"
|
||||
echo " Forward Port: $PORT (Scheme: http)"
|
||||
echo " SSL: Let's Encrypt aktivieren. Dann in $ENV_FILE APP_COOKIE_SECURE=true"
|
||||
echo " setzen und 'systemctl restart $APP_SLUG'. (Uploads: client_max_body_size >= 20M.)"
|
||||
echo
|
||||
echo " Logs: journalctl -u $APP_SLUG -f"
|
||||
echo " Neustart: systemctl restart $APP_SLUG"
|
||||
|
||||
Reference in New Issue
Block a user