psql variables (:'gt_pass') are substituted client-side in the psql stream
but NOT inside dollar-quoted DO $$..$$ bodies — those are sent to the server
as literal text, causing syntax error. Replace DO block with \gexec pattern:
quote_literal(:'gt_pass') builds the CREATE ROLE statement client-side, then
\gexec executes it. WHERE NOT EXISTS makes both role and DB steps idempotent.
Also connect to 'postgres' db (not app db) for CREATE DATABASE to work.