Skip to content

feat(tamanu): TAMANU_DATABASE_URL env override for DB connection#502

Open
passcod wants to merge 1 commit into
mainfrom
tamanu-database-url
Open

feat(tamanu): TAMANU_DATABASE_URL env override for DB connection#502
passcod wants to merge 1 commit into
mainfrom
tamanu-database-url

Conversation

@passcod

@passcod passcod commented Jun 18, 2026

Copy link
Copy Markdown
Member

🤖 Adds a TAMANU_DATABASE_URL environment variable that, when set, is used instead of the database section of the Tamanu config. Honoured by every bestool command that connects to or emits the Tamanu DB connection: alertd, tamanu doctor, tamanu logs, tamanu lifecycle (start/stop/status/restart), tamanu psql, tamanu db_url, tamanu backup, tamanu greenmask.

Behaviour

  • database_url() returns the override verbatim — preserving query params (sslmode) and Unix-socket forms. It flows straight into the connection stack (bestool_postgres::pooltokio_postgres::Config, which handles sockets and disables SSL for them; db_connect uses tokio_postgres::connect directly).
  • database() parses the override into host/user/password/name for the consumers that need fields rather than a URL (backup's pg_dump, greenmask, db_url/psql). Parsing goes through tokio-postgres's own connection-string parser, so any form the connection path accepts parses identically — including postgresql://tamanu_monitoring@/tamanu?host=/var/run/postgresql (Unix socket, peer auth).
  • db_url and psql no longer require a Tamanu install when the override is set. db_url echoes it verbatim (or re-points it at a -U role); psql passes it verbatim to the connection stack rather than through the url-crate path, which rejects the empty-host socket form.
  • alertd and tamanu doctor synthesise a sweep context from the override when there's no Tamanu install on the host, so DB and host checks run against it. This is what lets alertd monitor a database on a host with no Tamanu config.

Check levels

The doctor sweep now distinguishes two check levels, and an install/DB distinction that affects data, not gating:

  1. host — inspects the running host only. The caddy / kopia / HTTP-error-rate probes are reclassified here: they don't read config and already Skip gracefully when caddy/kopia is absent, so they run regardless of install.
  2. tamanu — needs a reachable Tamanu DB / deployment but not the install files. tamanu_http (local API), tamanu_service (service inventory), version_drift, and the DB checks live here, so they run in the DB-only case. Two refinements make this work:
    • tamanu_service's one config-derived expectation (the FHIR worker) degrades to Unknown without config rather than being guessed — services::expected now takes Option<&TamanuConfig>, mirroring the existing tri-state for the patient-portal signal.
    • version_drift needs a baseline version to compare running container tags against. That's the install's env-file version when present, otherwise the version Tamanu records in its own DB (local_system_facts.currentVersion) — the sweep populates the context version (and the wire tamanuVersion) from the DB for an install-less host. It self-skips only if neither source resolves a version.

Removed the tamanu_found check. It was never a healthcheck (it always passed; a "fail" had no meaning), it just reported the install's version/root/kind. Those move into the top-level status payload instead: tamanuVersion was already there, and tamanuRoot (when an install is on disk) and tamanuServerKind (central/facility) are now top-level ServerInfo fields. With it gone, no check is install-gated anymore — the install-vs-DB distinction only chooses the version source and whether tamanuRoot is reported.

Tidied other report-only checks. Same reasoning, for checks whose value is already a top-level status fact:

  • Removed the server_id check — metaServerId is already resolved at the top level (it's the /status/{id} POST target), and the check was pure reporting.
  • Made db_version and uptime off-wire (rendered in the CLI, omitted from the canopy health[] array) — pgVersion and uptimeSecs are already top-level facts, so they shouldn't alert. A new off-wire variant of the tamanu-level check arm carries db_version.

Notes

  • Normal usage works as expected: TAMANU_DATABASE_URL=… bestool alertd run reads the env var and monitors that database, install or not. The released binary builds with default features, which include tamanualertd-tamanu, so it always has this path. The only exception is a deliberately-minimal compile-time configuration built with --no-default-features --features alertd (i.e. without alertd-tamanu): that binary has no Tamanu code at all by construction and so doesn't read the env var. This is about that feature set, not about how the daemon is run.
  • backup and greenmask still require a local install for their non-DB needs (output dirs, pg_dump/psql discovery); the override only changes which database they target.

New tests: URL parsing (TCP, Unix socket, percent-encoded userinfo, scheme/dbname validation) in the tamanu crate; install-vs-DB check gating in the alertd doctor.

@passcod passcod force-pushed the tamanu-database-url branch 6 times, most recently from 0c1ba7d to d9633d0 Compare June 18, 2026 14:52
Every bestool command that connects to or emits the Tamanu database
connection now honours a TAMANU_DATABASE_URL environment variable,
using it instead of the database section of the Tamanu config.

- database_url() returns the override verbatim (preserving query params
  like sslmode and Unix-socket forms); database() parses it into fields
  via tokio-postgres's own connection-string parser for the consumers
  that need host/user/password/name (backup, greenmask, db_url, psql).
- db_url and psql no longer require a Tamanu install when the override
  is set; psql passes it verbatim to the connection stack rather than
  through the url-crate path that rejects the empty-host socket form.
- alertd and tamanu doctor synthesise a DB-only sweep context from the
  override when no Tamanu install is present: DB and host checks run,
  while install-dependent checks (install metadata, local HTTP, caddy,
  services, kopia) skip.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant