CREATEROLE user such as the RDS master) stays with the person who manages the database.
Setting up roles is provisioning: you run it as the admin, once per install and again before a release that changes roles. Migrations then run as
migrator and never need the admin: once the roles are set up, the migrations container refuses any other login.
Set up roles
Runtracecat db roles upgrade as the admin, from the Tracecat image of the release you are about to deploy. It creates the roles, grants their access, and moves an existing install’s objects to tracecat_owner and app_owner. It is safe to rerun.
TRACECAT__DB_ADMIN_URI: the admin’s connection URI for the Tracecat database, for examplepostgresql://postgres:<password>@db.example.com:5432/tracecat.ca.pem: the CA bundle that signed the database’s certificate, soverify-fullcan check it (for RDS, the global bundle).--login: howapp,migratorandagent_runtimelog in.passwordsets the passwords fromTRACECAT__DB_MIGRATOR_PASSWORDandTRACECAT__DB_APP_PASSWORD(andTRACECAT__DB_AGENT_RUNTIME_PASSWORDif set).aws_iamgrantsrds_iaminstead, so the roles log in with IAM tokens; leave the password variables unset.azure_entraexpects you to createmigrator,appandagent_runtimefirst, each mapped to the identity that logs in as it withpgaadauth_create_principal_with_oid(see Database IAM login); leave the password variables unset.
- Point the migrations at
migrator:TRACECAT__DB_USER=migratorandTRACECAT__DB_PASS, orTRACECAT__DB_URI. - Point every other service at
app. - Deploy.
tracecat db roles upgrade once more after the first deploy. It installs the guard that keeps row-level security on workspace tables, which needs the migrated schema and a superuser (rds_superuser on RDS). Until then, each migration run logs the dynamic-table RLS guard isn't installed.
If the admin can’t run commands against the database (no CREATEROLE, or a locked-down managed service), print the SQL and run it yourself:
Before each release
Release notes say when a release changes database roles. Check before you deploy:status exits with 1 when the database is behind. Run tracecat db roles upgrade from the new release’s image, then deploy. If you deploy first, migrations stop before changing anything:
app and tracecat_readonly access to new tables themselves.
By deployment type
Docker Compose
Compose sets up roles for you, because thepostgres superuser’s password is already in .env. Set these in .env, then restart:
migrations container runs tracecat db roles upgrade as the admin, the migrations as migrator, then upgrade again (it installs the RLS guard once the schema exists). Until you change TRACECAT__DB_URI, the services keep logging in as the admin. Once the roles exist, move them to app with TRACECAT__DB_URI=postgresql+psycopg://app:${TRACECAT__DB_APP_PASSWORD}@postgres_db:5432/postgres, and keep the variables above set: the next start needs them for role setup.
Kubernetes
Runtracecat db roles upgrade yourself, from a machine or a one-off pod that can reach the database, with the admin’s credentials. Don’t store the admin’s credentials in the cluster. Then give the chart’s migrations Job the migrator login (migrations.migrator in the chart’s values, with a password Secret or aws_iam) and the services the app login (externalPostgres.auth.appSecret).
AWS Fargate
The Fargate stack runs Tracecat as one database user. Database roles aren’t available there yet.Personal read-only access
Give people their own login and thetracecat_readonly role. As the admin:
On RDS, with IAM login:
\password alice, which hashes it on the client so the plaintext never reaches the server.
tracecat_readonly can read every workspace’s data in public except credential columns such as tokens and password hashes. Row-level security still applies to it on workspace-scoped tables, so a session sees their rows only after it opts in: run SET app.rls_bypass = 'on'; first (or SET app.current_workspace_id = '<workspace-id>'; for one workspace). Tables without a policy, such as organization-wide ones like user, are readable without it. The role stays read-only either way.
Break-glass access
The admin login keeps full access: it is a member oftracecat_owner (or a superuser). Use it only for repairs, then rotate its password. Don’t hand it to a Tracecat service or the migrations.
Roll back
To return to a single database user, point every service and the migrations back at the admin login, then run this as the admin in the Tracecat database (replace<admin> with its name):
REASSIGN OWNED gives the tables back to the admin. Each DROP OWNED then only removes that role’s grants and default privileges; run them one role at a time, since one statement for several roles fails on their shared default privileges. DROP ROLE removes the roles, including people’s tracecat_readonly membership.