How to reach an app's database — wbsp db
The platform's database (AWS RDS) lives inside the VPC with no public endpoint —
that's correct for security, but it means your laptop can't connect to it directly,
and kubectl port-forward only forwards to Pods (RDS isn't a Pod).
wbsp db solves this with one command. It tunnels to the database through a
small, internal-only relay that the platform runs in the cluster, and it figures out
the connection details for you — so you can run migrations, open psql, or point a
GUI client at the database without any manual setup.
Quick reference lives in Useful commands; this page is the full how-to. (A manual fallback using the admin user and a throwaway in-cluster pod exists for operators, but needs direct cluster access.)
How it works
your laptop ──kubectl port-forward──▶ wbsp-db-proxy relay ──▶ private RDS
(over the Kubernetes API) (in the cluster) (in the VPC)- The relay (
wbsp-db-proxyin thewbsp-systemnamespace) is a tiny TCP forwarder. It's provisioned with the platform, not per app, and one relay serves every app's database — the database is chosen by your connection, not by the relay. wbsp dbopens akubectl port-forwardto that relay on a free local port, reads the app's database connection (host/port/name/user/password) from the deployed app's pod, and points your command/psql/GUI atlocalhost.- PostgreSQL TLS is negotiated end to end (your client ↔ RDS). The relay only
forwards bytes, so encryption works through it. The connection uses
sslmode=require(encrypt without verifying the CA — the RDS CA isn't in your local trust store and the traffic is inside the VPC).
The relay is transport only: it does not bypass database authentication. You
still need the app's database credentials to connect — which wbsp db reads for
you from the app you have access to.
Prerequisites
- The app must be deployed.
wbsp dbreads the connection from the running app's pod env, so deploy the app first (wbsp deploy --config wbsp.yaml --destination prod). If it isn't deployed, the command tells you so. - Your
kubectlmust point at the cluster (the tunnel rides the Kubernetes API, so this also enforces access control). Your platform operator gives you the cluster name and region, and an access entry for the cluster. Then:aws eks update-kubeconfig --name <cluster> --region <region> - For
db connectonly: a localpsql. On macOS,brew install libpqinstalls it, but libpq is keg-only, so add it to yourPATH:On Debian/Ubuntu:echo 'export PATH="$(brew --prefix libpq)/bin:$PATH"' >> ~/.zshrc && source ~/.zshrcapt-get install postgresql-client. The other verbs (run,proxy,url) don't needpsql.
The commands
Run these from the app's directory (where its wbsp.yaml is). An aws destination
is the remote database; a local-machine destination (compose/dev/standalone)
talks to the docker-compose database directly with no relay. Below, prod names an
aws destination and compose names a local-machine one.
db run — run a command with the database in its env (migrations)
The headline use case. Opens a tunnel, sets the standard DATABASE_* /
DATABASE_URL environment to point at localhost, runs your command, then tears the
tunnel down — and propagates the command's exit code.
# Apply Prisma migrations against the app's real database
wbsp db run --config wbsp.yaml --destination prod -- npx prisma migrate deploy
# Seed script, or anything that reads DATABASE_URL / DATABASE_*
wbsp db run --config wbsp.yaml --destination prod -- node scripts/seed.jsEverything after -- is your command, run verbatim.
db connect — interactive psql
Opens a tunnel and drops you into a psql session against the app's database.
wbsp db connect --config wbsp.yaml --destination prodThe connection is supplied to psql via libpq PG* environment variables, so no
flags are needed. Exit psql (\q) and the tunnel closes automatically.
db proxy — hold a tunnel open for a GUI client
Opens a tunnel on a local port, prints the connection details (including the
password, so you can paste them into TablePlus / DBeaver / pgAdmin), and holds open
until you press Ctrl-C.
wbsp db proxy --config wbsp.yaml --destination prod
# Database tunnel open. Connect with:
# host=localhost
# port=54981
# dbname=test_wbsp_website
# user=test_wbsp_website_user
# password=••••••••
# url=postgresql://...@localhost:54981/test_wbsp_website?sslmode=require
# Holding open — press Ctrl-C to close.
# Pin a specific local port instead of auto-picking a free one:
wbsp db proxy --config wbsp.yaml --destination prod --port 6543db proxy is the only command that prints the password — by design, so you can
configure a GUI. The others never print it.
db url — print the connection string
wbsp db url --config wbsp.yaml --destination prodFor a local-machine destination this string is directly usable; for an aws
destination it's relative to an open tunnel (use db proxy to get the live
localhost:PORT form).
Local vs AWS
destination type | What wbsp db does |
|---|---|
compose / dev / standalone | Connects directly to the docker-compose Postgres — no relay. |
aws (incl. mode: demo) | Tunnels through the wbsp-db-proxy relay to private RDS. |
If your wbsp.yaml defines only one destination, you can omit --destination; with
more than one, pass it explicitly.
Security & access
- The relay is internal-only (a ClusterIP Service — never a LoadBalancer or
NodePort) and locked down by a NetworkPolicy: it may egress only to the database,
and it accepts no in-cluster traffic. The only way to reach it is
kubectl port-forward, which goes through the Kubernetes API server — so reaching the database requires valid cluster credentials + RBAC. - The relay does not bypass database authentication. You connect with the app's own database user; the relay just moves bytes.
- The password is passed to wrapped tools and
psqlvia environment only — never as a CLI flag, never logged, never written to disk. Onlydb proxyprints it, and only because you asked it to.
Operator: the relay
The relay is part of the platform, not something developers create.
wbsp-platform up builds it (a Deployment, a ClusterIP Service and a
NetworkPolicy named wbsp-db-proxy, in the wbsp-system namespace). To check
it is there:
kubectl -n wbsp-system get deploy,svc,netpol -l app=wbsp-db-proxyIf the relay is missing, wbsp db --destination prod (an aws destination) fails
with a clear message asking the operator to rebuild the platform.
Troubleshooting
| Symptom | Cause / fix |
|---|---|
deploy the app first | The app isn't running (no pod to read the connection from). wbsp deploy it, then retry. |
psql not found on PATH | Install the client; on macOS add keg-only libpq to PATH (see Prerequisites). |
| relay-missing / "provision the platform" error | The wbsp-db-proxy relay isn't deployed — an operator runs wbsp-platform up for the platform. |
invalid sslmode value from a custom client | Use libpq's sslmode=require (what wbsp db emits). no-verify is a node-postgres-only value; node apps build their URL from the DATABASE_* parts instead. |
Connection refused on localhost:PORT after db proxy | The tunnel closed (you pressed Ctrl-C or it errored). Re-run db proxy; check kubectl still has cluster access. |
See also
- Useful commands — the full command cheat-sheet by destination.