PostgreSQL refuses to run as root, but the setup wizard (and deploy.sh and
PM2) commonly run as root on a dedicated server. In that case Step 3 aborted
with "run this as the unprivileged user that will own the database, not root"
because postgres-local.sh inherited root and hit its own guard — and the same
failure would have recurred at deploy (ctl-start) and at PM2 start time.
- postgres-local.sh: when invoked as root, re-exec as the unprivileged owner of
.postgres/ (from $PG_RUN_USER for the first init, else the dir's owner) via
runuser instead of failing. Fixes init, ctl-start/ctl-stop and manual use.
- ecosystem.config.cjs: PM2 drops to the cluster owner's uid/gid for the
postgres process so it starts cleanly when PM2 runs as root.
- setup-wizard.sh: determine/create a non-root app user, chown .postgres/ to it,
and pass PG_RUN_USER so the very first init hands off correctly.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>