From d706d17cc8eb5b1a767e78f0fc2d0e5aeb36e3f0 Mon Sep 17 00:00:00 2001 From: David Kiania Date: Sat, 11 Apr 2026 19:22:30 +0300 Subject: [PATCH] Fix Grafana datasource: add GRAFANA_DB_RO_PASSWORD and sync grafana_ro on startup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit grafana_ro DB role was created with placeholder password 'SET_PASSWORD_IN_ENV' and GRAFANA_DB_RO_PASSWORD was never set in .env, so Grafana's TracksolidDB datasource could not authenticate — causing 'Failed to load home dashboard'. Fix: - Add GRAFANA_DB_RO_PASSWORD to .env with a secure generated password - Add sync_role_passwords() to run_migrations.py — runs ALTER ROLE on every startup so DB password stays in sync with the env var (idempotent) Co-Authored-By: Claude Sonnet 4.6 --- .env | 1 + run_migrations.py | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/.env b/.env index be60d53..d218223 100644 --- a/.env +++ b/.env @@ -12,5 +12,6 @@ DATABASE_URL= "postgres://postgres:U1pm3f5SX34DXkHoW6aKFsBHOlMA9binDPNG4aT0FAcg7 # Grafana GRAFANA_ADMIN_PASSWORD=ed3aaf20707fb5af9185708ec27f5211f71b35067277993eab624abce1 +GRAFANA_DB_RO_PASSWORD=7942a1DeLgyuiCzh8XFH21sPVJqRJo737qDW1PNDEtM API_BASE_URL = "https://eu-open.tracksolidpro.com/route/rest" diff --git a/run_migrations.py b/run_migrations.py index d5f3e84..8b148e9 100644 --- a/run_migrations.py +++ b/run_migrations.py @@ -158,6 +158,23 @@ def run_file(path, filename): return True +def sync_role_passwords(conn): + """ + Keep DB role passwords in sync with env vars on every startup. + Safe to run repeatedly — ALTER ROLE is idempotent. + This fixes roles created with the placeholder 'SET_PASSWORD_IN_ENV'. + """ + roles = { + "grafana_ro": os.getenv("GRAFANA_DB_RO_PASSWORD"), + } + with conn.cursor() as cur: + for role, password in roles.items(): + if password: + cur.execute(f"ALTER ROLE {role} WITH PASSWORD %s", (password,)) + print(f" Password synced for role: {role}") + conn.commit() + + def verify_schema(conn): """Verify critical tables exist. Exit 1 if missing — blocks service start.""" print("Verifying schema...") @@ -210,6 +227,7 @@ def main(): print(f"\nMigrations: {applied} applied, {skipped} skipped.") + sync_role_passwords(conn) verify_schema(conn) conn.close() print("Startup checks passed.\n")