How to reach an app's database — wbsp-app 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-app 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.md; 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-app 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-app db reads for
you from the app you have access to.
Prerequisites
- The app must be deployed.
wbsp-app dbreads the connection from the running app's pod env, so deploy the app first (wbsp-app 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 — see Security). For AWS:aws eks update-kubeconfig --name wbsp-platform --region ap-southeast-1 - 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-app db run --config wbsp.yaml --destination prod -- npx prisma migrate deploy
# Seed script, or anything that reads DATABASE_URL / DATABASE_*
wbsp-app 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-app 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-app 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-app 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-app 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-app 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: provisioning the relay
The relay is part of platform provisioning, not something developers create.
# Created automatically when the platform is provisioned
wbsp-platform provision --provider aws
# → creates wbsp-db-proxy (Deployment + ClusterIP Service + NetworkPolicy)
# in the wbsp-system namespace
# Verify
kubectl -n wbsp-system get deploy,svc,netpol -l app=wbsp-db-proxyIf the relay is missing, wbsp-app db --destination prod (an aws destination) fails
with a clear message asking the operator to provision the platform.
Troubleshooting
| Symptom | Cause / fix |
|---|---|
deploy the app first | The app isn't running (no pod to read the connection from). wbsp-app 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 provision --provider aws. |
invalid sslmode value from a custom client | Use libpq's sslmode=require (what wbsp-app 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.md — the full command cheat-sheet by destination.