Skip to content

feat(grafana): support managed PostgreSQL over TLS in the dashboard image - #9221

Open
DoDiODev wants to merge 1 commit into
apache:mainfrom
DoDiODev:pr/enterprise-grafana-pg-tls
Open

DoDiODev wants to merge 1 commit into
apache:mainfrom
DoDiODev:pr/enterprise-grafana-pg-tls

Conversation

@DoDiODev

Copy link
Copy Markdown
Contributor

Summary

Makes the dashboard image work with a managed PostgreSQL over TLS and fixes
some problems in its datasource provisioning that showed up while testing
this. Part of #9219 (section A). Defaults are unchanged.

TLS

  • docker-compose-dev-postgresql.yml passes GRAFANA_DATABASE_SSL_MODE
    (default disable) to the existing DATABASE_SSL_MODE; documented in
    env.example (follow-up to build(compose): make grafana port, root URL and datasource configurable #9207).
  • New optional DATABASE_SSL_ROOT_CERT, DATABASE_SSL_CERT and
    DATABASE_SSL_KEY (file paths inside the container, e.g. a mounted
    secret). They are written to the datasource as sslRootCertFile /
    sslCertFile / sslKeyFile with tlsConfigurationMethod: file-path.
    Without them, verify-ca / verify-full against a private CA cannot work.
    An unreadable path logs a warning.

Datasource provisioning

  • The API calls use GF_SECURITY_ADMIN_USER (default admin) instead of a
    hard-coded admin, and pass the credentials with --user instead of
    inside the URL.
    Before, a renamed admin got 401 ten times and no datasource was created.
    A password containing @, / or # made curl fail, and set -e then
    ended the entrypoint and with it the container (exit 6).
  • A failing curl no longer ends the entrypoint. 401/403 stop the retry
    loop with a hint, and an ERROR line is logged if the datasource could
    not be created. Grafana keeps running in both cases.
  • Clean slate deletes by UID. Grafana 13 answers {"message":"Not found"}
    for DELETE /api/datasources/<id>, so on every restart nothing was
    deleted, the POST hit "already exists", and the old datasource was kept
    with its old settings. A changed sslmode or database password never
    took effect after the first start. Deletion by ID is kept as a fallback
    for older Grafana versions.
  • New DATASOURCE_CLEAN_SLATE (default true = current behaviour).
    false replaces only the DevLake datasource (by UID) and keeps all other
    datasources, for a Grafana state that is shared with other teams or
    replicas. Changing the default is left to the discussion in [Feature][Grafana][config-ui] Gaps when running DevLake with a managed PostgreSQL and an external Grafana #9219.

Does this close any open issues?

Part of #9219 (section A).

Screenshots

N/A

Other Information

Tested locally with the image built from this branch and from main
(4ad2f66df), against postgres:18.6 with ssl=on and a test CA, and
mysql:8.4.11:

Scenario main this PR
Defaults, no new variables — ✅ unchanged (sslmode=disable)
verify-full + DATABASE_SSL_ROOT_CERT not possible ✅ datasource health OK
verify-full without root cert (negative test) — fails TLS verification, as expected
Existing volume, restart with DATABASE_SSL_MODE=require ❌ stays disable ✅ require
GF_SECURITY_ADMIN_USER=lakeadmin, password p@ss/w#rd ❌ container exits (6) ✅ datasource created, health OK
Admin password does not match the Grafana state 10 × "API error" one HTTP 401 with a hint, ERROR line, Grafana keeps running
Extra datasource + restart (default) ❌ nothing deleted ✅ only the DevLake datasource remains
DATASOURCE_CLEAN_SLATE=false + extra datasource — ✅ extra datasource kept, DevLake datasource replaced
MySQL mode, first start and restart — ✅ health OK

bash -n and shellcheck -S warning are clean. Full CI mirror on my fork:
run

…mage

The dashboard image could only talk to PostgreSQL with sslmode=disable
in the compose setup, and verify-ca/verify-full failed against a private
CA because the datasource never got a root certificate. While testing
this, a few related problems in the datasource provisioning showed up.

TLS:
- docker-compose-dev-postgresql.yml passes GRAFANA_DATABASE_SSL_MODE
  (default disable) as DATABASE_SSL_MODE, documented in env.example
- new optional DATABASE_SSL_ROOT_CERT, DATABASE_SSL_CERT and
  DATABASE_SSL_KEY (file paths in the container) are written to the
  datasource as sslRootCertFile/sslCertFile/sslKeyFile with
  tlsConfigurationMethod=file-path; unreadable paths log a warning

Provisioning:
- the API calls use GF_SECURITY_ADMIN_USER instead of a hard-coded
  "admin" and pass the credentials via --user, so a renamed admin or a
  password containing characters such as @ / # no longer breaks them
- a failing curl no longer ends the entrypoint (set -e) and with it the
  container; 401/403 stop the retry loop with a hint, and a final error
  is logged if the datasource could not be created
- the clean slate deletes datasources by UID: Grafana 13 answers
  "Not found" for deletion by numeric ID, so on every restart the old
  datasource was kept ("already exists") together with its old settings
  (e.g. a changed sslmode or password never took effect). Deletion by ID
  is kept as a fallback for older Grafana versions
- DATASOURCE_CLEAN_SLATE=false (default true) replaces only the DevLake
  datasource and keeps all other datasources, for a Grafana state that is
  shared with other teams or replicas

Defaults are unchanged.

Signed-off-by: DoDiODev <DoDiDev@proton.me>
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