#!/usr/bin/env bash set -euo pipefail # ----------------------------- # Config # ----------------------------- NAMESPACE="default" PG_ENABLED=true PG_SECRET_NAME="postgres-secret" PG_POD_SELECTOR="app=postgres" K8S_STORAGE_ROOT="/k8s_storage" TAR_EXCLUDES=( "$K8S_STORAGE_ROOT/postgres" ) BACKUP_ROOT="/tmp/k8s-backups" DATE="$(date -u +%Y-%m-%d_%H-%M-%S)" BACKUP_DIR="$BACKUP_ROOT/$DATE" mkdir -p "$BACKUP_DIR" echo "=== Backup started at $(date -u) ===" # ----------------------------- # Postgres pg_dump # ----------------------------- if [[ "$PG_ENABLED" == "true" ]]; then echo "=== Postgres pg_dump enabled ===" POSTGRES_POD=$(kubectl get pods \ -n "$NAMESPACE" \ -l "$PG_POD_SELECTOR" \ -o jsonpath='{.items[*].metadata.name}' | awk '{print $1}') if [[ -z "$POSTGRES_POD" ]]; then echo "❌ No Postgres pod found" kubectl get pods -n "$NAMESPACE" exit 1 fi POSTGRES_USER=$(kubectl get secret "$PG_SECRET_NAME" \ -n "$NAMESPACE" \ -o jsonpath='{.data.POSTGRES_USER}' | base64 -d) POSTGRES_DB=$(kubectl get secret "$PG_SECRET_NAME" \ -n "$NAMESPACE" \ -o jsonpath='{.data.POSTGRES_DB}' | base64 -d) echo "Dumping database: $POSTGRES_DB" kubectl exec -n "$NAMESPACE" "$POSTGRES_POD" -- \ pg_dump -U "$POSTGRES_USER" "$POSTGRES_DB" \ > "$BACKUP_DIR/postgres.sql" echo "✔ pg_dump complete ($(du -h "$BACKUP_DIR/postgres.sql" | cut -f1))" fi # ----------------------------- # Normalise permissions (IMPORTANT) # ----------------------------- echo "=== Normalising permissions on $K8S_STORAGE_ROOT ===" # Ensure backup user can read everything, without breaking apps sudo chmod -R a+rX "$K8S_STORAGE_ROOT" || true # ----------------------------- # Build tar exclude args # ----------------------------- TAR_EXCLUDE_ARGS=() for path in "${TAR_EXCLUDES[@]}"; do TAR_EXCLUDE_ARGS+=(--exclude="$path") done # ----------------------------- # Archive k8s storage (safe) # ----------------------------- echo "=== Archiving k8s storage ===" tar \ --ignore-failed-read \ --warning=no-file-changed \ -czf "$BACKUP_DIR/k8s_storage_$DATE.tar.gz" \ "${TAR_EXCLUDE_ARGS[@]}" \ "$K8S_STORAGE_ROOT" echo "✔ k8s_storage archived ($(du -h "$BACKUP_DIR/k8s_storage_$DATE.tar.gz" | cut -f1))" # ----------------------------- # Upload to S3 # ----------------------------- S3_BUCKET="s3://mist-backups/$DATE" aws s3 cp "$BACKUP_DIR" "$S3_BUCKET" --recursive echo "✔ Uploaded to $S3_BUCKET" # ----------------------------- # Restore instructions # ----------------------------- echo "" echo "========================================" echo "=== RESTORE GUIDE" echo "========================================" echo "" echo "Restore volumes:" echo " sudo tar -xzf k8s_storage_$DATE.tar.gz -C /" echo "" echo "Restore Postgres:" echo " kubectl exec -n $NAMESPACE -i $POSTGRES_POD -- \\" echo " psql -U $POSTGRES_USER $POSTGRES_DB < postgres.sql" echo "" echo "=== Backup completed successfully ==="