# Self-hosted Supabase for Caterium (Timeweb Cloud Server) Target: `https://api.caterium.ru` — replaces `https://cksuehzcimitsxmeloes.supabase.co`. This directory is deployable as-is on a fresh Ubuntu 22.04/24.04 **Timeweb Cloud Server (VPS with root)**. It CANNOT run on the existing `timeweb-caterium` shared-hosting SSH account (`ci503744@vh470.timeweb.ru`) — that account has no root, sudo is disabled (`no_new_privileges`), and there is no Docker daemon. Shared hosting is fine for serving the static frontend (`public/`) but architecturally cannot host Postgres/Kong/ GoTrue/PostgREST/Realtime/Storage containers. ## What's here | File | Purpose | |---|---| | `bootstrap-server.sh` | Run once (as root) on a fresh Cloud Server. Installs Docker, Docker Compose plugin, Caddy, ufw rules, clones this config, brings the stack up. | | `docker-compose.yml` | The Supabase stack: db, kong, auth, rest, realtime, storage, meta, functions, studio, imgproxy. | | `.env.example` | Every secret/setting the stack needs. Copy to `.env`, fill in, `chmod 600`. Never commit the real `.env`. | | `volumes/api/kong.yml` | Kong declarative routing for `/rest/v1`, `/auth/v1`, `/storage/v1`, `/realtime/v1`, `/functions/v1`. | | `volumes/db/init/` | One-time SQL run by the Postgres container on first boot (roles, `pg_cron`/extensions, JWT hook wiring). | | `Caddyfile` | Reverse proxy for `api.caterium.ru`: automatic HTTPS (Let's Encrypt), WebSocket upgrade for Realtime, large upload limits for Storage, header forwarding. | | `scripts/01-dump-old.sh` | Runs against the OLD Supabase project. Produces `roles.sql`, `schema.sql`, `data.sql` via `supabase db dump`. | | `scripts/02-restore-new.sh` | Restores those dumps into the new self-hosted Postgres via `psql`. | | `scripts/03-verify-counts.sql` | Row-count comparison old vs new (auth.users, orders, order_items, clients, catalog_items, storage.objects). | | `scripts/04-deploy-edge-function.sh` | Copies `supabase/functions/caterium-create-employee` and `caterium-platform-auth-admin` into the running `functions` container's mounted volume and reloads it. | | `scripts/05-storage-sync.sh` | Copies Storage objects (binary files) from the old project's Storage S3-compatible/API to the new bucket, preserving paths. | ## Order of operations 1. Provision the Cloud Server (see "Manual step required" below). Point DNS `api.caterium.ru` A-record at its IP. 2. `scp` this whole `ops/supabase-selfhosted/` directory to the server, or `git clone` the repo there. 3. `sudo bash bootstrap-server.sh` — installs Docker/Caddy, brings up the stack with placeholder secrets. 4. Fill in real secrets in `.env` (JWT secret, DB password, SMTP, dashboard user/pass) — generate fresh ones with `openssl rand -base64 32` unless told to reuse the old JWT secret. `docker compose up -d` again to apply. 5. Run `scripts/01-dump-old.sh` (needs `OLD_DB_URL` — the old project's Postgres connection string with password, from Supabase Dashboard → Project Settings → Database → Connection string → URI, "session pooler" disabled, direct connection). 6. Run `scripts/02-restore-new.sh` against the new stack's `db` container. 7. Run `scripts/03-verify-counts.sql` old vs new and compare against the expected counts (14 / 11 / 53 / 52 / 460 / 18). 8. Run `scripts/05-storage-sync.sh` to copy the 18 Storage objects and their metadata/policies. 9. Run `scripts/04-deploy-edge-function.sh` to bring `caterium-create-employee` online, verify with a test call. 10. Only after 5-9 pass: flip `DEFAULT_SUPABASE_URL` in `public/app-runtime.js`, ship the `localStorage` migration shim (see `ops/supabase-selfhosted/frontend-cutover.md`), commit to `main`, let CI promote to `production`. ## Manual step required right now (nothing beyond this is blocked) I do not have a Timeweb Cloud API token or root SSH credentials to any Timeweb **Cloud Server** (VPS) — only to the existing shared-hosting account used for the static frontend, which cannot run Docker. To unblock steps 1-10: **Either** - **(A)** In the Timeweb Cloud panel (https://timeweb.cloud/), create a Cloud Server: Ubuntu 22.04, minimum 2 vCPU / 4 GB RAM / 50 GB NVMe (recommended: 4 vCPU / 8 GB for headroom), public IPv4, and add my SSH public key as an authorized key OR give me the root password so I can add my own key. Then tell me the server's IP. - **(B)** Generate a Timeweb Cloud API token (panel → API → "Токены доступа" → create token with Cloud Servers write scope) and give it to me; I will provision the server via the Timeweb API myself (`POST https://api.timeweb.cloud/api/v1/servers`). Whichever you pick, also add a DNS A-record: `api.caterium.ru` → the new server's IP (in whatever DNS provider currently hosts `caterium.ru`'s zone — outside Cloudflare per your instruction not to put Cloudflare in the backend path). **Separately**, to actually migrate the data (step 5), I need the OLD Supabase project's direct Postgres connection string with the real database password (Supabase Dashboard → Project Settings → Database → Connection string → URI, non-pooled). I cannot retrieve this myself — it's not in any file on this machine and I won't ask you to paste a password into a browser form on my behalf. Paste the connection string here in chat, or set it as `OLD_DB_URL` in the shell before I run `scripts/01-dump-old.sh` for you. If you'd rather I don't see the raw password in chat, run `scripts/01-dump-old.sh` yourself with `OLD_DB_URL` exported and send me the three resulting `.sql` files (or their location on this machine) and I'll take it from there. I will use a **freshly generated JWT secret** for the new stack (per your instruction that this is acceptable) — existing sessions will be invalidated and all 14 users will need to log in once more with their existing email+password (which migrate unchanged, since `auth.users.encrypted_password` is copied byte-for-byte from the dump).