#!/usr/bin/env bash set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" COMPOSE_FILE="docker-compose-multitenant.yml" # Verzeichnisse INVOICE_ARCHIVE_DIR="${INVOICE_ARCHIVE_DIR:-/var/backups/invoice-archive}" FULL_BACKUP_DIR="${FULL_BACKUP_DIR:-/var/backups/inventarsystem}" LOG_DIR="$SCRIPT_DIR/logs" KEEP_DAYS="${INVOICE_KEEP_DAYS:-3650}" MODE="auto" BASE_NAME="" usage() { cat <&2 usage exit 2 ;; esac done } ensure_directory() { mkdir -p "$INVOICE_ARCHIVE_DIR" mkdir -p "$FULL_BACKUP_DIR" } cleanup_old_archives() { if [[ -n "$KEEP_DAYS" ]]; then find "$INVOICE_ARCHIVE_DIR" -maxdepth 1 -type f -mtime +"$KEEP_DAYS" -print -delete 2>/dev/null || true fi # Behalte die kompletten DB-Backups für 30 Tage find "$FULL_BACKUP_DIR" -maxdepth 1 -type f -mtime +30 -print -delete 2>/dev/null || true } docker_backup() { if ! command -v docker >/dev/null 2>&1; then return 1 fi if ! docker compose -f "$COMPOSE_FILE" ps -q app >/dev/null 2>&1; then return 1 fi local timestamp timestamp="$(date +'%Y-%m-%d_%H-%M-%S')" echo "[$(date +'%T')] Starte VOLLSTAENDIGES System-Backup..." # 1. MongoDB Full Dump (Alles: Ausleihen, User, Inventar, etc.) if docker compose -f "$COMPOSE_FILE" ps -q mongodb >/dev/null 2>&1; then echo "[$(date +'%T')] Erstelle Datenbank-Dump (MongoDB)..." docker compose -f "$COMPOSE_FILE" exec -T mongodb mongodump --archive --gzip > "$FULL_BACKUP_DIR/full_db_${timestamp}.archive.gz" else echo "Warnung: MongoDB-Container nicht gefunden. Überspringe DB-Dump." fi # 2. Logs sichern if [ -d "$LOG_DIR" ]; then echo "[$(date +'%T')] Sichere Logs..." tar -czf "$FULL_BACKUP_DIR/logs_${timestamp}.tar.gz" -C "$(dirname "$LOG_DIR")" "$(basename "$LOG_DIR")" fi # 3. Invoice Export (für Kompatibilität mit dem alten Format) local app_container app_container="$(docker compose -f "$COMPOSE_FILE" ps -q app | tr -d '[:space:]')" if [[ -n "$app_container" ]]; then local output_dir="/tmp/invoice_archive_${timestamp}" local remote_base="${output_dir}/${BASE_NAME}" docker compose -f "$COMPOSE_FILE" exec -T app mkdir -p "$output_dir" docker compose -f "$COMPOSE_FILE" exec -T app python3 /app/Web/modules/inventarsystem/backup_invoices.py \ --archive-dir "$output_dir" \ --base-name "$BASE_NAME" >/dev/null 2>&1 || true if docker compose -f "$COMPOSE_FILE" exec -T app test -f "${remote_base}.jsonl"; then docker cp "$app_container":"${remote_base}.jsonl" "$INVOICE_ARCHIVE_DIR/" docker cp "$app_container":"${remote_base}.csv" "$INVOICE_ARCHIVE_DIR/" docker cp "$app_container":"${remote_base}.meta.json" "$INVOICE_ARCHIVE_DIR/" else echo "[$(date +'%T')] Info: Keine Rechnungsdaten gefunden." fi docker compose -f "$COMPOSE_FILE" exec -T app rm -rf "$output_dir" fi echo "[$(date +'%T')] Backup erfolgreich abgeschlossen!" echo "Dateien gespeichert in: $FULL_BACKUP_DIR" return 0 } main() { parse_args "$@" if [[ -z "$BASE_NAME" ]]; then BASE_NAME="invoices-$(date +'%Y-%m-%d_%H-%M-%S')" fi ensure_directory case "$MODE" in auto|docker) if docker_backup; then cleanup_old_archives return 0 fi echo "Error: Docker Backup fehlgeschlagen." >&2 return 1 ;; *) echo "Error: unsupported mode '$MODE'" >&2 usage return 2 ;; esac } main "$@"