Full production-ready docker-compose stack (db, kong, auth, rest, realtime, storage, imgproxy, meta, functions, studio) targeting api.caterium.ru, plus bootstrap script for a fresh Cloud Server, Caddy reverse-proxy config (HTTPS, WebSocket, upload limits), and dump/restore/verify/storage-sync scripts for moving off the managed Supabase project (cksuehzcimitsxmeloes). Does not touch public/ or any live runtime behavior — frontend cutover is documented separately in frontend-cutover.md and only applied after Etap 8 verification. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
55 lines
2.3 KiB
Bash
55 lines
2.3 KiB
Bash
#!/bin/bash
|
|
# Copies Storage objects (binary files) from the OLD managed Supabase project's Storage
|
|
# API to the new self-hosted Storage API, preserving bucket names, object paths and
|
|
# content-type. Bucket definitions + storage.objects METADATA rows are already restored
|
|
# by 02-restore-new.sh (they live in the `storage` schema, covered by schema.sql/data.sql)
|
|
# — this script only moves the actual binary blobs, which live outside Postgres.
|
|
set -euo pipefail
|
|
|
|
: "${OLD_SUPABASE_URL:?e.g. https://cksuehzcimitsxmeloes.supabase.co}"
|
|
: "${OLD_SERVICE_ROLE_KEY:?Old project's service_role key (Dashboard -> Project Settings -> API)}"
|
|
: "${NEW_SUPABASE_URL:?e.g. https://api.caterium.ru}"
|
|
: "${NEW_SERVICE_ROLE_KEY:?New stack's SERVICE_ROLE_KEY from .env}"
|
|
|
|
TMP_DIR="$(mktemp -d)"
|
|
trap 'rm -rf "$TMP_DIR"' EXIT
|
|
|
|
echo "== Listing buckets on OLD project =="
|
|
BUCKETS=$(curl -sf "$OLD_SUPABASE_URL/storage/v1/bucket" \
|
|
-H "Authorization: Bearer $OLD_SERVICE_ROLE_KEY" \
|
|
-H "apikey: $OLD_SERVICE_ROLE_KEY" | jq -r '.[].id')
|
|
|
|
for bucket in $BUCKETS; do
|
|
echo "== Bucket: $bucket =="
|
|
OBJECTS=$(curl -sf -X POST "$OLD_SUPABASE_URL/storage/v1/object/list/$bucket" \
|
|
-H "Authorization: Bearer $OLD_SERVICE_ROLE_KEY" \
|
|
-H "apikey: $OLD_SERVICE_ROLE_KEY" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"limit": 1000, "offset": 0, "prefix": ""}' | jq -r '.[] | select(.id != null) | .name')
|
|
|
|
count=0
|
|
while IFS= read -r path; do
|
|
[ -z "$path" ] && continue
|
|
local_file="$TMP_DIR/$(basename "$path")"
|
|
curl -sf "$OLD_SUPABASE_URL/storage/v1/object/$bucket/$path" \
|
|
-H "Authorization: Bearer $OLD_SERVICE_ROLE_KEY" \
|
|
-H "apikey: $OLD_SERVICE_ROLE_KEY" \
|
|
-o "$local_file"
|
|
|
|
curl -sf -X POST "$NEW_SUPABASE_URL/storage/v1/object/$bucket/$path" \
|
|
-H "Authorization: Bearer $NEW_SERVICE_ROLE_KEY" \
|
|
-H "apikey: $NEW_SERVICE_ROLE_KEY" \
|
|
-H "x-upsert: true" \
|
|
--data-binary "@$local_file" > /dev/null
|
|
|
|
rm -f "$local_file"
|
|
count=$((count + 1))
|
|
echo " copied: $bucket/$path"
|
|
done <<< "$OBJECTS"
|
|
echo " -> $count object(s) copied for bucket $bucket"
|
|
done
|
|
|
|
echo ""
|
|
echo "Done. Spot-check: open a known photo URL under $NEW_SUPABASE_URL/storage/v1/object/public/<bucket>/<path>"
|
|
echo "and confirm it renders identically to the old one."
|