Merge pull request #107 from trails-cool/grafana-postgres-datasource
Add PostgreSQL datasource to Grafana with read-only user
This commit is contained in:
commit
2a5615dfdf
5 changed files with 64 additions and 7 deletions
7
.github/workflows/cd-infra.yml
vendored
7
.github/workflows/cd-infra.yml
vendored
|
|
@ -68,6 +68,13 @@ jobs:
|
|||
GHCR_TOKEN=$(grep DEPLOY_GHCR_TOKEN .env | cut -d= -f2-)
|
||||
echo "$GHCR_TOKEN" | docker login ghcr.io -u stigi --password-stdin 2>/dev/null || true
|
||||
|
||||
# Setup Grafana read-only DB user (idempotent)
|
||||
docker compose exec -T postgres psql -U trails -d trails -f /docker-entrypoint-initdb.d/init-grafana-user.sql 2>/dev/null || true
|
||||
GRAFANA_DB_PW=$(grep GRAFANA_DB_PASSWORD .env | cut -d= -f2-)
|
||||
if [ -n "$GRAFANA_DB_PW" ]; then
|
||||
docker compose exec -T postgres psql -U trails -d trails -c "ALTER ROLE grafana_reader PASSWORD '$GRAFANA_DB_PW'" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# Full restart: gh workflow run cd-infra.yml -f restart_all=true
|
||||
if [ "${{ github.event.inputs.restart_all }}" = "true" ]; then
|
||||
docker compose --env-file .env up -d --remove-orphans
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ services:
|
|||
POSTGRES_DB: trails
|
||||
volumes:
|
||||
- pgdata:/var/lib/postgresql/data
|
||||
- ./postgres/init-grafana-user.sql:/docker-entrypoint-initdb.d/init-grafana-user.sql:ro
|
||||
command:
|
||||
- "postgres"
|
||||
- "-c"
|
||||
|
|
@ -154,6 +155,7 @@ services:
|
|||
GF_AUTH_GITHUB_ALLOWED_ORGANIZATIONS: trails-cool
|
||||
GF_AUTH_GITHUB_SCOPES: user:email,read:org
|
||||
GF_AUTH_DISABLE_LOGIN_FORM: "true"
|
||||
GRAFANA_DB_PASSWORD: ${GRAFANA_DB_PASSWORD:-}
|
||||
volumes:
|
||||
- ./grafana/provisioning:/etc/grafana/provisioning:ro
|
||||
- ./grafana/dashboards:/var/lib/grafana/dashboards:ro
|
||||
|
|
|
|||
|
|
@ -15,3 +15,18 @@ datasources:
|
|||
access: proxy
|
||||
url: http://loki:3100
|
||||
editable: false
|
||||
|
||||
- name: PostgreSQL
|
||||
uid: postgres
|
||||
type: postgres
|
||||
access: proxy
|
||||
url: postgres:5432
|
||||
user: grafana_reader
|
||||
editable: false
|
||||
jsonData:
|
||||
database: trails
|
||||
sslmode: disable
|
||||
maxOpenConns: 2
|
||||
maxIdleConns: 1
|
||||
secureJsonData:
|
||||
password: $__env{GRAFANA_DB_PASSWORD}
|
||||
|
|
|
|||
32
infrastructure/postgres/init-grafana-user.sql
Normal file
32
infrastructure/postgres/init-grafana-user.sql
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
-- Read-only user for Grafana dashboards
|
||||
-- Password is set via: ALTER ROLE grafana_reader PASSWORD '<from SOPS>'
|
||||
-- Run by cd-infra deploy script after container start
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname = 'grafana_reader') THEN
|
||||
CREATE ROLE grafana_reader WITH LOGIN;
|
||||
END IF;
|
||||
END
|
||||
$$;
|
||||
|
||||
GRANT CONNECT ON DATABASE trails TO grafana_reader;
|
||||
GRANT USAGE ON SCHEMA public TO grafana_reader;
|
||||
GRANT SELECT ON ALL TABLES IN SCHEMA public TO grafana_reader;
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO grafana_reader;
|
||||
|
||||
-- Also grant on planner/journal schemas if they exist
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (SELECT 1 FROM information_schema.schemata WHERE schema_name = 'planner') THEN
|
||||
GRANT USAGE ON SCHEMA planner TO grafana_reader;
|
||||
GRANT SELECT ON ALL TABLES IN SCHEMA planner TO grafana_reader;
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA planner GRANT SELECT ON TABLES TO grafana_reader;
|
||||
END IF;
|
||||
IF EXISTS (SELECT 1 FROM information_schema.schemata WHERE schema_name = 'journal') THEN
|
||||
GRANT USAGE ON SCHEMA journal TO grafana_reader;
|
||||
GRANT SELECT ON ALL TABLES IN SCHEMA journal TO grafana_reader;
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA journal GRANT SELECT ON TABLES TO grafana_reader;
|
||||
END IF;
|
||||
END
|
||||
$$;
|
||||
|
|
@ -1,10 +1,11 @@
|
|||
#ENC[AES256_GCM,data:IbWmlFr0kUJNYnRkD9Rt6tPAgtE+8TrECPY3MstykO8EPIZOvkg0T1hjGsDLca5NA8cdWqWWEmSF4o7ewvk=,iv:UD1YxHEH9PxnSrkVI/Nm9WVazGk9Kh+B8uzfNqjmf3I=,tag:+mWHdGvo+OeQFa4Ak/S3Pg==,type:comment]
|
||||
#ENC[AES256_GCM,data:BDOEQHz+QsQcQCzrD8XWcxREuNWELctcjsZahTmwEAYolct7EaW4G9bGI1K8BL8V5OejHvqtxgd34LHBAzTrTL66ATW/pWGY2lF/G69J4Q==,iv:4RyNDeZUZOgibkI7+aIyCJDxd/7jZMMaBIepQCbbHFA=,tag:v/mPe5ILLVS2bLUKFpOoJg==,type:comment]
|
||||
GF_AUTH_GITHUB_CLIENT_ID=ENC[AES256_GCM,data:4a1+g2U6a+XlfwSLLoJFWruvOLg=,iv:h1yDpE21XPxqOGBsE+E1Xunr0eAC2ALLP9x11XMPd6Q=,tag:zKWMUrCi1b2Ir8g1BcsAcA==,type:str]
|
||||
GF_AUTH_GITHUB_CLIENT_SECRET=ENC[AES256_GCM,data:LGbZHhQeLcS01UJXtZefsGUi0P8lscZRrho0HGq+hKRuoy5RO1HssA==,iv:NATDvm3fKe4zjJ36PWb/iJLVA2lJsognRLg0TZY5yw4=,tag:JYatVnyvrc0dYue2aTh55Q==,type:str]
|
||||
sops_age__list_0__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB4UiszMUJMYzFlWE5Qc3Zk\nUDF2V1BIYmIwbjVydHI5OTJoRVJXdFhDZDEwCmlEQTFKRUZwYVlQbVRJMEpHL2Vj\nd21pS3BwZHc3QklCMVl4ZHFzZUJYRWMKLS0tIEtQeFQvNGxRUGhqNnBzQ0ZvaXRY\nMFZjQlhobXBKT08yc0dLVGNwd0pHbmcKEAS/YRu2NhGCZLX+nkVjo7PEu7ZV4iCW\nyO9GIsaIQcN6FWmp5IkjdeM6jkHxSk+qHCL5bKx78EgPMgzKobjgzQ==\n-----END AGE ENCRYPTED FILE-----\n
|
||||
#ENC[AES256_GCM,data:0mZOnEJyXdCzF0HYzuVFkOmGOpfsTzfHbrwmCwU7NyeaDKFpoTvH1fQW/XCcflGaWPRrKRyCEYOa4sdPnag=,iv:iiEYiIqvmvOFQTEDPFeu7fkluWf0z/v+tvDmY7L0cFE=,tag:Ds/EHF6XSGfnv8ZCa5OU6w==,type:comment]
|
||||
#ENC[AES256_GCM,data:+au0EOdh5q7IY7qcP4Jko5dJz4AdDCF8ilBqKUCHb9hB8xlM2FHiyLrcf3Q0eYbAyg28xaTm+wewKDivvuoOv4grGohqezJ4Ypffm1Yg6g==,iv:zXrneKQUu+bL5oRFmz5nVdUcUolH0HDFuOSK460rmpc=,tag:WDybda6Q9WBEp+SuzfKQqw==,type:comment]
|
||||
GF_AUTH_GITHUB_CLIENT_ID=ENC[AES256_GCM,data:mik8yBpOAkJXHQ8vEeMZV2Y+KY4=,iv:DNZLDWxnichM9E4fitJSQdf0lxNsneYJxleIs6CPJgs=,tag:aXCt7Ff5PggBWaXvRYv9tw==,type:str]
|
||||
GF_AUTH_GITHUB_CLIENT_SECRET=ENC[AES256_GCM,data:jcGhMeBwOLZotvfExZWqyMtql1C7AC0hlus7Vl/RLvEjshPmNtO9yg==,iv:20HLImbrFMkWLQ+chInq0Ig9j2Q4NSLXFN+72jXxM/M=,tag:INKt4Icg9QI1PTD+KEfCHg==,type:str]
|
||||
GRAFANA_DB_PASSWORD=ENC[AES256_GCM,data:o1G5rDo1G4RiOGBbd7KDcqEIKG7UuwTlVx7BI7eVHWI=,iv:Fd1wA+4uB7Ypix8n4aTGKJo6V+uiCkr4yZ3wkGZ5rQA=,tag:c0qpH/v7lgmU5yXZo7n+RA==,type:str]
|
||||
sops_age__list_0__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBBbnY1VndkeE9hYnByK3RU\nRDFUYU5DcWhCRXYrdStoallzU0ZnWkJJeEY4CnBUYUlIK2ZhcUV2aWhqSDFSYnhD\nb1hkOGdkSGFyajRXNVg5a1FZcE9mQzQKLS0tIEVKZThiV1RMdkhhaWlvM05vY1g4\nYTNYUkFaYUJzbVUvMi83eHg1NXhXcGMKShBIdPKho4WmWiykqFXdmQ/NRAKoUpUw\ntUQKcGlrhHRhpgaFTyeKj+UVD1y52cXWZX9xhFdJ7TFxEO1opNc9LQ==\n-----END AGE ENCRYPTED FILE-----\n
|
||||
sops_age__list_0__map_recipient=age1vukt8py0s2mm47fx6qh6vykckfkdqslf9w68ekytfzvc8xp7e3rqn6p64n
|
||||
sops_lastmodified=2026-03-27T15:40:55Z
|
||||
sops_mac=ENC[AES256_GCM,data:pkYMdGTyjc6/ig/hdBD4GGeyiOkJBp/z9+w3vlT/bfHeje4FBZxjdmgykfCmNFJqov1MoysEsP0z8VZpdcSa+cjcJXVIhXcSpl4Uo/NXZuYRIuPkQztSGna+tStrpus4Zxk2SLe8IF5AFgPtuCwZvS7R7JE4KKbkKG/kfcTMrR8=,iv:SXzctdK5QEV6RZuSSxDor7MYPgEJGvSih4l3G2+lwYI=,tag:umAgJ94DM7DKVPPniCdRvw==,type:str]
|
||||
sops_lastmodified=2026-03-27T19:07:05Z
|
||||
sops_mac=ENC[AES256_GCM,data:hKi5AD4+FFL5/bDHnBfNvWipsUA0GOLVF0/l5o2I6bh5aD4l/ZJbL1hOdxq/2MO7eJPjej5AFqREEDbMKHwY7s9nvKJhNAjtg8ejRK/y1x8r8Skm790cjcT04hIbpIgc2yaM131eyOuz39q9HODAmCoLqrVBpkStEQYhId5gQcY=,iv:fFSYntpfurMfD5vzRgaVONMZe3NyxuJPw0w2lqqCyQs=,tag:8gPfB9sJpwUaG8cc43kesQ==,type:str]
|
||||
sops_unencrypted_suffix=_unencrypted
|
||||
sops_version=3.9.4
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue