INBOX/checkpoint-updates-backup.md
2026-08-07 16:01:24 +02:00

6.9 KiB

CheckPoint Ehrenamt — Updates & Datensicherung

Vier Stufen von Änderungen · Backup-Strategie · Stand: Juni 2026


Grundregel (immer)

Vor jedem Update: Backup ziehen. Kein Update ohne Backup — egal wie klein die Änderung scheint.


Backup manuell auslösen

docker exec checkpoint python3 -c "
import sqlite3
src = sqlite3.connect('/app/instance/checkpoint.sqlite')
dst = sqlite3.connect('/app/instance/latest-backup.sqlite')
src.backup(dst)
dst.close()
src.close()
"

Warum nicht einfach cp? SQLite schreibt in mehreren Schritten (WAL-Modus). Ein roher Datei-Copy kann die Datenbank mitten in einem Schreibvorgang erwischen und ein korruptes Backup erzeugen. connection.backup() macht einen konsistenten Online-Snapshot — auch bei laufendem Betrieb sicher.

Backup prüfen:

docker exec checkpoint ls -lh /app/instance/

Automatisches tägliches Backup (Cronjob)

Läuft täglich um 03:30 UTC auf dem VPS:

30 03 * * * docker exec checkpoint python3 -c "import sqlite3; src=sqlite3.connect('/app/instance/checkpoint.sqlite'); dst=sqlite3.connect('/app/instance/latest-backup.sqlite'); src.backup(dst); dst.close(); src.close()"

Cronjob anzeigen: crontab -l Cronjob bearbeiten: crontab -e

Wichtig: Das Backup liegt im Docker-Volume auf dem VPS. Wenn der VPS ausfällt, ist auch das Backup weg. Deshalb zusätzlich Ebene 3 (siehe unten).


Backup vom VPS runterkopieren (Ebene 3)

Auf dem lokalen Rechner:

scp patsy@<vps-ip>:/var/lib/docker/volumes/checkpoint_checkpoint_data/_data/latest-backup.sqlite ./checkpoint-backup-$(date +%Y%m%d).sqlite

Mindestens einmal pro Woche, immer vor größeren Updates (Stufe 3 + 4).


Die vier Update-Stufen


Stufe 1 — Statische Dateien (CSS, JS, Bilder)

Beispiele: Farbe ändern, Button-Stil anpassen, Token-Werte in tokens.css.

Risiko: keines für die Daten.

Vorgehen:

# 1. Backup (Pflicht, auch hier)
docker exec checkpoint python3 -c "import sqlite3; src=sqlite3.connect('/app/instance/checkpoint.sqlite'); dst=sqlite3.connect('/app/instance/latest-backup.sqlite'); src.backup(dst); dst.close(); src.close()"

# 2. Code holen
cd ~/apps/checkpoint
git pull

# 3. Image neu bauen und Container ersetzen
cd ~/stacks/checkpoint
docker compose build
docker compose up -d

# 4. Logs prüfen
docker logs checkpoint --tail 50

# 5. App im Browser aufrufen und prüfen

Stufe 2 — Python-Code, Routen, Templates (keine DB-Änderung)

Beispiele: Bugfix in einer Route, neues Template, geänderte Business-Logik, neue Blueprint-Route.

Risiko: keines für die Daten. Aber: fehlerhafter Code kann die App down bringen. Lokal testen bevor pushen.

Vorgehen: identisch mit Stufe 1.

db.create_all() läuft beim Container-Start automatisch — bei unverändertem Datenmodell macht es nichts.


Stufe 3 — Neue Tabelle oder neue Spalte (additiv)

Beispiele: Neues Modell hinzufügen, optionale Spalte ergänzen.

Risiko: mittel. db.create_all() legt neue Tabellen automatisch an, ändert aber bestehende Tabellen nicht. Neue Spalte vergessen → App crasht beim ersten Zugriff auf das Feld.

Vorgehen:

# 1. Backup ziehen (und lokal runterkopieren)
docker exec checkpoint python3 -c "import sqlite3; src=sqlite3.connect('/app/instance/checkpoint.sqlite'); dst=sqlite3.connect('/app/instance/latest-backup.sqlite'); src.backup(dst); dst.close(); src.close()"

