diff --git a/install.sh b/install.sh index 6fe8dcc..4b84eee 100644 --- a/install.sh +++ b/install.sh @@ -8,23 +8,30 @@ # Erkennt selbstständig, ob unter /srv/tesm bereits eine Installation # existiert (an sqlite.db), und verhält sich entsprechend: # -# - Keine vorhandene Installation -> normale Frischinstallation. -# - Vorhanden, SCHEMA_VERSION unverändert -> einfaches In-Place-Update -# (Code/Templates/Abhängigkeiten aktualisieren; sqlite.db bleibt -# unangetastet -- rsync schließt sie ohnehin aus). Kein Backup nötig, -# da sich am Datenbank-Schema nichts ändert. -# - Vorhanden, SCHEMA_VERSION unbekannt oder abweichend -> Update MIT -# Sicherheitsnetz: die komplette bisherige Installation (Code, venv, -# Datenbank, Schlüssel) wird vorher 1:1 nach /srv/tesm-backup-pre- -# migration- kopiert. Die eigentliche Schema-Migration -# übernimmt danach die App selbst beim Start (siehe _ensure_schema() -# in app.py). Kommt der Dienst anschließend nachweislich NICHT gesund -# hoch (HTTP-Check auf /login), wird automatisch die komplette -# Sicherung zurückgespielt (alter Code + alte Datenbank zusammen -- -# ein reines DB-Rollback allein würde denselben Migrationsfehler beim -# nächsten Start mit dem neuen Code sofort wiederholen) und das -# Backup bleibt zur manuellen Prüfung erhalten. Kommt er gesund hoch, -# gilt die Migration als erfolgreich und das Backup wird gelöscht. +# - Keine vorhandene Installation -> normale Frischinstallation, kein +# Backup nötig (nichts, worauf zurückgerollt werden könnte). +# - Vorhanden (egal ob SCHEMA_VERSION gleich geblieben oder sich +# geändert hat) -> Update MIT Sicherheitsnetz: die komplette bisherige +# Installation (Code, venv, Datenbank, Schlüssel) wird vorher 1:1 nach +# /srv/tesm-backup-pre-update- kopiert. Eine eigentliche +# Schema-Migration übernimmt danach die App selbst beim Start (siehe +# _ensure_schema() in app.py). Kommt der Dienst anschließend +# nachweislich NICHT gesund hoch (HTTP-Check auf /login), wird +# automatisch die komplette Sicherung zurückgespielt (alter Code + +# alte Datenbank zusammen -- ein reines DB-Rollback allein würde +# denselben Fehler beim nächsten Start mit dem neuen Code sofort +# wiederholen) und das Backup bleibt zur manuellen Prüfung erhalten. +# Kommt er gesund hoch, gilt das Update als erfolgreich und das +# Backup wird gelöscht. +# +# Das Sicherheitsnetz greift bewusst bei JEDEM Update einer bestehenden +# Installation, nicht nur bei einer erkannten Schema-Änderung -- ein +# rein code-seitiger Fehler im neuen Paket hat mit dem Datenbank-Schema +# nichts zu tun, hätte den Dienst bei einem "Schema unverändert -> kein +# Backup"-Kurzschluss aber trotzdem ungeschützt lahmgelegt (live +# reproduziert). SCHEMA_VERSION bestimmt nur noch den Wortlaut der +# Log-Meldung (In-Place-Update vs. Migration), nicht mehr, OB +# abgesichert wird. # ============================================================================ set -e @@ -46,6 +53,15 @@ step() { echo -e "${RED}→${NC} ${1}..." | tee -a /var/log/tesm-install clear 2>/dev/null || true # ---- Bestehende Installation erkennen ---- +# WICHTIG: das Sicherheitsnetz (Backup + Health-Check + ggf. Rückroll) +# greift bei JEDEM Update einer bestehenden Installation, nicht nur bei +# einer erkannten Schema-Änderung -- live so gefunden: ein rein +# code-seitiger Fehler im neuen Paket (z.B. ein kaputtes app.py, mit dem +# Schema selbst hat das nichts zu tun) hätte bei einem reinen "Schema +# unverändert -> kein Backup"-Kurzschluss ungeschützt den Dienst +# lahmgelegt, ganz ohne automatische Wiederherstellung. Die +# SCHEMA_VERSION-Auswertung dient jetzt nur noch der Log-Meldung (WARUM +# aktualisiert wird), nicht mehr der Entscheidung OB abgesichert wird. EXISTING_INSTALL=0 [ -f /srv/tesm/sqlite.db ] && EXISTING_INSTALL=1 @@ -63,7 +79,7 @@ if [ "$EXISTING_INSTALL" -eq 1 ]; then print_status "Service stopped" if [ -n "$OLD_SCHEMA_VERSION" ] && [ -n "$NEW_SCHEMA_VERSION" ] && [ "$OLD_SCHEMA_VERSION" == "$NEW_SCHEMA_VERSION" ]; then - echo -e "${GREEN}Bestehende Installation erkannt, Datenbank-Schema unverändert (Version ${OLD_SCHEMA_VERSION}):${NC} einfaches In-Place-Update, kein Backup nötig." + echo -e "${GREEN}Bestehende Installation erkannt, Datenbank-Schema unverändert (Version ${OLD_SCHEMA_VERSION}):${NC} In-Place-Update." else if [ -n "$OLD_SCHEMA_VERSION" ] && [ -n "$NEW_SCHEMA_VERSION" ]; then reason="Datenbank-Schema hat sich geändert (${OLD_SCHEMA_VERSION} -> ${NEW_SCHEMA_VERSION})" @@ -71,13 +87,13 @@ if [ "$EXISTING_INSTALL" -eq 1 ]; then reason="Schema-Version der bestehenden Installation oder dieses Pakets unbekannt" fi echo -e "${YELLOW}Bestehende Installation erkannt, ${reason}:${NC}" - echo "Update mit automatischer Migration und Sicherheitsnetz (Rückroll-Backup)." - NEEDS_MIGRATION_GUARD=1 - BACKUP_DIR="/srv/tesm-backup-pre-migration-$(date +%Y%m%d-%H%M%S)" - step "Backing up current installation to $BACKUP_DIR before migration" - cp -a /srv/tesm "$BACKUP_DIR" - print_status "Backup created" + echo "Update mit automatischer Migration." fi + NEEDS_MIGRATION_GUARD=1 + BACKUP_DIR="/srv/tesm-backup-pre-update-$(date +%Y%m%d-%H%M%S)" + step "Backing up current installation to $BACKUP_DIR before update" + cp -a /srv/tesm "$BACKUP_DIR" + print_status "Backup created" fi # ---- Pakete ---- @@ -164,11 +180,10 @@ sudo systemctl enable --now tesm.service sudo systemctl enable --now tesm-check.service tesm-check-restart.timer print_status "Services enabled and started" -# ---- Migrations-Sicherheitsnetz prüfen ---- -# Nur relevant, wenn oben tatsächlich eine riskante Migration (abweichende/ -# unbekannte SCHEMA_VERSION) erkannt wurde -- beim einfachen In-Place-Update -# oder einer Frischinstallation ist BACKUP_DIR leer und dieser Block wird -# komplett übersprungen. +# ---- Sicherheitsnetz prüfen ---- +# Läuft bei JEDEM Update einer bestehenden Installation (NEEDS_MIGRATION_ +# GUARD=1, siehe oben) -- nur bei einer Frischinstallation ist BACKUP_DIR +# leer und dieser Block wird komplett übersprungen. if [ "$NEEDS_MIGRATION_GUARD" -eq 1 ]; then step "Verifying migrated installation" HEALTHY=0 @@ -182,15 +197,23 @@ if [ "$NEEDS_MIGRATION_GUARD" -eq 1 ]; then if [ "$HEALTHY" -eq 1 ]; then print_status "Migration verified healthy" rm -rf "$BACKUP_DIR" - echo -e "${GREEN}✔${NC} Migration erfolgreich -- Backup wieder entfernt." + echo -e "${GREEN}✔${NC} Update erfolgreich -- Backup wieder entfernt." else - echo -e "${RED}✖ Migration fehlgeschlagen -- Dienst antwortet nicht gesund. Rolle zurück...${NC}" + echo -e "${RED}✖ Update fehlgeschlagen -- Dienst antwortet nicht gesund. Rolle zurück...${NC}" sudo systemctl stop tesm.service 2>/dev/null || true - sudo rm -rf /srv/tesm - sudo mv "$BACKUP_DIR" /srv/tesm + # Fehlgeschlagene Installation NICHT einfach löschen, sondern separat + # beiseite legen (zur Fehlersuche) -- und das Backup per "cp" statt + # "mv" zurückspielen, damit BEIDES danach getrennt erhalten bleibt + # (sonst würde das Backup beim Zurückspielen selbst zum neuen + # /srv/tesm werden und als eigenständige Sicherung verschwinden). + FAILED_DIR="/srv/tesm-failed-update-$(date +%Y%m%d-%H%M%S)" + sudo mv /srv/tesm "$FAILED_DIR" + sudo cp -a "$BACKUP_DIR" /srv/tesm sudo systemctl start tesm.service echo -e "${YELLOW}Zurückgerollt auf den Stand vor dem Update (alter Code + alte Datenbank zusammen).${NC}" - echo "Bitte /var/log/tesm/app.log prüfen oder Export/Import nutzen, bevor erneut aktualisiert wird." + echo "Backup bleibt erhalten unter: ${BACKUP_DIR}" + echo "Die fehlgeschlagene Installation liegt zur Fehlersuche unter: ${FAILED_DIR}" + echo "Bitte /var/log/tesm/app.log dort prüfen, bevor erneut aktualisiert wird." fi fi diff --git a/srv/tesm/VERSION b/srv/tesm/VERSION index 21e8796..ee90284 100644 --- a/srv/tesm/VERSION +++ b/srv/tesm/VERSION @@ -1 +1 @@ -1.0.3 +1.0.4