From c38bca615d4bfc04c88301051c166f07d073da23 Mon Sep 17 00:00:00 2001 From: Dotty Dotter Date: Sat, 25 Apr 2026 21:00:52 +0200 Subject: [PATCH] ops: Daily DB-Backup-Script + Cron 03:00 (Release 1.0) - scripts/backup-db.sh: Online-Backup via Pythons sqlite3.backup() (atomar, async-safe, kein sqlite3-CLI im Container noetig) - gzip-compressed Backups in /opt/gwoe-antragspruefer/backups/ - 30-Tage-Retention + monatlicher Snapshot bleibt erhalten - Host-Cron 0 3 * * * (vor dem Mail-Digest 07:00) Co-Authored-By: Claude Opus 4.7 (1M context) --- scripts/backup-db.sh | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100755 scripts/backup-db.sh diff --git a/scripts/backup-db.sh b/scripts/backup-db.sh new file mode 100755 index 0000000..b05d50a --- /dev/null +++ b/scripts/backup-db.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# Daily backup via Pythons sqlite3.backup() — atomar, async-DB-safe, +# kein sqlite3-CLI im Container vorausgesetzt. +set -euo pipefail +TS=$(date +%Y%m%d-%H%M%S) +BACKUP_DIR=/opt/gwoe-antragspruefer/backups +mkdir -p $BACKUP_DIR +docker exec gwoe-antragspruefer python -c " +import sqlite3 +src = sqlite3.connect(\"/app/data/gwoe-antraege.db\") +dst = sqlite3.connect(\"/tmp/db-backup.db\") +src.backup(dst); dst.close(); src.close() +" 2>&1 +docker cp gwoe-antragspruefer:/tmp/db-backup.db $BACKUP_DIR/gwoe-antraege-$TS.db +docker exec gwoe-antragspruefer rm /tmp/db-backup.db +gzip -9 $BACKUP_DIR/gwoe-antraege-$TS.db +find $BACKUP_DIR -name "gwoe-antraege-*.db.gz" -mtime +30 \ + ! -name "gwoe-antraege-*01-*.db.gz" -delete 2>/dev/null || true +echo "$(date -Iseconds) backup ok: $BACKUP_DIR/gwoe-antraege-$TS.db.gz"