Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
11e514dd25 |
@@ -17,6 +17,15 @@ und dieses Projekt folgt [Semantic Versioning](https://semver.org/lang/de/).
|
|||||||
|
|
||||||
### Sicherheit
|
### Sicherheit
|
||||||
|
|
||||||
|
## [0.20.0] – 2026-10-03
|
||||||
|
|
||||||
|
### Hinzugefügt
|
||||||
|
- `deploy/update.sh` und `deploy/backup.sh` erkennen die Installationsart selbst und beherrschen jetzt auch die Installation als Dienst (Node und PostgreSQL direkt im Container) – nicht mehr nur Docker (#031)
|
||||||
|
- Eine fehlgeschlagene Sicherung bricht die Aktualisierung ab, bevor etwas verändert wird (#031)
|
||||||
|
|
||||||
|
### Behoben
|
||||||
|
- Die Zustandsprüfung des Web-Containers konnte nie gelingen: Next bindet im Standalone-Modus an die Adresse aus `HOSTNAME`, und Docker setzt dort den Containernamen – der Server lauschte nur auf der Container-IP. `web` blieb dauerhaft auf „health: starting“ (#031)
|
||||||
|
|
||||||
## [0.19.2] – 2026-10-03
|
## [0.19.2] – 2026-10-03
|
||||||
|
|
||||||
### Sicherheit
|
### Sicherheit
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## Zeitübersicht
|
## Zeitübersicht
|
||||||
|
|
||||||
**Gesamt:** 15 h 23 min
|
**Gesamt:** 16 h 08 min
|
||||||
|
|
||||||
| Issue | Zeit |
|
| Issue | Zeit |
|
||||||
|---|---|
|
|---|---|
|
||||||
@@ -36,6 +36,7 @@
|
|||||||
| #028 Passkeys | 0 h 45 min |
|
| #028 Passkeys | 0 h 45 min |
|
||||||
| #029 Einrichtungsdokumentation | 0 h 40 min |
|
| #029 Einrichtungsdokumentation | 0 h 40 min |
|
||||||
| #030 netbird Reverse Proxy | 0 h 20 min |
|
| #030 netbird Reverse Proxy | 0 h 20 min |
|
||||||
|
| #031 Update für beide Varianten | 0 h 45 min |
|
||||||
|
|
||||||
| Meilenstein | Zeit |
|
| Meilenstein | Zeit |
|
||||||
|---|---|
|
|---|---|
|
||||||
@@ -58,7 +59,7 @@
|
|||||||
|
|
||||||
## 2026-09-17 · Sitzung 1 · 19:36–laufend
|
## 2026-09-17 · Sitzung 1 · 19:36–laufend
|
||||||
**Issue:** #001–#007 (Meilensteine v0.1.0 bis v0.4.0)
|
**Issue:** #001–#007 (Meilensteine v0.1.0 bis v0.4.0)
|
||||||
**Version:** 0.19.2
|
**Version:** 0.20.0
|
||||||
|
|
||||||
### Erledigt
|
### Erledigt
|
||||||
- Auftrag gelesen, Rückfragen gestellt
|
- Auftrag gelesen, Rückfragen gestellt
|
||||||
@@ -169,6 +170,9 @@
|
|||||||
- `npm audit` vor der Freigabe erneut laufen lassen: In den zwei Wochen seit dem letzten Stand kam eine kritische Meldung zu Next.js dazu (RCE in `next/og`). Wir nutzen `next/og` nicht, waren also nicht angreifbar – angehoben auf 16.3.8, Tests und Build grün
|
- `npm audit` vor der Freigabe erneut laufen lassen: In den zwei Wochen seit dem letzten Stand kam eine kritische Meldung zu Next.js dazu (RCE in `next/og`). Wir nutzen `next/og` nicht, waren also nicht angreifbar – angehoben auf 16.3.8, Tests und Build grün
|
||||||
- Lehre für den Betrieb: Vor jedem Produktivgang und danach regelmäßig `npm audit` prüfen, nicht nur bei Änderungen am Code
|
- Lehre für den Betrieb: Vor jedem Produktivgang und danach regelmäßig `npm audit` prüfen, nicht nur bei Änderungen am Code
|
||||||
|
|
||||||
|
- Update- und Sicherungsskript für beide Installationsarten (#031). Beim Durchspielen zwei Fehler gefunden: Die Zustandsprüfung des Web-Containers konnte nie gelingen (Next bindet an `HOSTNAME`, Docker setzt dort den Containernamen), und eine fehlgeschlagene Sicherung hielt die Aktualisierung nicht auf
|
||||||
|
- Lehre: Ein Skript, das nie unter echten Bedingungen gelaufen ist, ist eine Behauptung. Erst der Durchlauf gegen einen laufenden Stapel hat beide Fehler gezeigt
|
||||||
|
|
||||||
### Nächster Schritt
|
### Nächster Schritt
|
||||||
- #016 Benutzerhandbuch mit Screenshots, danach #017 Favicons und #019 CI-Pipeline
|
- #016 Benutzerhandbuch mit Screenshots, danach #017 Favicons und #019 CI-Pipeline
|
||||||
- Für 1.0.0 fehlt noch: PMG (kein Host verfügbar) und der Fall „aktive Subscription auf PBS“ (#023)
|
- Für 1.0.0 fehlt noch: PMG (kein Host verfügbar) und der Fall „aktive Subscription auf PBS“ (#023)
|
||||||
|
|||||||
@@ -24,6 +24,9 @@ RUN npx prisma generate \
|
|||||||
FROM basis AS laufzeit
|
FROM basis AS laufzeit
|
||||||
ENV NODE_ENV=production
|
ENV NODE_ENV=production
|
||||||
ENV PORT=3000
|
ENV PORT=3000
|
||||||
|
# Ohne diese Zeile nimmt Next den von Docker gesetzten HOSTNAME als Bindeadresse und lauscht
|
||||||
|
# nur auf der Container-IP. Die Zustandsprüfung über 127.0.0.1 schlägt dann immer fehl.
|
||||||
|
ENV HOSTNAME=0.0.0.0
|
||||||
|
|
||||||
RUN addgroup -g 1001 -S proxledger && adduser -S proxledger -u 1001 -G proxledger
|
RUN addgroup -g 1001 -S proxledger && adduser -S proxledger -u 1001 -G proxledger
|
||||||
|
|
||||||
|
|||||||
+37
-3
@@ -1,5 +1,6 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Sichert Datenbank und hochgeladene PDFs von ProxLedger.
|
# Sichert Datenbank, hochgeladene PDFs und die Konfiguration von ProxLedger.
|
||||||
|
# Erkennt selbst, ob die Installation mit Docker oder als Dienst im Container läuft.
|
||||||
#
|
#
|
||||||
# ./backup.sh /pfad/zum/sicherungsordner
|
# ./backup.sh /pfad/zum/sicherungsordner
|
||||||
#
|
#
|
||||||
@@ -13,17 +14,50 @@ set -o pipefail
|
|||||||
ZIEL="${1:-/var/backups/proxledger}"
|
ZIEL="${1:-/var/backups/proxledger}"
|
||||||
AUFBEWAHRUNG_TAGE="${AUFBEWAHRUNG_TAGE:-30}"
|
AUFBEWAHRUNG_TAGE="${AUFBEWAHRUNG_TAGE:-30}"
|
||||||
STAND=$(date +%Y%m%d-%H%M%S)
|
STAND=$(date +%Y%m%d-%H%M%S)
|
||||||
COMPOSE_VERZEICHNIS="${COMPOSE_VERZEICHNIS:-/opt/proxledger}"
|
VERZEICHNIS="${COMPOSE_VERZEICHNIS:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}"
|
||||||
|
|
||||||
mkdir -p "$ZIEL"
|
mkdir -p "$ZIEL"
|
||||||
cd "$COMPOSE_VERZEICHNIS"
|
cd "$VERZEICHNIS"
|
||||||
|
|
||||||
|
# Siehe deploy/update.sh – der Dienst ist das eindeutigere Merkmal.
|
||||||
|
if systemctl cat proxledger.service >/dev/null 2>&1; then
|
||||||
|
ART="dienst"
|
||||||
|
else
|
||||||
|
ART="docker"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Sichere ProxLedger (${ART}) nach ${ZIEL} …"
|
||||||
|
|
||||||
|
if [ "$ART" = "docker" ]; then
|
||||||
echo "Sichere Datenbank …"
|
echo "Sichere Datenbank …"
|
||||||
docker compose exec -T postgres pg_dump -U "${POSTGRES_USER:-proxledger}" "${POSTGRES_DB:-proxledger}" \
|
docker compose exec -T postgres pg_dump -U "${POSTGRES_USER:-proxledger}" "${POSTGRES_DB:-proxledger}" \
|
||||||
| gzip > "${ZIEL}/datenbank-${STAND}.sql.gz"
|
| gzip > "${ZIEL}/datenbank-${STAND}.sql.gz"
|
||||||
|
|
||||||
echo "Sichere hochgeladene Dateien …"
|
echo "Sichere hochgeladene Dateien …"
|
||||||
docker compose run --rm -T --entrypoint tar web -czf - /data/uploads > "${ZIEL}/uploads-${STAND}.tar.gz" 2>/dev/null || true
|
docker compose run --rm -T --entrypoint tar web -czf - /data/uploads > "${ZIEL}/uploads-${STAND}.tar.gz" 2>/dev/null || true
|
||||||
|
else
|
||||||
|
# DATABASE_URL steht in der .env; pg_dump versteht sie direkt.
|
||||||
|
# shellcheck disable=SC1091
|
||||||
|
set -o allexport
|
||||||
|
. ./.env
|
||||||
|
set +o allexport
|
||||||
|
|
||||||
|
[ -n "${DATABASE_URL:-}" ] || {
|
||||||
|
echo "DATABASE_URL fehlt in der .env – ohne sie keine Sicherung." >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "Sichere Datenbank …"
|
||||||
|
pg_dump "$DATABASE_URL" | gzip > "${ZIEL}/datenbank-${STAND}.sql.gz"
|
||||||
|
|
||||||
|
echo "Sichere hochgeladene Dateien …"
|
||||||
|
UPLOADS="${UPLOAD_DIR:-${VERZEICHNIS}/data/uploads}"
|
||||||
|
if [ -d "$UPLOADS" ]; then
|
||||||
|
tar -czf "${ZIEL}/uploads-${STAND}.tar.gz" -C "$(dirname "$UPLOADS")" "$(basename "$UPLOADS")"
|
||||||
|
else
|
||||||
|
echo " (kein Upload-Verzeichnis unter ${UPLOADS})"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
echo "Sichere Konfiguration …"
|
echo "Sichere Konfiguration …"
|
||||||
cp .env "${ZIEL}/env-${STAND}.txt"
|
cp .env "${ZIEL}/env-${STAND}.txt"
|
||||||
|
|||||||
@@ -181,4 +181,5 @@ printf ' 3. Für den Betrieb über HTTPS einen Reverse Proxy davorsetzen (Beisp
|
|||||||
echo
|
echo
|
||||||
gelb "APP_URL in /opt/proxledger/.env auf die endgültige Adresse setzen, sobald der Reverse Proxy steht."
|
gelb "APP_URL in /opt/proxledger/.env auf die endgültige Adresse setzen, sobald der Reverse Proxy steht."
|
||||||
printf ' Logs ansehen: pct exec %s -- docker compose -f /opt/proxledger/docker-compose.yml logs -f\n' "$CTID"
|
printf ' Logs ansehen: pct exec %s -- docker compose -f /opt/proxledger/docker-compose.yml logs -f\n' "$CTID"
|
||||||
printf ' Aktualisieren: pct exec %s -- bash -c "cd /opt/proxledger && git pull && docker compose up -d --build"\n' "$CTID"
|
printf ' Aktualisieren: pct exec %s -- bash -c "bash /opt/proxledger/deploy/update.sh"\n' "$CTID"
|
||||||
|
printf ' Sichern: pct exec %s -- bash -c "bash /opt/proxledger/deploy/backup.sh /var/backups/proxledger"\n' "$CTID"
|
||||||
|
|||||||
+78
-10
@@ -1,7 +1,8 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# ProxLedger aktualisieren (Docker-Installation).
|
# ProxLedger aktualisieren – erkennt selbst, ob die Installation mit Docker
|
||||||
|
# oder als Dienst im Container (Node + PostgreSQL direkt) läuft.
|
||||||
#
|
#
|
||||||
# bash deploy/update.sh # Quelltext holen, neu bauen, migrieren, neu starten
|
# bash deploy/update.sh # sichern, holen, bauen, migrieren, neu starten
|
||||||
# bash deploy/update.sh --ohne-sicherung
|
# bash deploy/update.sh --ohne-sicherung
|
||||||
#
|
#
|
||||||
# Vor dem Aktualisieren wird gesichert – das dauert Sekunden und erspart schlechte Abende.
|
# Vor dem Aktualisieren wird gesichert – das dauert Sekunden und erspart schlechte Abende.
|
||||||
@@ -23,20 +24,53 @@ fehler() {
|
|||||||
SICHERN="ja"
|
SICHERN="ja"
|
||||||
[ "${1:-}" = "--ohne-sicherung" ] && SICHERN="nein"
|
[ "${1:-}" = "--ohne-sicherung" ] && SICHERN="nein"
|
||||||
|
|
||||||
command -v docker >/dev/null 2>&1 || fehler "Docker nicht gefunden."
|
# Wohin gesichert wird. Der Standardort gehört root; wer anders arbeitet, setzt SICHERUNG_ZIEL.
|
||||||
[ -f .env ] || fehler "Keine .env gefunden – wird dieses Skript im richtigen Verzeichnis ausgeführt?"
|
SICHERUNG_ZIEL="${SICHERUNG_ZIEL:-/var/backups/proxledger}"
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------- Art der Installation
|
||||||
|
#
|
||||||
|
# Der systemd-Dienst ist das eindeutigere Merkmal: Die docker-compose.yml liegt auch im
|
||||||
|
# Quelltext der Dienst-Installation, ein Dienst namens proxledger aber nur dort.
|
||||||
|
installationsart() {
|
||||||
|
if systemctl cat proxledger.service >/dev/null 2>&1; then
|
||||||
|
printf 'dienst'
|
||||||
|
elif command -v docker >/dev/null 2>&1 && [ -f docker-compose.yml ]; then
|
||||||
|
printf 'docker'
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
ART=$(installationsart)
|
||||||
|
[ -n "$ART" ] || fehler "Keine Installation gefunden – weder der Dienst proxledger noch Docker mit docker-compose.yml."
|
||||||
|
|
||||||
|
blau "Installationsart: ${ART}"
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------- Sicherung
|
||||||
if [ "$SICHERN" = "ja" ]; then
|
if [ "$SICHERN" = "ja" ]; then
|
||||||
blau "Sicherung anlegen …"
|
blau "Sicherung anlegen nach ${SICHERUNG_ZIEL} …"
|
||||||
bash deploy/backup.sh
|
if ! bash deploy/backup.sh "$SICHERUNG_ZIEL"; then
|
||||||
|
fehler "Die Sicherung ist fehlgeschlagen – deshalb wird nicht aktualisiert.
|
||||||
|
Häufigste Ursache: fehlende Rechte am Zielordner. Mögliche Wege:
|
||||||
|
sudo bash deploy/update.sh
|
||||||
|
SICHERUNG_ZIEL=/pfad/mit/rechten bash deploy/update.sh
|
||||||
|
bash deploy/update.sh --ohne-sicherung (nur wenn anderweitig gesichert ist)"
|
||||||
|
fi
|
||||||
gruen "Sicherung abgeschlossen."
|
gruen "Sicherung abgeschlossen."
|
||||||
|
else
|
||||||
|
printf '\033[1;33m! Ohne Sicherung – auf eigenes Risiko.\033[0m\n'
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------- Quelltext
|
||||||
if [ -d .git ]; then
|
if [ -d .git ]; then
|
||||||
blau "Neuen Stand holen …"
|
blau "Neuen Stand holen …"
|
||||||
git pull --ff-only
|
git pull --ff-only
|
||||||
|
else
|
||||||
|
printf '\033[1;33m! Kein Git-Verzeichnis – der Quelltext bleibt wie er ist.\033[0m\n'
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------- Aktualisieren
|
||||||
|
if [ "$ART" = "docker" ]; then
|
||||||
|
[ -f .env ] || fehler "Keine .env gefunden – wird dieses Skript im richtigen Verzeichnis ausgeführt?"
|
||||||
|
|
||||||
blau "Abbilder neu bauen …"
|
blau "Abbilder neu bauen …"
|
||||||
docker compose build --pull
|
docker compose build --pull
|
||||||
|
|
||||||
@@ -45,16 +79,50 @@ docker compose run --rm migrate
|
|||||||
|
|
||||||
blau "Dienste neu starten …"
|
blau "Dienste neu starten …"
|
||||||
docker compose up -d
|
docker compose up -d
|
||||||
|
else
|
||||||
|
command -v npm >/dev/null 2>&1 || fehler "npm nicht gefunden – gehört zur Installation als Dienst."
|
||||||
|
[ -f .env ] || fehler "Keine .env gefunden (erwartet in ${VERZEICHNIS})."
|
||||||
|
|
||||||
# Kurz warten und nachsehen, ob das Dashboard wieder antwortet.
|
# Die .env trägt APP_SECRET; ein git pull fasst sie nicht an, aber sicher ist sicher.
|
||||||
|
cp .env "/tmp/proxledger-env-$(date +%s).sicherung"
|
||||||
|
|
||||||
|
blau "Abhängigkeiten installieren …"
|
||||||
|
npm ci
|
||||||
|
|
||||||
|
blau "Datenbank migrieren …"
|
||||||
|
npx prisma generate
|
||||||
|
npx prisma migrate deploy
|
||||||
|
|
||||||
|
blau "Anwendung bauen …"
|
||||||
|
npm run build
|
||||||
|
npm run build:worker
|
||||||
|
|
||||||
|
blau "Dienste neu starten …"
|
||||||
|
systemctl restart proxledger proxledger-worker
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------- Prüfen
|
||||||
blau "Warte auf das Dashboard …"
|
blau "Warte auf das Dashboard …"
|
||||||
for versuch in $(seq 1 30); do
|
PORT="${PORT:-3000}"
|
||||||
if docker compose exec -T web wget -qO- http://localhost:3000/api/gesundheit >/dev/null 2>&1; then
|
|
||||||
|
for versuch in $(seq 1 45); do
|
||||||
|
if [ "$ART" = "docker" ]; then
|
||||||
|
erreichbar=$(docker compose exec -T web wget -qO- "http://127.0.0.1:3000/api/gesundheit" >/dev/null 2>&1 && echo ja || echo nein)
|
||||||
|
else
|
||||||
|
erreichbar=$(curl -fsS -o /dev/null --max-time 2 "http://localhost:${PORT}/api/gesundheit" && echo ja || echo nein)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$erreichbar" = "ja" ]; then
|
||||||
gruen "ProxLedger läuft wieder (nach ${versuch} s)."
|
gruen "ProxLedger läuft wieder (nach ${versuch} s)."
|
||||||
docker compose ps
|
[ "$ART" = "docker" ] && docker compose ps
|
||||||
|
[ "$ART" = "dienst" ] && systemctl --no-pager --lines=0 status proxledger proxledger-worker | grep -E "●|Active:"
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
sleep 1
|
sleep 1
|
||||||
done
|
done
|
||||||
|
|
||||||
|
if [ "$ART" = "docker" ]; then
|
||||||
fehler "Das Dashboard antwortet nicht. Protokoll ansehen: docker compose logs -n 50 web"
|
fehler "Das Dashboard antwortet nicht. Protokoll ansehen: docker compose logs -n 50 web"
|
||||||
|
else
|
||||||
|
fehler "Das Dashboard antwortet nicht. Protokoll ansehen: journalctl -u proxledger -n 50"
|
||||||
|
fi
|
||||||
|
|||||||
+1
-1
@@ -60,7 +60,7 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- uploads:/data
|
- uploads:/data
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "wget", "-qO-", "http://localhost:3000/api/gesundheit"]
|
test: ["CMD", "wget", "-qO-", "http://127.0.0.1:3000/api/gesundheit"]
|
||||||
interval: 30s
|
interval: 30s
|
||||||
timeout: 5s
|
timeout: 5s
|
||||||
retries: 5
|
retries: 5
|
||||||
|
|||||||
@@ -396,31 +396,46 @@ Rückweg immer nutzbar.
|
|||||||
**Sichern:**
|
**Sichern:**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./deploy/backup.sh /var/backups/proxledger
|
bash /opt/proxledger/deploy/backup.sh /var/backups/proxledger
|
||||||
```
|
```
|
||||||
|
|
||||||
Das Skript sichert Datenbank, hochgeladene PDFs und die `.env`. Für regelmäßige Sicherungen in die
|
Das Skript sichert Datenbank, hochgeladene PDFs und die `.env` – und erkennt selbst, ob die
|
||||||
Crontab eintragen:
|
Installation mit Docker oder als Dienst im Container läuft. Für regelmäßige Sicherungen in die Crontab:
|
||||||
|
|
||||||
```
|
```
|
||||||
30 2 * * * /opt/proxledger/deploy/backup.sh /var/backups/proxledger
|
30 2 * * * /opt/proxledger/deploy/backup.sh /var/backups/proxledger
|
||||||
```
|
```
|
||||||
|
|
||||||
**Zurückspielen:**
|
**Zurückspielen** (Docker):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
gunzip -c datenbank-20260917-023000.sql.gz | docker compose exec -T postgres psql -U proxledger proxledger
|
gunzip -c datenbank-20260917-023000.sql.gz | docker compose exec -T postgres psql -U proxledger proxledger
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Bei der Installation als Dienst stattdessen:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
gunzip -c datenbank-20260917-023000.sql.gz | psql "$DATABASE_URL"
|
||||||
|
```
|
||||||
|
|
||||||
**Aktualisieren:**
|
**Aktualisieren:**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd /opt/proxledger
|
bash /opt/proxledger/deploy/update.sh
|
||||||
git pull
|
|
||||||
docker compose up -d --build
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Migrationen laufen dabei automatisch.
|
Ein Befehl für beide Installationsarten. Der Reihe nach: sichern, neuen Stand holen, bauen,
|
||||||
|
migrieren, neu starten – und zum Schluss prüfen, ob das Dashboard wieder antwortet. Schlägt die
|
||||||
|
Sicherung fehl, bricht das Skript ab, **bevor** etwas verändert wird.
|
||||||
|
|
||||||
|
| Aufruf | Wirkung |
|
||||||
|
|---|---|
|
||||||
|
| `bash deploy/update.sh` | der übliche Weg |
|
||||||
|
| `SICHERUNG_ZIEL=/pfad bash deploy/update.sh` | anderer Ort für die Sicherung |
|
||||||
|
| `bash deploy/update.sh --ohne-sicherung` | nur, wenn anderweitig gesichert ist |
|
||||||
|
|
||||||
|
Beim LXC-Weg nach Art der Helper-Scripts geht es auch über das Skript auf dem Proxmox-Host – dort
|
||||||
|
erkennt das Gerüst eine vorhandene Installation und bietet die Aktualisierung an.
|
||||||
|
|
||||||
> `APP_SECRET` unbedingt mitsichern: Ohne diesen Wert sind alle Sitzungen ungültig. Und beachte, dass eine
|
> `APP_SECRET` unbedingt mitsichern: Ohne diesen Wert sind alle Sitzungen ungültig. Und beachte, dass eine
|
||||||
> Sicherung die Zugangsdaten für SMTP und Webhook im Klartext enthält – sie gehört entsprechend geschützt.
|
> Sicherung die Zugangsdaten für SMTP und Webhook im Klartext enthält – sie gehört entsprechend geschützt.
|
||||||
|
|||||||
@@ -14,10 +14,15 @@ Maschinenkennung, nicht an einem Token.
|
|||||||
## Sichern
|
## Sichern
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
bash deploy/backup.sh # Datenbank und Uploads
|
bash deploy/backup.sh /var/backups/proxledger
|
||||||
```
|
```
|
||||||
|
|
||||||
Beim LXC-Weg reicht zusätzlich die gewohnte Proxmox-Sicherung des Containers.
|
Das Skript erkennt selbst, ob die Installation mit Docker oder als Dienst läuft, und sichert in beiden
|
||||||
|
Fällen Datenbank, Uploads und `.env`. Beim LXC-Weg reicht zusätzlich die gewohnte Proxmox-Sicherung
|
||||||
|
des Containers.
|
||||||
|
|
||||||
|
Vor jeder Aktualisierung läuft es ohnehin automatisch – [`deploy/update.sh`](../../deploy/update.sh)
|
||||||
|
ruft es als Erstes auf und bricht ab, wenn es fehlschlägt.
|
||||||
|
|
||||||
## Zurückspielen
|
## Zurückspielen
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
# #031 Update- und Sicherungsskript für beide Installationsarten
|
||||||
|
**Status:** erledigt
|
||||||
|
**Meilenstein:** v0.20.0
|
||||||
|
**Labels:** deployment
|
||||||
|
**Geschätzt:** 2 h **Tatsächlich:** 0 h 45 min
|
||||||
|
|
||||||
|
## Ziel
|
||||||
|
`deploy/update.sh` und `deploy/backup.sh` konnten nur Docker. Die Installation als Dienst (Node und
|
||||||
|
PostgreSQL direkt im LXC) ging leer aus – dort half nur der Weg über das Gerüst der community-scripts.
|
||||||
|
|
||||||
|
## Aufgaben
|
||||||
|
- [x] Beide Skripte erkennen die Installationsart selbst (systemd-Dienst oder Docker)
|
||||||
|
- [x] Dienst-Weg: `npm ci`, `prisma migrate deploy`, bauen, `systemctl restart`
|
||||||
|
- [x] Sicherung für den Dienst-Weg: `pg_dump` über `DATABASE_URL`, Uploads aus `UPLOAD_DIR`
|
||||||
|
- [x] Fehlgeschlagene Sicherung bricht die Aktualisierung ab – **vor** jeder Änderung
|
||||||
|
- [x] Hinweis am Ende von `deploy/lxc-installer.sh` auf die Skripte umgestellt
|
||||||
|
- [x] Handbuch und Betriebsdoku angepasst
|
||||||
|
- [x] Docker-Weg vollständig durchgespielt
|
||||||
|
|
||||||
|
## Zwei Fehler beim Durchspielen gefunden
|
||||||
|
1. **Die Zustandsprüfung des Web-Containers konnte nie gelingen.** Next bindet im Standalone-Modus an
|
||||||
|
die Adresse aus `HOSTNAME` – und Docker setzt darin den Containernamen. Der Server lauschte also
|
||||||
|
nur auf der Container-IP, nicht auf `127.0.0.1`. Der Dienst `web` blieb dauerhaft auf
|
||||||
|
„health: starting“; von außen war er trotzdem erreichbar, deshalb fiel es bisher nicht auf.
|
||||||
|
Behoben mit `ENV HOSTNAME=0.0.0.0` im Dockerfile; die Prüfungen verwenden jetzt `127.0.0.1`
|
||||||
|
statt `localhost` (das löst im Container auch auf `::1` auf).
|
||||||
|
2. **Die Sicherung scheiterte stumm an fehlenden Rechten** (`/var/backups` gehört root) und die
|
||||||
|
Aktualisierung lief trotzdem weiter. Jetzt bricht sie ab und nennt die drei Auswege.
|
||||||
|
|
||||||
|
## Prüfung
|
||||||
|
Vollständiger Durchlauf gegen einen laufenden Stapel: Sicherung (Datenbank 6,3 KB mit 25 Tabellen,
|
||||||
|
Uploads, `.env`), Abbilder gebaut, migriert, neu gestartet, Dashboard nach zwei Sekunden wieder da.
|
||||||
|
Danach stand `web` zum ersten Mal auf **healthy**.
|
||||||
@@ -34,4 +34,5 @@ Details und Architektur: [../architektur.md](../architektur.md). Zeiten werden a
|
|||||||
| [#028](028-passkeys.md) | Anmeldung mit Passkeys | erledigt | v0.18.0 | 4 h | 0 h 45 min |
|
| [#028](028-passkeys.md) | Anmeldung mit Passkeys | erledigt | v0.18.0 | 4 h | 0 h 45 min |
|
||||||
| [#029](029-betriebsdokumentation.md) | Einrichtungsdokumentation | erledigt | v0.19.0 | 3 h | 0 h 40 min |
|
| [#029](029-betriebsdokumentation.md) | Einrichtungsdokumentation | erledigt | v0.19.0 | 3 h | 0 h 40 min |
|
||||||
| [#030](030-netbird-reverse-proxy.md) | netbird Reverse Proxy in die Anleitung | erledigt | v0.19.1 | 1 h | 0 h 20 min |
|
| [#030](030-netbird-reverse-proxy.md) | netbird Reverse Proxy in die Anleitung | erledigt | v0.19.1 | 1 h | 0 h 20 min |
|
||||||
| | **Summe** | | | **147 h** | **15 h 23 min** |
|
| [#031](031-update-skript-beide-varianten.md) | Update- und Sicherungsskript für beide Varianten | erledigt | v0.20.0 | 2 h | 0 h 45 min |
|
||||||
|
| | **Summe** | | | **149 h** | **16 h 08 min** |
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "proxledger",
|
"name": "proxledger",
|
||||||
"version": "0.19.2",
|
"version": "0.20.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev",
|
"dev": "next dev",
|
||||||
|
|||||||
Reference in New Issue
Block a user