docfast/scripts/borg-offsite.sh
OpenClaw a1d26b85ec
Some checks failed
Deploy to Production / Deploy to Server (push) Has been cancelled
Add off-site BorgBackup to Hetzner Storage Box
- Separate borg repo on Hetzner Storage Box (repokey-blake2)
- Runs daily at 03:30 UTC (after local backup at 03:00)
- Same data: PG dump, Docker volumes, nginx, SSL, DKIM, app files
- Same retention: 7 daily + 4 weekly + 3 monthly
- Remote: ssh://u149513-sub11@u149513-sub11.your-backup.de:23/./docfast-1
2026-02-16 18:05:44 +00:00

90 lines
2.8 KiB
Bash
Executable file

#!/bin/bash
# DocFast Off-site BorgBackup to Hetzner Storage Box
# Runs AFTER local backup completes (cron: 03:30 UTC)
# Same data & retention as local: 7 daily + 4 weekly + 3 monthly
set -uo pipefail
REMOTE_REPO="ssh://u149513-sub11@u149513-sub11.your-backup.de:23/./docfast-1"
BACKUP_NAME="docfast-$(date +%Y-%m-%d_%H%M)"
LOG_FILE="/var/log/docfast-backup.log"
log() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - [OFFSITE] $1" | tee -a "$LOG_FILE"
}
export BORG_PASSPHRASE="docfast-backup-$(date +%Y)"
export BORG_RELOCATED_REPO_ACCESS_IS_OK=yes
export BORG_RSH="ssh -o StrictHostKeyChecking=no"
# Prepare data (same as local backup script)
TEMP_DIR="/tmp/docfast-backup-offsite-$$"
mkdir -p "$TEMP_DIR"
trap "rm -rf $TEMP_DIR" EXIT
# PostgreSQL dump
log "Dumping PostgreSQL..."
export PGPASSFILE="/root/.pgpass"
pg_dump -h localhost -p 5432 -U docfast -d docfast \
--no-password --clean --if-exists --format=custom \
> "$TEMP_DIR/docfast-db.dump" 2>>"$LOG_FILE" || log "WARNING: PostgreSQL dump failed"
# Docker volumes
mkdir -p "$TEMP_DIR/docker-volumes"
cp -r /var/lib/docker/volumes/* "$TEMP_DIR/docker-volumes/" 2>/dev/null || true
# Nginx
mkdir -p "$TEMP_DIR/nginx"
cp -r /etc/nginx/* "$TEMP_DIR/nginx/" 2>/dev/null || true
# SSL
mkdir -p "$TEMP_DIR/letsencrypt"
cp -r /etc/letsencrypt/* "$TEMP_DIR/letsencrypt/" 2>/dev/null || true
# Crontabs
mkdir -p "$TEMP_DIR/crontabs"
cp -r /var/spool/cron/crontabs/* "$TEMP_DIR/crontabs/" 2>/dev/null || true
crontab -l > "$TEMP_DIR/crontabs/root-crontab.txt" 2>/dev/null || true
# OpenDKIM
mkdir -p "$TEMP_DIR/opendkim"
cp -r /etc/opendkim/* "$TEMP_DIR/opendkim/" 2>/dev/null || true
# App files
mkdir -p "$TEMP_DIR/docfast-app"
cp /opt/docfast/docker-compose.yml "$TEMP_DIR/docfast-app/" 2>/dev/null || true
cp /opt/docfast/.env "$TEMP_DIR/docfast-app/" 2>/dev/null || true
cp -r /opt/docfast/scripts "$TEMP_DIR/docfast-app/" 2>/dev/null || true
cp -r /opt/docfast/deploy "$TEMP_DIR/docfast-app/" 2>/dev/null || true
# System info
mkdir -p "$TEMP_DIR/system"
systemctl list-unit-files --state=enabled > "$TEMP_DIR/system/enabled-services.txt" 2>/dev/null || true
dpkg -l > "$TEMP_DIR/system/installed-packages.txt" 2>/dev/null || true
log "Starting off-site backup: $BACKUP_NAME"
# Create remote backup
borg create \
--stats \
--compression lz4 \
--exclude-caches \
"$REMOTE_REPO::$BACKUP_NAME" \
"$TEMP_DIR" 2>>"$LOG_FILE" || { log "ERROR: Off-site backup creation failed"; exit 1; }
log "Off-site backup created, pruning..."
# Prune (same retention as local)
borg prune \
--list \
--prefix 'docfast-' \
--keep-daily 7 \
--keep-weekly 4 \
--keep-monthly 3 \
"$REMOTE_REPO" 2>>"$LOG_FILE" || log "WARNING: Off-site prune failed"
# Compact
borg compact "$REMOTE_REPO" 2>>"$LOG_FILE" || true
log "Off-site backup completed: $BACKUP_NAME"
borg info "$REMOTE_REPO" 2>>"$LOG_FILE"