#!/bin/bash # ============================================================================= # brain server backup — runs daily via cron # Backs up: app, configs, database, nginx, systemd, SSL, fail2ban, sysctl # Storage: /var/backups/brain/ (borg repo + pg dumps) # Retention: 7 daily, 4 weekly, 3 monthly # ============================================================================= set -euo pipefail BACKUP_DIR="/var/backups/brain" BORG_REPO="$BACKUP_DIR/borg-repo" PG_DIR="$BACKUP_DIR/pg-dumps" LOG="/var/log/brain-backup.log" TIMESTAMP=$(date +%Y-%m-%d_%H%M) export BORG_PASSPHRASE="" log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG"; } log "=== Backup starting ===" # --- PostgreSQL dump --- mkdir -p "$PG_DIR" log "Dumping PostgreSQL knowledge_base..." sudo -u postgres pg_dump -Fc knowledge_base > "$PG_DIR/knowledge_base_${TIMESTAMP}.dump" 2>> "$LOG" # Keep last 14 dumps ls -t "$PG_DIR"/knowledge_base_*.dump 2>/dev/null | tail -n +15 | xargs -r rm -- log " pg_dump OK ($(du -sh "$PG_DIR/knowledge_base_${TIMESTAMP}.dump" | cut -f1))" # --- Borg backup --- log "Running borg backup..." borg create \ --stats \ --compression zstd,3 \ --exclude '*.pyc' \ --exclude '__pycache__' \ --exclude '.git' \ --exclude 'node_modules' \ "$BORG_REPO::${TIMESTAMP}" \ /root/llm_team_ui.py \ /root/llm_team_config.json \ /home/profit/.env \ /etc/nginx/sites-available/ \ /etc/nginx/sites-enabled/ \ /etc/nginx/nginx.conf \ /etc/fail2ban/jail.local \ /etc/fail2ban/jail.d/ \ /etc/ssh/sshd_config \ /etc/sysctl.d/99-security.conf \ /etc/systemd/system/llm-team-ui.service \ /etc/systemd/system/goaccess.service \ /etc/systemd/system/ollama.service \ /etc/systemd/system/minio.service \ /etc/systemd/system/vault.service \ /var/backups/brain/pg-dumps/ \ 2>> "$LOG" log " borg OK" # --- Prune old backups --- log "Pruning old backups..." borg prune \ --keep-daily=7 \ --keep-weekly=4 \ --keep-monthly=3 \ "$BORG_REPO" 2>> "$LOG" borg compact "$BORG_REPO" 2>> "$LOG" log " prune OK" # --- Report --- REPO_SIZE=$(du -sh "$BORG_REPO" | cut -f1) log "=== Backup complete. Repo size: $REPO_SIZE ==="