#!/usr/bin/env bash set -euo pipefail # Восстановление Gitea из архива backup-gitea.sh. # # Пример: # sudo ./scripts/restore-gitea.sh /opt/backups/gitea/gitea-backup-20260421-031000.tar.gz # # По умолчанию: # - target dir: /opt/gitea/data # - create snapshot before restore: yes if [[ $# -lt 1 ]]; then echo "Usage: $0 " exit 1 fi ARCHIVE_PATH="$1" TARGET_DIR="${TARGET_DIR:-/opt/gitea/data}" TAKE_SNAPSHOT_BEFORE_RESTORE="${TAKE_SNAPSHOT_BEFORE_RESTORE:-true}" SNAPSHOT_DIR="${SNAPSHOT_DIR:-/opt/backups/gitea}" DATE_TAG="$(date +%Y%m%d-%H%M%S)" if [[ ! -f "$ARCHIVE_PATH" ]]; then echo "[ERR] Archive not found: $ARCHIVE_PATH" exit 1 fi if [[ "${EUID:-$(id -u)}" -ne 0 ]]; then echo "[ERR] Run as root (sudo)." exit 1 fi echo "[INFO] Restore archive: $ARCHIVE_PATH" echo "[INFO] Target dir: $TARGET_DIR" if [[ "$TAKE_SNAPSHOT_BEFORE_RESTORE" == "true" && -d "$TARGET_DIR" ]]; then mkdir -p "$SNAPSHOT_DIR" SNAPSHOT_PATH="${SNAPSHOT_DIR}/gitea-pre-restore-${DATE_TAG}.tar.gz" echo "[INFO] Creating pre-restore snapshot: $SNAPSHOT_PATH" tar -C "$(dirname "$TARGET_DIR")" -czf "$SNAPSHOT_PATH" "$(basename "$TARGET_DIR")" fi if command -v docker >/dev/null 2>&1; then if [[ -f /opt/gitea/docker-compose.yml ]]; then echo "[INFO] Stopping Gitea container..." (cd /opt/gitea && docker compose stop gitea) fi fi TMP_DIR="$(mktemp -d)" trap 'rm -rf "$TMP_DIR"' EXIT echo "[INFO] Extracting archive..." tar -C "$TMP_DIR" -xzf "$ARCHIVE_PATH" if [[ ! -d "$TMP_DIR/data" ]]; then echo "[ERR] Archive structure is invalid: expected 'data/' root folder" exit 1 fi echo "[INFO] Restoring files to $TARGET_DIR" rm -rf "$TARGET_DIR" mkdir -p "$(dirname "$TARGET_DIR")" mv "$TMP_DIR/data" "$TARGET_DIR" # Чаще всего Gitea в контейнере работает как uid/gid 1000. chown -R 1000:1000 "$TARGET_DIR" || true if command -v docker >/dev/null 2>&1; then if [[ -f /opt/gitea/docker-compose.yml ]]; then echo "[INFO] Starting Gitea container..." (cd /opt/gitea && docker compose up -d gitea) fi fi echo "[OK] Restore completed"