# 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 ```bash 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: ```bash 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: ```bash scp patsy@:/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:** ```bash # 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:** ```bash # 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:** ```bash # 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@:/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) ```bash # 1. Letzten funktionierenden Commit finden cd ~/apps/checkpoint git log --oneline -10 # 2. Auf diesen Commit zurückgehen git checkout # 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.