Skip to content

BE-M0-11 · The signing key, a restart and the checks

ID BE-M0-11 · Level L0 · Pack Pack A · Local stack settings · Run order row 18

The local stack signs tokens with this Mac's ES256 key, refuses self sign-up and runs without the switched-off services; pack A is merged into main.

  • BE-M0-10 is Done. You are on the branch supabase/local-settings in ~/opleet-v2/opleet. Docker Desktop is running.

1 · The script that makes the key once per machine, and the root script that runs it

Section titled “1 · The script that makes the key once per machine, and the root script that runs it”
Terminal window
mkdir -p tools/db
cat > tools/db/signing-key.sh <<'EOF'
# Makes the local Supabase stack's ES256 signing key, once per machine (D13, FE-R4).
# The key signs tokens for the local stack only. It is git-ignored and never leaves this machine.
# Run it with: pnpm db:signing-key
set -euo pipefail
cd "$(dirname "$0")/../.."
key=supabase/signing_keys.json
if [ -s "$key" ] && grep -q '"kty"' "$key"; then
echo "$key already holds a signing key; nothing to do."
exit 0
fi
echo '[]' > "$key"
pnpm exec supabase gen signing-key --algorithm ES256 --yes
chmod 600 "$key"
EOF
pnpm pkg set 'scripts["db:signing-key"]=bash tools/db/signing-key.sh'

2 · Make the key, and confirm git ignores it

Section titled “2 · Make the key, and confirm git ignores it”
Terminal window
pnpm db:signing-key
git check-ignore -v supabase/signing_keys.json
ls -l supabase/signing_keys.json

3 · Start the stack with the new settings

Section titled “3 · Start the stack with the new settings”
Terminal window
pnpm supabase start

4 · Read the key the stack publishes, try a self sign-up, and list the running services. The local keys this reads are the same on every machine and aren't secrets.

Section titled “4 · Read the key the stack publishes, try a self sign-up, and list the running services. The local keys this reads are the same on every machine and aren't secrets.”
Terminal window
eval "$(pnpm supabase status -o env)"
curl -s "$API_URL/auth/v1/.well-known/jwks.json" -H "apikey: $PUBLISHABLE_KEY"; echo
curl -s -X POST "$API_URL/auth/v1/signup" -H "apikey: $PUBLISHABLE_KEY" -H "Content-Type: application/json" -d '{"email":"signup-check@example.test","password":"signup-check-1234"}'; echo
docker ps --format '{{.Names}}' | sort

5 · Commit, then open and merge the pull request for pack A

Section titled “5 · Commit, then open and merge the pull request for pack A”
Terminal window
git add tools/db/signing-key.sh package.json
git commit -m "build(tools): make the local signing key once per machine"
git push -u origin supabase/local-settings
gh pr create --title "build(supabase): local stack settings and signing key" --body "BE pack A (BE-M0-10, BE-M0-11), timeline row 18."
gh pr checks --watch
gh pr merge --squash --delete-branch
git pull
  • Block 1 prints nothing.
  • Block 2: $ bash tools/db/signing-key.sh, then JWT signing key appended to: supabase/signing_keys.json (now contains 1 keys); the CLI may print its overwrite question first, answered by --yes. check-ignore prints supabase/.gitignore:11:signing_keys.json, and ls shows -rw-------: only you can read the key.
  • Block 3: “Started supabase local development setup.” with the local URLs. It is quicker than TL-M0-16 because the images are already downloaded. It may list the switched-off services as stopped.
  • Block 4: the first curl prints a keys list holding one key with "kty":"EC" and "alg":"ES256", and no "d" field. The second prints {"code":422,"error_code":"signup_disabled","msg":"Signups not allowed for this instance"}. docker ps lists names ending in _opleet: the database, auth, rest, kong, storage, pg_meta, studio and the mail tester; none of them contains analytics, vector, edge_runtime, realtime or imgproxy.
  • Block 5: ✔️ biome and ✔️ commitlint, then the commit line; checks and pr-title pass; ✓ Squashed and merged pull request #….
Terminal window
git log --oneline -1
docker ps --format '{{.Names}}' | grep -E 'analytics|vector|edge_runtime|realtime|imgproxy' || echo "none of the switched-off services is running"
git status --short

Expect the squash commit “build(supabase): local stack settings and signing key (#…)” on main, then “none of the switched-off services is running”, then nothing from git status: the key file stays ignored.

  • Block 2 stops with GenSigningKeyReadError: you aren't at the repository root. Run cd ~/opleet-v2/opleet and block 2 again. Anything else: paste it.
  • Block 3 says it failed to read the signing keys: run block 2 first. A port is in use: run pnpm supabase stop --all, then block 3 again.
  • eval prints “command not found”: paste the output of pnpm supabase status -o env | cut -d= -f1, which shows only the variable names.
  • The first curl shows "alg":"HS256", an empty keys list or a "d" field: stop and paste it.
  • The sign-up returns a user or an access_token: stop. Sign-up is still on; paste the output of grep -n enable_signup supabase/config.toml.
  • A switched-off service is running: paste the output of docker ps and pnpm supabase status.
  • pr-title fails: run gh pr edit --title "build(supabase): local stack settings and signing key", then gh pr checks --watch again.

Before merging:

Terminal window
gh pr close --delete-branch
git switch main
git branch -D supabase/local-settings
pnpm supabase stop
rm supabase/signing_keys.json

After merging: revert it with a new pull request.

Done 2026-10-06 (zuki)