Skip to content

feat(supabase): PG15->17 in-place migration tooling + runbook#81

Open
Carlos-Vera wants to merge 1 commit into
easypanel-io:18-05-2026from
Carlos-Vera:feat/pg17-migration-tooling
Open

feat(supabase): PG15->17 in-place migration tooling + runbook#81
Carlos-Vera wants to merge 1 commit into
easypanel-io:18-05-2026from
Carlos-Vera:feat/pg17-migration-tooling

Conversation

@Carlos-Vera

Copy link
Copy Markdown

What this PR does

Adds the tooling to migrate an existing EasyPanel-hosted Supabase stack from Postgres 15 to 17 in place, keeping the data — three scripts + a step-by-step runbook under supabase/code/. No image or service versions change here; this is the migration counterpart to the bump in #80.

Why it's separate from #80

#80 is one line (the image bump) and can be judged on its own. This is the part that answers "ok, but how does someone with a running 15 stack actually move?" — kept apart so you can take one without the other.

What's in it

  • utils/upgrade-pg17.easypanel.sh — the conversion. Autodetects the db container / data dir / db-config by compose project label (EasyPanel doesn't set container_name, so nothing is hardcoded), runs Supabase's own initiate.sh/complete.sh from a one-off container, --conversion-only so EasyPanel keeps owning start/stop, keeps data.bak.pg15 for rollback.
  • utils/regen-db-config.sh — regenerates the db-config volume from the 17 image while preserving pgsodium_root.key (see Gotcha A below).
  • utils/post-upgrade-pg17-roles.sh — the role/collation migrations pg_upgrade doesn't carry over.
  • docs/RUNBOOK-easypanel-pg15-to-17.md — the whole thing, step by step, with backup and rollback.

Tested

Ran it on a real EasyPanel deployment (15.8.1.08517.6.1.150): 17.6 healthy, all containers up, infra preserved. Also locally against a stack replicating the EasyPanel layout with an app schema + RLS + seeded rows — every table's md5 byte-identical before/after, vault still decrypting. pg_upgrade itself is seconds; wall-clock is image pulls.

Gotcha A: the db-config volume

The db-config volume (mounted at /etc/postgresql-custom) survives the upgrade and can carry a PG15 setting that 17 rejects — the db then loops on configuration file ".../supautils.conf" contains errors. It didn't trigger on 15.8.1.085 → 17.6.1.150 (17 tolerates the one real drift, a renamed supautils.* GUC), but I reproduced it by injecting a parameter removed after 15. The fix regenerates db-config from the 17 image while preserving pgsodium_root.key — drop that key and vault comes back with invalid secret key. Handled behind a flag, with a standalone contingency script.

The honest part: is this the right tool for the EasyPanel user?

A gut check, because here it matters more than the code. Someone running Supabase through EasyPanel mostly chose it to not touch a terminal. This path still needs SSH (or the service web console) + running a script. It works, but it's not "click a button".

A few open questions I don't think should be waved away:

  • Blast radius for a non-technical user: if 17 lands on a branch their running stack pulls, and they redeploy with data but haven't migrated, the db won't start and they won't know why. That alone argues for shipping 17 on a new dated branch only (option 1 in chore(supabase): bump postgres to 17.6.1.150 #80), and treating this tooling as the escape hatch for whoever does need to move.
  • How many actually need it? New deployments are fine on 17 with zero effort. The only people this is for are existing stacks with data — probably a minority, and for a small DB a plain pg_dumpall + restore may feel less scary than a pg_upgrade script they can't read.
  • Where it could get simpler: the script can already be launched from the service's web console in EasyPanel (the terminal icon), so SSH isn't strictly required — worth documenting that path for non-CLI users. The real simplification would be EasyPanel driving this as a panel action, but that's the panel's call, not the template's.

Not trying to solve that here — just flagging it so the call on #80 is made with the non-technical user in mind, not only the mechanics.

Adds tooling to migrate an existing EasyPanel-hosted Supabase stack from
Postgres 15 to 17 in place, preserving data -- the counterpart to the image
bump in easypanel-io#80.

- utils/upgrade-pg17.easypanel.sh: autodetects db container / data dir /
  db-config by compose project label (no container_name assumption),
  --conversion-only mode so EasyPanel keeps owning start/stop, and
  REGEN_DB_CONFIG to regenerate db-config from the PG17 image while preserving
  pgsodium_root.key (Gotcha A).
- utils/post-upgrade-pg17-roles.sh: post-start role/collation migrations that
  pg_upgrade does not carry over.
- utils/regen-db-config.sh: standalone db-config regeneration (Gotcha A
  contingency), preserving the pgsodium key.
- docs/RUNBOOK-easypanel-pg15-to-17.md: step-by-step runbook.

The PG17 image bump (easypanel-io#80) and the rest/functions healthchecks (easypanel-io#79) are
proposed separately; this branch adds only the migration tooling and docs.

Autor: Carlos Vera <carlos@braveslab.com>
---
De un venezolano para el mundo con el favor de nuestro Señor JesusCristo.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant