Files
gitea-backup/backup-scripts/restore-gitea.sh
2026-01-06 22:12:07 +05:00

495 lines
18 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
#
# Скрипт восстановления Gitea из бэкапа
# Основан на рекомендациях: https://docs.gitea.com/administration/backup-and-restore
#
# Поддерживает:
# - Архивы созданные через `gitea dump`
# - Нативные дампы PostgreSQL
# - Ручные бэкапы директорий
#
# База данных: PostgreSQL
# Запускать в LXC контейнере ПОСЛЕ установки Gitea
#
set -e
# ============================================
# НАСТРОЙКИ
# ============================================
# Путь к архиву бэкапа
BACKUP_ARCHIVE="${1:-}"
# Новый домен/IP (оставьте пустым для автоопределения)
NEW_DOMAIN="${NEW_DOMAIN:-$(hostname -I | awk '{print $1}')}"
# Новый порт
NEW_PORT="${NEW_PORT:-3000}"
# Credentials для PostgreSQL
DB_USER="${DB_USER:-gitea}"
DB_NAME="${DB_NAME:-gitea}"
DB_PASSWORD="${DB_PASSWORD:-gitea}"
DB_HOST="${DB_HOST:-127.0.0.1}"
# Пути Gitea (для нативной установки в LXC)
# Согласно https://docs.gitea.com/administration/backup-and-restore#restore-command-restore
GITEA_USER="git"
GITEA_HOME="/home/git"
GITEA_WORK_DIR="/var/lib/gitea"
GITEA_CONFIG="/etc/gitea/app.ini"
GITEA_CUSTOM="/var/lib/gitea/custom"
GITEA_DATA="/var/lib/gitea/data"
GITEA_REPOS="/var/lib/gitea/data/gitea-repositories"
GITEA_LOG="/var/lib/gitea/log"
GITEA_BIN="/usr/local/bin/gitea"
# ============================================
# ФУНКЦИИ
# ============================================
log() {
echo -e "\033[1;32m[$(date '+%H:%M:%S')]\033[0m $1"
}
warn() {
echo -e "\033[1;33m[WARNING]\033[0m $1"
}
error() {
echo -e "\033[1;31m[ERROR]\033[0m $1" >&2
exit 1
}
# ============================================
# ПРОВЕРКИ
# ============================================
if [ "$EUID" -ne 0 ]; then
error "Запустите скрипт от root: sudo $0 /path/to/backup.tar.gz"
fi
if [ -z "$BACKUP_ARCHIVE" ]; then
echo "Использование: $0 <путь_к_архиву_бэкапа>"
echo ""
echo "Примеры:"
echo " $0 /tmp/gitea-backup-20240115-120000.tar.gz"
echo ""
echo "Переменные окружения:"
echo " NEW_DOMAIN - новый домен/IP для Gitea (default: auto)"
echo " NEW_PORT - HTTP порт (default: 3000)"
echo " DB_USER - пользователь PostgreSQL (default: gitea)"
echo " DB_PASSWORD - пароль PostgreSQL (default: gitea)"
exit 1
fi
if [ ! -f "$BACKUP_ARCHIVE" ]; then
error "Файл бэкапа не найден: $BACKUP_ARCHIVE"
fi
# Установка необходимых утилит
log "Проверка зависимостей..."
if ! command -v unzip &> /dev/null; then
log " Установка unzip..."
apt-get update -qq && apt-get install -y -qq unzip
fi
log "=========================================="
log " Восстановление Gitea из бэкапа"
log "=========================================="
log ""
log "Архив: $BACKUP_ARCHIVE"
log "Новый домен: $NEW_DOMAIN"
log "Новый порт: $NEW_PORT"
log "База данных: PostgreSQL ($DB_USER@$DB_NAME)"
log ""
# ============================================
# РАСПАКОВКА
# ============================================
log "Распаковка архива..."
TEMP_DIR=$(mktemp -d)
cd "$TEMP_DIR"
# Определяем тип архива и распаковываем
case "$BACKUP_ARCHIVE" in
*.tar.gz|*.tgz)
tar -xzf "$BACKUP_ARCHIVE"
;;
*.zip)
unzip -q "$BACKUP_ARCHIVE"
;;
*)
tar -xf "$BACKUP_ARCHIVE" 2>/dev/null || unzip -q "$BACKUP_ARCHIVE" 2>/dev/null
;;
esac
# Находим директорию с данными
BACKUP_DIR=$(find . -maxdepth 1 -type d -name "gitea-backup*" | head -1)
if [ -z "$BACKUP_DIR" ] || [ "$BACKUP_DIR" = "." ]; then
BACKUP_DIR="."
fi
log "Директория бэкапа: $BACKUP_DIR"
log "Содержимое:"
ls -la "$BACKUP_DIR"
echo ""
# ============================================
# ОСТАНОВКА GITEA
# ============================================
log "Остановка Gitea..."
systemctl stop gitea 2>/dev/null || true
sleep 2
# ============================================
# ОПРЕДЕЛЕНИЕ ТИПА БЭКАПА
# ============================================
log "Анализ бэкапа..."
# Читаем информацию о версии
if [ -f "$BACKUP_DIR/gitea-version.txt" ]; then
OLD_VERSION=$(cat "$BACKUP_DIR/gitea-version.txt")
log " Версия Gitea в бэкапе: $OLD_VERSION"
fi
# Проверяем наличие gitea dump архива
GITEA_DUMP=""
for ext in zip tar.gz; do
if [ -f "$BACKUP_DIR/gitea-dump.$ext" ]; then
GITEA_DUMP="$BACKUP_DIR/gitea-dump.$ext"
break
fi
done
# Или ищем по паттерну
if [ -z "$GITEA_DUMP" ]; then
GITEA_DUMP=$(find "$BACKUP_DIR" -name "gitea-dump-*.zip" -o -name "gitea-dump-*.tar.gz" 2>/dev/null | head -1)
fi
if [ -n "$GITEA_DUMP" ]; then
log " Найден gitea dump: $(basename $GITEA_DUMP)"
fi
# Проверяем нативный дамп PostgreSQL
NATIVE_DB_DUMP=""
if [ -f "$BACKUP_DIR/gitea-db-native.sql" ]; then
NATIVE_DB_DUMP="$BACKUP_DIR/gitea-db-native.sql"
log " Найден нативный дамп PostgreSQL: gitea-db-native.sql"
fi
# ============================================
# ВОССТАНОВЛЕНИЕ POSTGRESQL
# ============================================
log "Восстановление базы данных PostgreSQL..."
if [ -n "$NATIVE_DB_DUMP" ]; then
log " Восстановление из нативного дампа..."
# Пересоздаём БД
sudo -u postgres psql -c "DROP DATABASE IF EXISTS $DB_NAME;" 2>/dev/null || true
sudo -u postgres psql -c "CREATE DATABASE $DB_NAME OWNER $DB_USER;" 2>/dev/null || \
sudo -u postgres psql -c "CREATE DATABASE $DB_NAME;" 2>/dev/null
# Импортируем
PGPASSWORD="$DB_PASSWORD" psql -U "$DB_USER" -h "$DB_HOST" -d "$DB_NAME" < "$NATIVE_DB_DUMP"
log " ✓ PostgreSQL база восстановлена"
else
# Пробуем из gitea dump
if [ -n "$GITEA_DUMP" ]; then
DUMP_TEMP=$(mktemp -d)
case "$GITEA_DUMP" in
*.zip) unzip -q "$GITEA_DUMP" -d "$DUMP_TEMP" ;;
*.tar.gz) tar -xzf "$GITEA_DUMP" -C "$DUMP_TEMP" ;;
esac
SQL_FILE=$(find "$DUMP_TEMP" -name "gitea-db.sql" 2>/dev/null | head -1)
if [ -n "$SQL_FILE" ]; then
warn " Используем дамп из gitea dump (рекомендуется нативный)"
sudo -u postgres psql -c "DROP DATABASE IF EXISTS $DB_NAME;" 2>/dev/null || true
sudo -u postgres psql -c "CREATE DATABASE $DB_NAME OWNER $DB_USER;" 2>/dev/null
PGPASSWORD="$DB_PASSWORD" psql -U "$DB_USER" -h "$DB_HOST" -d "$DB_NAME" < "$SQL_FILE"
log " ✓ PostgreSQL база восстановлена из gitea dump"
else
warn " SQL дамп не найден в бэкапе"
fi
else
warn " Дамп базы данных не найден!"
fi
fi
# ============================================
# ВОССТАНОВЛЕНИЕ ДАННЫХ ИЗ GITEA DUMP
# Согласно: https://docs.gitea.com/administration/backup-and-restore#restore-command-restore
# Структура gitea dump:
# - app.ini (опционально)
# - custom/ - кастомизации
# - data/ - данные (attachments, avatars, lfs, indexers)
# - repos/ - репозитории
# - gitea-db.sql - дамп БД
# - log/ - логи (не нужны для восстановления)
# ============================================
if [ -n "$GITEA_DUMP" ]; then
log "Восстановление данных из gitea dump..."
# Убедимся что архив распакован
if [ -z "$DUMP_TEMP" ]; then
DUMP_TEMP=$(mktemp -d)
case "$GITEA_DUMP" in
*.zip) unzip -q "$GITEA_DUMP" -d "$DUMP_TEMP" ;;
*.tar.gz) tar -xzf "$GITEA_DUMP" -C "$DUMP_TEMP" ;;
esac
fi
log " Содержимое gitea dump:"
ls -la "$DUMP_TEMP"
echo ""
# Создаём необходимые директории
mkdir -p "$GITEA_DATA" "$GITEA_REPOS" "$GITEA_CUSTOM" "$GITEA_LOG"
# 1. Репозитории: repos/ -> GITEA_REPOS
if [ -d "$DUMP_TEMP/repos" ]; then
log " → Репозитории (repos/ -> $GITEA_REPOS)..."
cp -r "$DUMP_TEMP/repos/"* "$GITEA_REPOS/" 2>/dev/null || true
log " Скопировано: $(ls -1 "$GITEA_REPOS" 2>/dev/null | wc -l) элементов"
else
warn " Директория repos/ не найдена в dump"
fi
# 2. Data директория: data/ -> GITEA_DATA
if [ -d "$DUMP_TEMP/data" ]; then
log " → Data директория (data/ -> $GITEA_DATA)..."
for item in "$DUMP_TEMP/data/"*; do
if [ -e "$item" ]; then
item_name=$(basename "$item")
if [ "$item_name" != "conf" ]; then
cp -r "$item" "$GITEA_DATA/" 2>/dev/null || true
fi
fi
done
log " Скопировано в data/"
fi
# 3. Custom директория: custom/ -> GITEA_CUSTOM
if [ -d "$DUMP_TEMP/custom" ]; then
log " → Custom директория (custom/ -> $GITEA_CUSTOM)..."
cp -r "$DUMP_TEMP/custom/"* "$GITEA_CUSTOM/" 2>/dev/null || true
fi
# 4. Логи: log/ -> GITEA_LOG (опционально)
if [ -d "$DUMP_TEMP/log" ]; then
log " → Логи (log/ -> $GITEA_LOG)..."
cp -r "$DUMP_TEMP/log/"* "$GITEA_LOG/" 2>/dev/null || true
fi
# 5. LFS данные (если отдельно)
if [ -d "$DUMP_TEMP/lfs" ]; then
log " → LFS данные..."
mkdir -p "$GITEA_DATA/lfs"
cp -r "$DUMP_TEMP/lfs/"* "$GITEA_DATA/lfs/" 2>/dev/null || true
fi
log " ✓ Данные из gitea dump восстановлены"
fi
# ============================================
# ВОССТАНОВЛЕНИЕ ИЗ РУЧНОГО БЭКАПА (fallback)
# ============================================
if [ -z "$GITEA_DUMP" ] && [ -d "$BACKUP_DIR/data" ]; then
log "Восстановление из ручного бэкапа..."
# Репозитории
for repo_dir in "gitea-repositories" "git/repositories" "repositories"; do
if [ -d "$BACKUP_DIR/data/$repo_dir" ]; then
log " → Репозитории ($repo_dir)..."
mkdir -p "$GITEA_REPOS"
cp -r "$BACKUP_DIR/data/$repo_dir/"* "$GITEA_REPOS/" 2>/dev/null || true
break
fi
done
# Остальные данные
for subdir in avatars attachments lfs packages; do
if [ -d "$BACKUP_DIR/data/$subdir" ]; then
log "$subdir..."
mkdir -p "$GITEA_DATA/$subdir"
cp -r "$BACKUP_DIR/data/$subdir/"* "$GITEA_DATA/$subdir/" 2>/dev/null || true
fi
done
fi
# ============================================
# ВОССТАНОВЛЕНИЕ КОНФИГУРАЦИИ
# ============================================
log "Восстановление конфигурации..."
if [ -f "$BACKUP_DIR/app.ini" ]; then
# Сохраняем бэкап текущего конфига
if [ -f "$GITEA_CONFIG" ]; then
cp "$GITEA_CONFIG" "$GITEA_CONFIG.new-install-backup"
fi
# Копируем конфиг из бэкапа
cp "$BACKUP_DIR/app.ini" "$GITEA_CONFIG"
log " ✓ app.ini восстановлен"
fi
# ============================================
# ОБНОВЛЕНИЕ КОНФИГУРАЦИИ ДЛЯ НОВОГО СЕРВЕРА
# ============================================
log "Обновление конфигурации для нового сервера..."
if [ -f "$GITEA_CONFIG" ]; then
log " Исходный app.ini:"
grep -E "^(DOMAIN|ROOT_URL|ROOT|WORK_PATH|RUN_USER|HOST)\s*=" "$GITEA_CONFIG" 2>/dev/null | head -10 || true
echo ""
# === [server] секция ===
sed -i "s|^DOMAIN\s*=.*|DOMAIN = $NEW_DOMAIN|" "$GITEA_CONFIG"
sed -i "s|^SSH_DOMAIN\s*=.*|SSH_DOMAIN = $NEW_DOMAIN|" "$GITEA_CONFIG"
sed -i "s|^ROOT_URL\s*=.*|ROOT_URL = http://$NEW_DOMAIN:$NEW_PORT/|" "$GITEA_CONFIG"
sed -i "s|^HTTP_PORT\s*=.*|HTTP_PORT = $NEW_PORT|" "$GITEA_CONFIG"
# === [repository] секция ===
sed -i "s|^ROOT\s*=.*/git/repositories.*|ROOT = $GITEA_REPOS|" "$GITEA_CONFIG"
sed -i "s|^ROOT\s*=.*/data/git/repositories.*|ROOT = $GITEA_REPOS|" "$GITEA_CONFIG"
sed -i "s|^ROOT\s*=.*/gitea-repositories.*|ROOT = $GITEA_REPOS|" "$GITEA_CONFIG"
# === Глобальные пути ===
sed -i "s|^WORK_PATH\s*=.*/var/lib/gitea.*|WORK_PATH = $GITEA_WORK_DIR|" "$GITEA_CONFIG"
sed -i "s|^WORK_PATH\s*=.*/data.*|WORK_PATH = $GITEA_WORK_DIR|" "$GITEA_CONFIG"
sed -i "s|^WORK_PATH\s*=.*/app/gitea.*|WORK_PATH = $GITEA_WORK_DIR|" "$GITEA_CONFIG"
# === [database] секция - PostgreSQL ===
sed -i "s|^HOST\s*=.*db:.*|HOST = $DB_HOST:5432|" "$GITEA_CONFIG"
sed -i "s|^HOST\s*=.*gitea-db.*|HOST = $DB_HOST:5432|" "$GITEA_CONFIG"
# === [log] секция ===
sed -i "s|^ROOT_PATH\s*=.*/log.*|ROOT_PATH = $GITEA_LOG|" "$GITEA_CONFIG"
# === [server] LFS ===
sed -i "s|^LFS_CONTENT_PATH\s*=.*|LFS_CONTENT_PATH = $GITEA_DATA/lfs|" "$GITEA_CONFIG"
# === [security] секция ===
sed -i "s|^INSTALL_LOCK\s*=.*|INSTALL_LOCK = true|" "$GITEA_CONFIG"
# === Глобальные настройки ===
sed -i "s|^RUN_USER\s*=.*|RUN_USER = $GITEA_USER|" "$GITEA_CONFIG"
log " Обновлённый app.ini:"
grep -E "^(DOMAIN|ROOT_URL|ROOT|WORK_PATH|RUN_USER|HOST)\s*=" "$GITEA_CONFIG" 2>/dev/null | head -10 || true
echo ""
log " ✓ Конфигурация обновлена"
log " Domain: $NEW_DOMAIN"
log " Port: $NEW_PORT"
log " Repos: $GITEA_REPOS"
fi
# ============================================
# ПРАВА ДОСТУПА
# ============================================
log "Установка прав доступа..."
chown -R $GITEA_USER:$GITEA_USER "$GITEA_WORK_DIR"
chown -R $GITEA_USER:$GITEA_USER "$GITEA_HOME" 2>/dev/null || true
chown root:$GITEA_USER "$GITEA_CONFIG"
chmod 640 "$GITEA_CONFIG"
chmod -R 750 "$GITEA_REPOS" 2>/dev/null || true
log " ✓ Права установлены"
# ============================================
# РЕГЕНЕРАЦИЯ SSH КЛЮЧЕЙ
# ============================================
log "Регенерация SSH authorized_keys..."
mkdir -p "$GITEA_HOME/.ssh"
touch "$GITEA_HOME/.ssh/authorized_keys"
chown -R $GITEA_USER:$GITEA_USER "$GITEA_HOME/.ssh"
chmod 700 "$GITEA_HOME/.ssh"
chmod 600 "$GITEA_HOME/.ssh/authorized_keys"
sudo -u $GITEA_USER $GITEA_BIN admin regenerate keys -c "$GITEA_CONFIG" 2>/dev/null && \
log " ✓ SSH ключи регенерированы" || \
warn " Не удалось регенерировать SSH ключи (возможно нет пользователей с ключами)"
# ============================================
# РЕГЕНЕРАЦИЯ GIT HOOKS (КРИТИЧНО!)
# Согласно документации: ./gitea admin regenerate hooks
# Без этого git push не будет работать!
# ============================================
log "Регенерация Git hooks..."
sudo -u $GITEA_USER $GITEA_BIN admin regenerate hooks -c "$GITEA_CONFIG" 2>/dev/null && \
log " ✓ Git hooks регенерированы" || \
warn " Не удалось регенерировать hooks (выполните вручную после запуска)"
# ============================================
# ОЧИСТКА
# ============================================
log "Очистка временных файлов..."
rm -rf "$TEMP_DIR"
[ -n "$DUMP_TEMP" ] && rm -rf "$DUMP_TEMP"
# ============================================
# ЗАПУСК GITEA
# ============================================
log "Запуск Gitea..."
systemctl start gitea
sleep 3
if systemctl is-active --quiet gitea; then
log "✅ Gitea успешно запущена!"
else
warn "Gitea не запустилась автоматически"
echo ""
echo "Проверьте логи:"
echo " journalctl -u gitea -e"
echo " cat $GITEA_WORK_DIR/log/gitea.log"
fi
# ============================================
# ИТОГИ
# ============================================
echo ""
echo "=========================================="
echo " ✅ Восстановление завершено!"
echo "=========================================="
echo ""
echo " Gitea доступна: http://$NEW_DOMAIN:$NEW_PORT"
echo ""
echo " Конфигурация: $GITEA_CONFIG"
echo " Данные: $GITEA_WORK_DIR"
echo ""
echo " Проверьте:"
echo " ☐ Авторизация пользователей"
echo " ☐ Список репозиториев"
echo " ☐ Git clone/push операции"
echo " ☐ Webhooks (если используются)"
echo ""
echo " Если есть проблемы, выполните:"
echo " sudo -u git $GITEA_BIN doctor check --all --fix -c $GITEA_CONFIG"
echo " sudo -u git $GITEA_BIN admin regenerate hooks -c $GITEA_CONFIG"
echo ""
echo " Логи: journalctl -u gitea -f"
echo ""
echo "=========================================="