Skip to content

Analyze the database directly

The hub's data is yours — connecting pgAdmin, IntelliJ or plain psql to the self-host PostgreSQL is a supported gesture, not a workaround. This page gives you the door, the credentials, and the one habit that makes what you see match what the product sees.

Three roles, three postures

The install creates three database roles. Pick by what you want your session to be able to do:

Role Sees Can write Use it for
lumnik_readonly one tenant at a time (RLS applies) no — refused by PostgreSQL itself day-to-day analysis: you see exactly what the product's chat sees, and cannot break anything
lumnik_app one tenant at a time (RLS applies) yes reproducing the application's own posture
lumnik_admin every tenant (bypasses RLS) yes, including DDL cross-tenant checks, schema exploration — handle in read-mostly discipline

Passwords live in your .env (LUMNIK_READONLY_DB_PASSWORD, LUMNIK_APP_DB_PASSWORD, LUMNIK_ADMIN_DB_PASSWORD) — generated per install, never shipped.

Quick look, no tooling

The database publishes no port to your machine by default. From inside the container, psql connects without a password:

CID=$(docker compose -f docker-compose.selfhost.yml ps -q postgres)
docker exec -it $CID psql -U lumnik_readonly -d lumnik

Connect a GUI (pgAdmin, IntelliJ, DBeaver…)

Give the database a TCP door on your machine only, via a compose override — the shipped file stays untouched:

# analyse-ports.yml (next to docker-compose.selfhost.yml)
services:
  postgres:
    ports: ["127.0.0.1:5433:5432"]
docker compose -f docker-compose.selfhost.yml -f analyse-ports.yml up -d postgres

Then in your tool: host localhost, port 5433, database lumnik, one of the three roles above with its .env password. The 127.0.0.1: prefix matters — the database listens to your machine, not your network. To close the door, re-run up.sh (or the same command without the override file).

The one habit: name your tenant

Under lumnik_readonly or lumnik_app, row-level security filters every table by the current tenant — and until you name one, you see no rows at all (deliberate: fail-closed). Start each session with:

SET app.current_tenant = '1';   -- your tenant id; a fresh install seeds tenant 1

In IntelliJ, put that line in the data source's startup script so every connection carries it. In pgAdmin, run it at the top of each Query Tool session.

Where to look first: \dn lists the schemas (core, connector, identity); ingested data lands in connector as t_-prefixed tables, one per endpoint, each carrying the tenant_id column the isolation keys on. The same query run without the SET, then as lumnik_admin, is the fastest way to see the tenant isolation work.