migration

This commit is contained in:
2026-04-13 15:54:14 +02:00
parent cb548ee09a
commit 827213c883
17 changed files with 428 additions and 22 deletions

165
scripts/gitea-restore.sh Normal file
View File

@@ -0,0 +1,165 @@
#!/usr/bin/env bash
set -euo pipefail
# Gitea restore helper — restores a gitea-dump zip into a running Gitea deployment
#
# Prerequisites:
# - Gitea deployed on the target cluster (Helm chart via ArgoCD)
# - kubectl context pointing to the target cluster
# - A gitea-dump zip file (from gitea-backup.sh download or CronJob)
#
# Usage:
# ./scripts/gitea-restore.sh <gitea-dump-file.zip>
#
# What it does:
# 1. Scales Gitea down to 0
# 2. Restores the PostgreSQL database from gitea-db.sql
# 3. Restores Git repositories to the data PVC
# 4. Scales Gitea back up
NAMESPACE="gitea"
DEPLOYMENT="gitea"
PG_STATEFULSET="gitea-postgresql"
PVC="gitea-shared-storage"
HELPER_POD="gitea-restore-helper"
HELPER_IMAGE="alpine:3.20"
PG_USER="gitea"
PG_DB="gitea"
DUMP_FILE="${1:?Usage: $0 <gitea-dump-file.zip>}"
if [ ! -f "$DUMP_FILE" ]; then
echo "Error: file not found: $DUMP_FILE"
exit 1
fi
echo "=== Gitea Restore ==="
echo "Dump file: $DUMP_FILE"
echo ""
# --- Safety prompt ---
read -r -p "This will OVERWRITE the Gitea database and repositories on the current cluster. Continue? [y/N] " confirm
if [[ ! "$confirm" =~ ^[Yy]$ ]]; then
echo "Aborted."
exit 0
fi
cleanup() {
kubectl -n "$NAMESPACE" delete pod "$HELPER_POD" --ignore-not-found --grace-period=0 > /dev/null 2>&1 || true
}
trap cleanup EXIT
# --- Step 1: Extract dump locally ---
RESTORE_DIR=$(mktemp -d)
echo ""
echo "[1/5] Extracting dump..."
unzip -q "$DUMP_FILE" -d "$RESTORE_DIR"
# Detect SQL dump file (gitea-db.sql or gitea-dump-*.sql)
SQL_FILE=$(find "$RESTORE_DIR" -maxdepth 1 -name '*.sql' | head -1)
if [ -z "$SQL_FILE" ]; then
echo "Error: no .sql file found in dump."
rm -rf "$RESTORE_DIR"
exit 1
fi
# Detect repos — either a "repos" folder or gitea-repo.zip
if [ -d "$RESTORE_DIR/repos" ]; then
REPOS_SOURCE="dir"
REPOS_PATH="$RESTORE_DIR/repos"
elif [ -f "$RESTORE_DIR/gitea-repo.zip" ]; then
REPOS_SOURCE="zip"
REPOS_PATH="$RESTORE_DIR/gitea-repo.zip"
else
echo "Error: no repos/ directory or gitea-repo.zip found in dump."
rm -rf "$RESTORE_DIR"
exit 1
fi
echo " Found: $(basename "$SQL_FILE") ($(du -h "$SQL_FILE" | cut -f1))"
echo " Found: repos ($REPOS_SOURCE)"
[ -d "$RESTORE_DIR/data" ] && echo " Found: data/"
[ -f "$RESTORE_DIR/app.ini" ] && echo " Found: app.ini (managed by Helm, skipping)"
# --- Step 2: Scale down Gitea ---
echo ""
echo "[2/5] Scaling down Gitea..."
kubectl -n "$NAMESPACE" scale deployment "$DEPLOYMENT" --replicas=0
kubectl -n "$NAMESPACE" rollout status deployment "$DEPLOYMENT" --timeout=60s 2>/dev/null || true
echo " Waiting for pods to terminate..."
kubectl -n "$NAMESPACE" wait --for=delete pod -l app.kubernetes.io/name=gitea --timeout=120s 2>/dev/null || true
echo " Gitea is down."
# --- Step 3: Restore database ---
echo ""
echo "[3/5] Restoring database..."
# Drop and recreate to ensure clean state
kubectl -n "$NAMESPACE" exec "${PG_STATEFULSET}-0" -- \
psql -U "$PG_USER" -d postgres -c "DROP DATABASE IF EXISTS ${PG_DB};" 2>/dev/null
kubectl -n "$NAMESPACE" exec "${PG_STATEFULSET}-0" -- \
psql -U "$PG_USER" -d postgres -c "CREATE DATABASE ${PG_DB} OWNER ${PG_USER};" 2>/dev/null
kubectl -n "$NAMESPACE" exec -i "${PG_STATEFULSET}-0" -- \
psql -U "$PG_USER" -d "$PG_DB" < "$SQL_FILE" > /dev/null
echo " Database restored."
# --- Step 4: Restore repositories ---
echo ""
echo "[4/5] Restoring repositories..."
# Need a helper pod on the same node as the PVC (RWO)
cleanup
kubectl -n "$NAMESPACE" run "$HELPER_POD" --restart=Never \
--image="$HELPER_IMAGE" \
--overrides="{
\"spec\":{
\"containers\":[{
\"name\":\"$HELPER_POD\",
\"image\":\"$HELPER_IMAGE\",
\"command\":[\"sleep\",\"3600\"],
\"volumeMounts\":[{\"name\":\"data\",\"mountPath\":\"/data\"}]
}],
\"volumes\":[{
\"name\":\"data\",
\"persistentVolumeClaim\":{\"claimName\":\"$PVC\"}
}]
}
}" > /dev/null 2>&1
kubectl -n "$NAMESPACE" wait --for=condition=Ready "pod/$HELPER_POD" --timeout=120s > /dev/null 2>&1
# Clear existing repos
kubectl -n "$NAMESPACE" exec "$HELPER_POD" -- sh -c "rm -rf /data/gitea/repositories/*" 2>/dev/null || true
# Upload repos — tar via stdin since kubectl cp needs tar in the container
echo " Uploading repositories..."
if [ "$REPOS_SOURCE" = "dir" ]; then
# repos/ directory — tar and stream into the PVC
tar -cf - -C "$REPOS_PATH" . | kubectl -n "$NAMESPACE" exec -i "$HELPER_POD" -- sh -c "tar -xf - -C /data/gitea/repositories/"
else
# gitea-repo.zip — stream and extract
cat "$REPOS_PATH" | kubectl -n "$NAMESPACE" exec -i "$HELPER_POD" -- sh -c "cat > /tmp/gitea-repo.zip && unzip -q -o /tmp/gitea-repo.zip -d /data/gitea/repositories/ && rm /tmp/gitea-repo.zip"
fi
# Restore data/ directory (avatars, attachments, LFS, etc.) if present
if [ -d "$RESTORE_DIR/data" ]; then
echo " Uploading data (avatars, attachments, LFS)..."
tar -cf - -C "$RESTORE_DIR/data" . | kubectl -n "$NAMESPACE" exec -i "$HELPER_POD" -- sh -c "tar -xf - -C /data/gitea/"
fi
# Fix ownership
kubectl -n "$NAMESPACE" exec "$HELPER_POD" -- chown -R 1000:1000 /data/gitea/
echo " Repositories restored."
# --- Step 5: Scale back up ---
echo ""
echo "[5/5] Scaling Gitea back up..."
kubectl -n "$NAMESPACE" scale deployment "$DEPLOYMENT" --replicas=1
kubectl -n "$NAMESPACE" rollout status deployment "$DEPLOYMENT" --timeout=120s
# Cleanup temp dir
rm -rf "$RESTORE_DIR"
echo ""
echo "=== Restore complete ==="
echo "Gitea should be back online with restored data."
echo "Verify at your Gitea URL that repos and users are present."