Connect to the database (SQL)¶
What this is: opening a direct SQL connection to the rack's PostgreSQL from your
laptop, using psql or a GUI client like DataGrip.
When you'd do it: inspecting or debugging live data — principals, chat history,
track hits — that the app doesn't surface in its UI.
How long it takes: a couple of minutes.
Who can do this: a developer or infra operator whose SSH public key is in
ssh_authorized_keyson the rack. This is not an operator task — it needs rack access, not a Directory login.
Postgres runs as a container on core-01 and is not published on any host port.
Its only clients are the Directory and Web containers on the same Docker network, which
reach it by the alias postgres. There is therefore no host:port to point a client at
from your laptop — every route in goes over SSH.
Which database¶
One Postgres instance on core-01, two databases, one role:
| Database | Used by | Role |
|---|---|---|
waypoint_directory |
Directory | waypoint |
waypoint |
Web | waypoint |
waypoint is the instance's superuser (it is POSTGRES_USER), so unlike a managed
service there is no separate app-user / superuser split and only one password.
The shape of it¶
flowchart LR
A["psql / DataGrip<br/>on your laptop"] -->|"SSH"| B["core-01"]
B -->|"docker network"| C["postgres<br/>container"]
Before you start¶
- Your SSH key is on the rack — run
bin/bootstrap-controller.shin theinfrastructurerepo, get the printed public key merged intossh_authorized_keys, and letfoundation.ymlconverge. - You can reach
core-01.bedrock.lanover the rack LAN or an explicitly provisioned management path that routes the rack address and resolves the internal name. The Cloudflare phone/device path does not expose.lanor SSH. - You know the sudo password for
ubuntu(it isansible_become_passwordin the rack vault) — needed only for the GUI path below.
Steps¶
The quick way — psql on the box¶
No password: connections over the container's local socket are trusted, which is the
same route roles/service/directory uses for its own migrations. Swap
-d waypoint_directory for -d waypoint to reach the web tier's database.
The GUI way — an SSH tunnel¶
The container publishes no port, so the tunnel has to target the container's address on the Docker network rather than the host:
PGIP=$(ssh ubuntu@core-01.bedrock.lan \
"docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' postgres")
ssh -N -L 5433:$PGIP:5432 ubuntu@core-01.bedrock.lan
Leave that running in its own terminal. Then fetch the password, which is generated on the first converge and stored root-only on the box:
Connect from DataGrip — new data source → PostgreSQL:
| Field | Value |
|---|---|
| Host | localhost |
| Port | 5433 |
| Database | waypoint_directory or waypoint |
| User | waypoint |
| Password | from postgres-secrets.env above |
| SSL | off — the SSH tunnel already encrypts |
The equivalent JDBC URL:
How to know it worked¶
psqlgives you a prompt, and\llists bothwaypointandwaypoint_directory.\dtinsidewaypoint_directorylists the Directory's tables.- DataGrip's Test Connection returns green and the schema tree populates.
If something goes wrong¶
Permission denied (publickey). Your key is not on the rack yet. It is live only once the PR adding it tossh_authorized_keysis merged andfoundation.ymlhas converged —authorized_keysis written to exactly that list.Error: No such container: postgres. Postgres is not running oncore-01. Check withdocker compose -f /etc/bedrock/compose/docker-compose.yml psand re-runplaybooks/core.yml.connection refusedonlocalhost:5433. The tunnel died, or the container was recreated and took a new address on the Docker network. Re-read$PGIPand restart the tunnel.password authentication failed. The database password is the one in/etc/bedrock/postgres-secrets.envon the box — not anything in the vault. The vault holds the sudo password, which is what gets you permission to read that file.sudoprompts and you don't have the password. It isansible_become_passwordin the rack vault:ansible-vault view inventories/rack/group_vars/all/vault.yml.- Client insists on SSL. Turn it off. The SSH tunnel already encrypts, and layering
TLS over
localhostbreaks the connection for no gain.
A note on the password¶
It is generated once, on the first converge, and written with force: false — so
re-running Ansible never changes it. Nothing else holds a copy, which means the file on
core-01 is the only record. Changing it is a deliberate act: rotate it in Postgres and
in that file together, then re-run playbooks/core.yml so the app containers pick the
new value up.
See also¶
- Stand up the Directory — the Directory and its database
- Stand up the web client — the web tier and its database
- Operator training index
Verified against infrastructure@5ac55aeb on 2026-09-02 — Postgres placement, credentials and unpublished port were checked against roles/platform/postgres/ and playbooks/core.yml; the SSH path was checked against inventory connection variables and the Cloudflare private routes/L4 policy, which expose the owned device-service ports but not SSH or internal .lan names.