The repository is owned by the organisation `public`, not by the user `igor`.
Gitea forwards the old address for anything a browser or git does, so the install
command and the clone lines kept working and the wrong address went unnoticed.
An API call is the exception. A POST to `/api/v1/repos/igor/supaspin/...` is
answered with a redirect that curl does not follow for a POST, so the command
returns an empty body and no error - which reads as a rejected token. Creating
the v1.2.0 tag and opening its pull request both failed this way first.
- CLAUDE.md: the tagging rule now names `public` and says why an API address
cannot use the forwarded one.
- README.md, install.sh: the install, token and clone commands now use the
address the server actually serves.
Version 1.2.0 -> 1.2.1. No change to what the program does.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- install.sh said "Installed supaspin supaspin 1.1.0." because --version now includes the name; it now says
"Installed supaspin 1.1.1."
- CLAUDE.md: tells AI agents to read Igor's global rules first, and states the versioning rule (number in VERSION,
code and README together, semantic versioning, major bumps only with Igor's yes, a git tag vX.Y.Z after every merge)
- version 1.1.0 -> 1.1.1
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds a terminal app that creates, lists, shows and deletes numbered Supabase
instances on a single-node microk8s server, for testing and staging copies of
any app. Nothing in it is specific to one app.
- supaspin: single-file Python app (menu and commands: create, list, show,
env, tunnel, delete, mail, setup). Instance N gets namespace supaspin-N,
hostname slot N, Postgres on <LAN IP>:544N and Studio on <LAN IP>:300N.
Lowest free number is reused; a refused create says why.
- Disk: fixed-size ext4 image files, loop-mounted from /etc/fstab. db 2 GB,
storage 1 GB, functions/snippets/deno/pgsodium 256 MB each. imgproxy mounts
the storage volume (the chart's own imgproxy volume cannot see uploads, so
image resizing failed). Empty mount points are made read-only until mounted
so a pod started early after a reboot cannot initialise a database there.
- Memory: limits 5.625 GiB, requests 1.875 GiB per instance, all 12 services.
Half of a production setup, except analytics (768 MiB) and realtime
(384 MiB), which were killed for running out of memory at half of it.
- Priority class supaspin-low (-100, never preempts) on every instance pod.
- Public HTTPS through the existing nginx ingress with Let's Encrypt. The
Studio and pg-meta routes are cut out of the Kong gateway config by a
post-renderer, which also pins the db and studio pods to fixed host ports.
- Certificates: delete keeps the TLS secret (with its cert-manager issuer
annotations) in namespace supaspin-certs and create restores it, so
create/delete cycles do not hit Let's Encrypt's 5-per-week limit.
- Secrets generated per instance: JWT secret, anon and service keys, Postgres
and Studio passwords, realtime/meta/logflare keys. The rendered values file
is removed after install; secrets are never written through kubectl apply.
- Instance .env (mode 600) with the usual Supabase variable names, plus an SSH
tunnel command and DATABASE_URL help.
- Delete is idempotent and finds the real mounts instead of trusting a list,
so half-created and older instances clean up completely. A failed create
offers to run it.
- Mail settings: saved defaults changeable from the menu; create asks to use
them or enter different ones for that instance.
- install.sh: installs the app; accepts a Gitea token or a local checkout
because git.didgibot.com requires sign-in even for public repositories.
uninstall.sh: removes the app and, after confirmation, every instance.
- tests: 30 unittest cases (numbering, ports, JWT signing, values, .env,
fstab handling, post-renderer, certificate secret handling).
- README: install, first-run setup, menu, tunnel, troubleshooting, uninstall.
Pinned chart: supabase-community/supabase-kubernetes 0.8.0 (Postgres 17.6.1.136).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>