Files
mrcharles 3d38c507e8 feat: add Database-Gateway Cloudron package (Infrastructure) [#639]
Database Gateway 0.24.0 as the 12th package: multi-stage Go build
(CGO required by the libpg_query parser, hence an alpine:3.23 runtime
matching upstream), native OIDC wired to the Cloudron platform identity
provider, postgresql addon storage with goose migrations applied at
start, jq-generated config + OPA policy seeded to /app/data. Verified
end-to-end against a throwaway postgres (migrations, policy compile,
startup to the OIDC handoff). Docs gardened to 12 packages.

Ticket: https://projects.knownelement.com/issues/639
2026-09-01 19:28:06 -05:00
..

Database Gateway — Cloudron Package

Database Gateway (dbgw) is a web gateway for secure, controlled access to PostgreSQL databases: users log in via OIDC and run SQL through a unified web UI, with every query parsed and authorized by embedded OPA policies (per user, target, operation and table). Results are stored in a local PostgreSQL with shareable links for debugging and auditing.

Packaging overview

Aspect Choice
Pattern Multi-stage Go build (JOURNAL pattern #2)
Builder golang:1.26-alpine (upstream's own build recipe, CGO on)
Base image alpine:3.23 (musl runtime required — see below)
Upstream v0.24.0 (Go 1.26.1, Echo; frontend pre-built and embedded via go:embed)
Addons localstorage + postgresql (16) — storage for profiles, bookmarks, query results
Auth Native OIDC (preferred) wired to the Cloudron platform identity provider
Runtime start.sh waits for Postgres, seeds config + OPA policy, migrate-up, execs run

Why alpine instead of cloudron/base: the SQL parser is a cgo binding (libpg_query) — the binary must be built with CGO_ENABLED=1 (a static build fails with undefined: pg.Parse) and therefore links musl, which does not exec on Ubuntu/glibc bases. Alpine runtime matches upstream's own image; bash/psql/jq/openssl are apk-installed for start.sh.

Why not the official image: upstream publishes ghcr.io/kazhuravlev/ database-gateway:latest but tagging is :latest-only; building v0.24.0 from the cloned source pins the version and lets the ldflags carry the release tag into /healthcheck-style version output.

Authentication (auth gate verdict: OIDC, preferred)

Database Gateway authenticates only via OIDC — no local user database, no LDAP. This is the preferred row of the auth matrix:

  • CLOUDRON_OIDC_ISSUER, CLOUDRON_OIDC_CLIENT_ID, CLOUDRON_OIDC_CLIENT_SECRET (injected by Cloudron's platform OIDC provider, manifestVersion 2) are written into /app/data/config.json on first start.
  • Redirect URL: ${CLOUDRON_APP_ORIGIN}/auth/callback.
  • Scopes: openid profile email groups; role_claim is groups, mapped adminsadmin, usersuser (Cloudron's built-in groups).
  • Access policy is then enforced per query by OPA (see below), not just at login.

Ports

Port Type Purpose
8080 httpPort Web UI + LRPC API (only listener)

Configuration (persistent, in /app/data)

  • config.json — seeded once on first start (OIDC + storage from Cloudron env). Add your database targets here with the Cloudron file manager; restart the app after editing. See upstream example for the full target format (connection, default_schema, tables[].table must be schema-qualified, fields allowlist).
  • opa/simple.rego — seeded default: Cloudron admins see all targets and may run any op; everyone else denied until an operator extends the policy (input subjects contain user:<email> and role:<role>).
  • .cookie_secret — random 32-byte hex, generated once; rotating it invalidates sessions.

The postgresql addon database is the gateway's own storage (users, bookmarks, cached results) — not a query target. Targets point at the other PostgreSQL instances you want to reach.

Build & test

docker build --cgroup-parent ukrrs-batch.slice -t database-gateway-cloudron:test Package-Workspace/Infrastructure/database-gateway/
docker run --rm --entrypoint /usr/local/bin/database-gateway database-gateway-cloudron:test --version

Files

  • Dockerfile — multi-stage Go build (golang:1.26-alpine → alpine:3.23, musl)
  • CloudronManifest.json — manifestVersion 2, httpPort 8080, localstorage + postgresql addons
  • start.sh — DB wait, config/policy seeding, migrations, exec gateway
  • .env.example — environment knobs consumed at seed time
  • logo.png — from upstream frontend/src/favicon-96x96.png