# 2. Code holen, bauen, starten
cd ~/apps/checkpoint && git pull
cd ~/stacks/checkpoint && docker compose build && docker compose up -d

# 3. Neue Spalte manuell ergänzen (Beispiel)
docker exec -it checkpoint python3 -c "
import sqlite3
con = sqlite3.connect('/app/instance/checkpoint.sqlite')
con.execute('ALTER TABLE user ADD COLUMN telefon TEXT')
con.commit()
con.close()
"

# 4. Logs prüfen
docker logs checkpoint --tail 50

# 5. App testen — besonders die betroffenen Bereiche

Neue Tabellen (komplett neue Modelle) werden von db.create_all() automatisch angelegt — kein manueller Schritt nötig.


Stufe 4 — Schema-Änderung an bestehenden Tabellen

Beispiele: Spalte umbenennen, Datentyp ändern, Tabelle umstrukturieren, Spalte löschen.

Risiko: hoch. SQLite unterstützt viele ALTER TABLE-Operationen nicht nativ. Niemals ohne Backup und ohne vorherige Absprache durchführen.

Vorgehen:

# 1. Backup ziehen UND lokal runterkopieren (Pflicht)
docker exec checkpoint python3 -c "import sqlite3; src=sqlite3.connect('/app/instance/checkpoint.sqlite'); dst=sqlite3.connect('/app/instance/latest-backup.sqlite'); src.backup(dst); dst.close(); src.close()"

scp patsy@<vps-ip>:/var/lib/docker/volumes/checkpoint_checkpoint_data/_data/latest-backup.sqlite ./checkpoint-backup-$(date +%Y%m%d).sqlite

# 2. Migrationsstrategie mit Claude besprechen bevor Code angefasst wird

# 3. Lokal testen mit einer Kopie der echten DB

# 4. Erst dann: Code holen, bauen, starten
cd ~/apps/checkpoint && git pull
cd ~/stacks/checkpoint && docker compose build && docker compose up -d

# 5. Migration manuell ausführen (Strategie je nach Änderung)

# 6. Intensiv testen

SQLite-Einschränkung: Spalten umbenennen geht ab SQLite 3.25+, Spalten löschen ab 3.35+. Datentyp ändern oder komplexe Umstrukturierungen erfordern die „Tabelle neu bauen"-Strategie:

  1. Neue Tabelle mit korrekter Struktur anlegen
  2. Daten rüber kopieren
  3. Alte Tabelle löschen
  4. Neue Tabelle umbenennen

Bei Stufe 4 immer erst besprechen, nie blind durchführen.


Update-Checkliste (für jedes Update)

Vor dem Update
  □ Backup manuell ausgelöst
  □ Backup-Datei im Volume vorhanden (ls -lh prüfen)
  □ Bei Stufe 3/4: Backup lokal runtergeladen

Update
  □ git pull
  □ docker compose build
  □ docker compose up -d

Nach dem Update
  □ docker logs checkpoint --tail 50  — keine Fehler?
  □ App im Browser aufgerufen — lädt sie?
  □ Login funktioniert?
  □ Bei Stufe 3: ALTER TABLE ausgeführt?
  □ Betroffene Funktion manuell getestet?

Rollback (wenn etwas schiefgeht)

# 1. Letzten funktionierenden Commit finden
cd ~/apps/checkpoint
git log --oneline -10

# 2. Auf diesen Commit zurückgehen
git checkout <commit-hash>

# 3. Image neu bauen und starten
cd ~/stacks/checkpoint
docker compose build
docker compose up -d

# 4. Bei DB-Schaden: Backup wiederherstellen
docker exec checkpoint python3 -c "
import sqlite3
src = sqlite3.connect('/app/instance/latest-backup.sqlite')
dst = sqlite3.connect('/app/instance/checkpoint.sqlite')
src.backup(dst)
dst.close()
src.close()
"

Drei Backup-Ebenen im Überblick

Ebene Was Wie oft Wo
1 Manuell vor jedem Update Bei jedem Update Docker Volume (VPS)
2 Automatischer Cronjob Täglich 03:30 UTC Docker Volume (VPS)
3 Lokale Kopie Mindestens wöchentlich Eigener Rechner

Ebene 3 ist die wichtigste — nur ein Backup außerhalb des VPS ist ein echtes Backup.