#!/bin/bash # # Скрипт бэкапа Gitea в LXC контейнере # Запускать ВНУТРИ LXC контейнера # # Создаёт: # - pg_dump базы данных # - gitea dump (репозитории, конфиг, данные) # - Единый архив # set -e # ============================================ # НАСТРОЙКИ # ============================================ # Директория для бэкапов BACKUP_BASE="${BACKUP_BASE:-/var/backups/gitea}" # PostgreSQL DB_USER="${DB_USER:-gitea}" DB_NAME="${DB_NAME:-gitea}" # Gitea пути GITEA_BIN="${GITEA_BIN:-/usr/local/bin/gitea}" GITEA_CONFIG="${GITEA_CONFIG:-/etc/gitea/app.ini}" GITEA_DATA="${GITEA_DATA:-/var/lib/gitea}" # Сколько бэкапов хранить (0 = не удалять старые) KEEP_BACKUPS="${KEEP_BACKUPS:-7}" # Отправка на удалённый сервер (опционально) REMOTE_BACKUP="${REMOTE_BACKUP:-}" # user@host:/path/to/backups # ============================================ # ФУНКЦИИ # ============================================ log() { echo -e "\033[1;32m[$(date '+%Y-%m-%d %H:%M:%S')]\033[0m $1" } warn() { echo -e "\033[1;33m[WARN]\033[0m $1" } error() { echo -e "\033[1;31m[ERROR]\033[0m $1" >&2 exit 1 } cleanup() { if [ -n "$BACKUP_DIR" ] && [ -d "$BACKUP_DIR" ]; then rm -rf "$BACKUP_DIR" fi } trap cleanup EXIT # ============================================ # ПРОВЕРКИ # ============================================ if [ "$EUID" -ne 0 ]; then error "Запустите от root: sudo $0" fi if ! command -v "$GITEA_BIN" &>/dev/null; then error "Gitea не найдена: $GITEA_BIN" fi if ! systemctl is-active --quiet postgresql; then error "PostgreSQL не запущен" fi # ============================================ # ПОДГОТОВКА # ============================================ TIMESTAMP=$(date +%Y%m%d-%H%M%S) BACKUP_DIR="$BACKUP_BASE/gitea-backup-$TIMESTAMP" ARCHIVE_NAME="gitea-backup-$TIMESTAMP.tar.gz" mkdir -p "$BACKUP_DIR" mkdir -p "$BACKUP_BASE" log "==========================================" log " Бэкап Gitea (LXC)" log "==========================================" log "" log "Директория: $BACKUP_DIR" log "Архив: $BACKUP_BASE/$ARCHIVE_NAME" log "" # Сохраняем версию GITEA_VERSION=$("$GITEA_BIN" --version 2>&1 | head -1) echo "$GITEA_VERSION" > "$BACKUP_DIR/gitea-version.txt" log "Версия Gitea: $GITEA_VERSION" # ============================================ # ШАГ 1: ДАМП POSTGRESQL # ============================================ log "Создание дампа PostgreSQL..." sudo -u postgres pg_dump -d "$DB_NAME" --no-owner --no-acl > "$BACKUP_DIR/database.sql" log " ✓ database.sql ($(du -h "$BACKUP_DIR/database.sql" | cut -f1))" # ============================================ # ШАГ 2: ОСТАНОВКА GITEA (для консистентности) # ============================================ GITEA_WAS_RUNNING=false if systemctl is-active --quiet gitea; then GITEA_WAS_RUNNING=true log "Остановка Gitea..." systemctl stop gitea sleep 2 fi # ============================================ # ШАГ 3: GITEA DUMP # ============================================ log "Создание gitea dump..." # gitea dump запускается от пользователя git, поэтому используем его директорию DUMP_TEMP="$GITEA_DATA/tmp-dump" mkdir -p "$DUMP_TEMP" chown git:git "$DUMP_TEMP" # gitea dump создаёт архив с репозиториями и данными sudo -u git "$GITEA_BIN" dump \ --config "$GITEA_CONFIG" \ --work-path "$GITEA_DATA" \ --file "$DUMP_TEMP/gitea-dump.zip" \ --tempdir "$DUMP_TEMP" \ --skip-db \ --type zip 2>&1 | tee "$BACKUP_DIR/dump.log" || { warn "gitea dump завершился с предупреждениями (см. dump.log)" } # Проверяем на фатальные ошибки if grep -q "\[F\]" "$BACKUP_DIR/dump.log" 2>/dev/null; then warn "Обнаружена фатальная ошибка в gitea dump:" grep "\[F\]" "$BACKUP_DIR/dump.log" fi # Перемещаем результат в директорию бэкапа if [ -f "$DUMP_TEMP/gitea-dump.zip" ]; then mv "$DUMP_TEMP/gitea-dump.zip" "$BACKUP_DIR/" log " ✓ gitea-dump.zip ($(du -h "$BACKUP_DIR/gitea-dump.zip" | cut -f1))" else warn "gitea-dump.zip не создан, копируем данные вручную..." cp -a "$GITEA_DATA" "$BACKUP_DIR/data" log " ✓ data/ (ручное копирование)" fi # Очищаем временную директорию rm -rf "$DUMP_TEMP" # ============================================ # ШАГ 4: КОПИРОВАНИЕ КОНФИГУРАЦИИ # ============================================ log "Копирование конфигурации..." cp "$GITEA_CONFIG" "$BACKUP_DIR/app.ini" log " ✓ app.ini" # ============================================ # ШАГ 5: ПЕРЕЗАПУСК GITEA # ============================================ if [ "$GITEA_WAS_RUNNING" = true ]; then log "Запуск Gitea..." systemctl start gitea log " ✓ Gitea запущена" fi # ============================================ # ШАГ 6: СОЗДАНИЕ АРХИВА # ============================================ log "Создание архива..." cd "$BACKUP_BASE" tar -czf "$ARCHIVE_NAME" -C "$BACKUP_BASE" "$(basename $BACKUP_DIR)" ARCHIVE_SIZE=$(du -h "$BACKUP_BASE/$ARCHIVE_NAME" | cut -f1) log " ✓ $ARCHIVE_NAME ($ARCHIVE_SIZE)" # Удаляем временную директорию rm -rf "$BACKUP_DIR" trap - EXIT # ============================================ # ШАГ 7: РОТАЦИЯ СТАРЫХ БЭКАПОВ # ============================================ if [ "$KEEP_BACKUPS" -gt 0 ]; then log "Ротация бэкапов (храним $KEEP_BACKUPS)..." cd "$BACKUP_BASE" ls -t gitea-backup-*.tar.gz 2>/dev/null | tail -n +$((KEEP_BACKUPS + 1)) | xargs -r rm -f CURRENT_COUNT=$(ls -1 gitea-backup-*.tar.gz 2>/dev/null | wc -l) log " ✓ Текущих бэкапов: $CURRENT_COUNT" fi # ============================================ # ШАГ 8: ОТПРАВКА НА УДАЛЁННЫЙ СЕРВЕР # ============================================ if [ -n "$REMOTE_BACKUP" ]; then log "Отправка на удалённый сервер: $REMOTE_BACKUP" if scp "$BACKUP_BASE/$ARCHIVE_NAME" "$REMOTE_BACKUP/"; then log " ✓ Отправлено" else warn "Не удалось отправить бэкап" fi fi # ============================================ # ИТОГИ # ============================================ log "" log "==========================================" log " ✅ Бэкап завершён!" log "==========================================" log "" log "Файл: $BACKUP_BASE/$ARCHIVE_NAME" log "Размер: $ARCHIVE_SIZE" log "" log "Содержимое архива:" log " - database.sql (PostgreSQL дамп)" log " - gitea-dump.zip (репозитории, LFS, данные)" log " - app.ini (конфигурация)" log " - gitea-version.txt" log "" # Возвращаем путь к архиву (для скриптов) echo "$BACKUP_BASE/$ARCHIVE_NAME"