This commit is contained in:
2026-01-06 22:12:07 +05:00
commit 12f57baa26
13 changed files with 3110 additions and 0 deletions

494
backup-scripts/restore-gitea.sh Executable file
View File

@@ -0,0 +1,494 @@
#!/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 "=========================================="