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-proxy in the wbsp-system namespace) 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 db opens a kubectl port-forward to 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 at localhost.
  • 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 db reads 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 kubectl must 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 connect only: a local psql. On macOS, brew install libpq installs it, but libpq is keg-only, so add it to your PATH:
    echo 'export PATH="$(brew --prefix libpq)/bin:$PATH"' >> ~/.zshrc && source ~/.zshrc
    On Debian/Ubuntu: apt-get install postgresql-client. The other verbs (run, proxy, url) don't need psql.

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.js

Everything 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 prod

The 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 6543

db 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 prod

For 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 typeWhat wbsp-app db does
compose / dev / standaloneConnects 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 psql via environment only — never as a CLI flag, never logged, never written to disk. Only db proxy prints 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-proxy

If 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

SymptomCause / fix
deploy the app firstThe app isn't running (no pod to read the connection from). wbsp-app deploy it, then retry.
psql not found on PATHInstall the client; on macOS add keg-only libpq to PATH (see Prerequisites).
relay-missing / "provision the platform" errorThe wbsp-db-proxy relay isn't deployed — an operator runs wbsp-platform provision --provider aws.
invalid sslmode value from a custom clientUse 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 proxyThe tunnel closed (you pressed Ctrl-C or it errored). Re-run db proxy; check kubectl still has cluster access.

See also