#!/usr/bin/env bash # BÜTÇEM günlük yedek — sunucuda (Atlas) root olarak, cron ile çalışır. Ayrıntı: docs/DEPLOY.md › Yedekleme # # Üretir (BACKUP_DIR altında, tarih damgalı): # mongo-YYYYmmdd-HHMMSS.archive.gz → butcem veritabanı (mongodump --archive --gzip) # uploads-YYYYmmdd-HHMMSS.tar.gz → yüklenen dosyalar (uploads volume) # SHA256SUMS-YYYYmmdd-HHMMSS → bütünlük özetleri # RETENTION_DAYS günden eski yedekleri siler. # # Ayarlar /etc/butcem-backup.env dosyasından okunur (yalnızca root okuyabilmeli: chmod 600). set -euo pipefail CONFIG="${BUTCEM_BACKUP_CONFIG:-/etc/butcem-backup.env}" # shellcheck source=/dev/null [ -f "$CONFIG" ] && . "$CONFIG" : "${MONGO_CONTAINER:?MONGO_CONTAINER tanımlı değil (MongoDB konteyner adı veya adının bir parçası)}" : "${MONGO_ROOT_USER:?MONGO_ROOT_USER tanımlı değil}" : "${MONGO_ROOT_PASSWORD:?MONGO_ROOT_PASSWORD tanımlı değil}" : "${UPLOADS_VOLUME:?UPLOADS_VOLUME tanımlı değil (uygulamanın /app/uploads volume adı)}" BACKUP_DIR="${BACKUP_DIR:-/var/backups/butcem}" RETENTION_DAYS="${RETENTION_DAYS:-7}" DB_NAME="${DB_NAME:-butcem}" HELPER_IMAGE="${HELPER_IMAGE:-alpine:3.20}" TS="$(date +%Y%m%d-%H%M%S)" log() { echo "[$(date '+%F %T')] $*"; } # Dokploy konteyner adlarına rastgele son ek ekler; adın bir parçasıyla eşleşen çalışan konteyner. CID="$(docker ps -q --filter "name=${MONGO_CONTAINER}" | head -n1)" [ -n "$CID" ] || { log "HATA: '${MONGO_CONTAINER}' adlı çalışan MongoDB konteyneri yok."; exit 1; } docker volume inspect "$UPLOADS_VOLUME" >/dev/null 2>&1 || { log "HATA: '${UPLOADS_VOLUME}' volume'u yok."; exit 1; } install -d -m 700 "$BACKUP_DIR" MONGO_FILE="$BACKUP_DIR/mongo-$TS.archive.gz" UPLOADS_FILE="$BACKUP_DIR/uploads-$TS.tar.gz" # 1) MongoDB: parola komut satırında görünmesin diye geçici yapılandırma dosyasıyla. log "MongoDB yedeği alınıyor ($DB_NAME)…" CONF="/tmp/butcem-dump-$TS.yaml" printf 'password: "%s"\n' "$MONGO_ROOT_PASSWORD" | docker exec -i "$CID" sh -c "umask 077 && cat > $CONF" if ! docker exec "$CID" mongodump --quiet --config "$CONF" --username "$MONGO_ROOT_USER" \ --authenticationDatabase admin --db "$DB_NAME" --archive --gzip >"$MONGO_FILE"; then docker exec "$CID" rm -f "$CONF" rm -f "$MONGO_FILE" log "HATA: mongodump başarısız." exit 1 fi docker exec "$CID" rm -f "$CONF" [ -s "$MONGO_FILE" ] || { log "HATA: MongoDB yedeği boş."; exit 1; } # 2) Yüklenen dosyalar: volume salt okunur bağlanır. log "Uploads yedeği alınıyor ($UPLOADS_VOLUME)…" docker run --rm -v "$UPLOADS_VOLUME":/data:ro -v "$BACKUP_DIR":/backup "$HELPER_IMAGE" \ tar czf "/backup/$(basename "$UPLOADS_FILE")" -C /data . [ -s "$UPLOADS_FILE" ] || { log "HATA: uploads yedeği boş."; exit 1; } # 3) Bütünlük özeti ve izinler ( cd "$BACKUP_DIR" && sha256sum "$(basename "$MONGO_FILE")" "$(basename "$UPLOADS_FILE")" >"SHA256SUMS-$TS" ) chmod 600 "$MONGO_FILE" "$UPLOADS_FILE" "$BACKUP_DIR/SHA256SUMS-$TS" # 4) Saklama süresi find "$BACKUP_DIR" -maxdepth 1 -type f \( -name 'mongo-*.archive.gz' -o -name 'uploads-*.tar.gz' -o -name 'SHA256SUMS-*' \) \ -mtime +"$RETENTION_DAYS" -print -delete | sed 's/^/ silindi: /' log "Tamam: $(du -h "$MONGO_FILE" | cut -f1) veritabanı, $(du -h "$UPLOADS_FILE" | cut -f1) dosya → $BACKUP_DIR"