From e16f322869c35e9f30d6bc1c6bfa5c07b6cb55c2 Mon Sep 17 00:00:00 2001 From: Protocol dd0c Agent Date: Tue, 3 Mar 2026 05:04:42 +0000 Subject: [PATCH] add db-setup service: idempotent per-service Postgres user bootstrap Runs on every 'docker compose up -d' before product services start. Creates dd0c_{drift,alert,portal,cost,run} users with least-privilege grants if they don't exist. Fixes auth failures on existing PG volumes that predate the security hardening. --- products/docker-compose.yml | 42 +++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/products/docker-compose.yml b/products/docker-compose.yml index aeaadf2..2479e71 100644 --- a/products/docker-compose.yml +++ b/products/docker-compose.yml @@ -53,6 +53,43 @@ services: - meili_data:/meili_data + # --- DB User Bootstrap (idempotent, runs every up) --- + db-setup: + image: postgres:16-alpine + restart: "no" + depends_on: + postgres: { condition: service_healthy } + environment: + PGHOST: postgres + PGUSER: ${POSTGRES_USER:-dd0c} + PGPASSWORD: ${POSTGRES_PASSWORD:-dd0c-dev} + DB_DRIFT_PASSWORD: ${DB_DRIFT_PASSWORD:-dd0c-dev} + DB_ALERT_PASSWORD: ${DB_ALERT_PASSWORD:-dd0c-dev} + DB_PORTAL_PASSWORD: ${DB_PORTAL_PASSWORD:-dd0c-dev} + DB_COST_PASSWORD: ${DB_COST_PASSWORD:-dd0c-dev} + DB_RUN_PASSWORD: ${DB_RUN_PASSWORD:-dd0c-dev} + entrypoint: ["sh", "-c"] + command: + - | + set -e + create_user() { + local db=$$1 user=$$2 pass=$$3 + psql -d postgres -c "DO \$$\$$ BEGIN CREATE USER $$user WITH PASSWORD '$$pass'; EXCEPTION WHEN duplicate_object THEN ALTER USER $$user WITH PASSWORD '$$pass'; END \$$\$$;" + psql -d "$$db" -c "GRANT CONNECT ON DATABASE $$db TO $$user;" + psql -d "$$db" -c "GRANT USAGE ON SCHEMA public TO $$user;" + psql -d "$$db" -c "GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO $$user;" + psql -d "$$db" -c "GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO $$user;" + psql -d "$$db" -c "ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO $$user;" + psql -d "$$db" -c "ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT USAGE, SELECT ON SEQUENCES TO $$user;" + echo "✓ $$user → $$db" + } + create_user dd0c_drift dd0c_drift "$$DB_DRIFT_PASSWORD" + create_user dd0c_alert dd0c_alert "$$DB_ALERT_PASSWORD" + create_user dd0c_portal dd0c_portal "$$DB_PORTAL_PASSWORD" + create_user dd0c_cost dd0c_cost "$$DB_COST_PASSWORD" + create_user dd0c_run dd0c_run "$$DB_RUN_PASSWORD" + echo "db-setup complete" + # --- dd0c Products --- # P1: LLM Cost Router (Rust — API server) # NOTE: Rust services are behind the "rust" profile because they take 10+ min to compile. @@ -127,6 +164,7 @@ services: depends_on: postgres: { condition: service_healthy } redis: { condition: service_healthy } + db-setup: { condition: service_completed_successfully } # P3: Alert Intelligence alert: @@ -146,6 +184,7 @@ services: depends_on: postgres: { condition: service_healthy } redis: { condition: service_healthy } + db-setup: { condition: service_completed_successfully } # P4: Lightweight IDP / Service Catalog portal: @@ -167,6 +206,7 @@ services: postgres: { condition: service_healthy } redis: { condition: service_healthy } meilisearch: { condition: service_started } + db-setup: { condition: service_completed_successfully } # P5: AWS Cost Anomaly Detection cost: @@ -187,6 +227,7 @@ services: depends_on: postgres: { condition: service_healthy } redis: { condition: service_healthy } + db-setup: { condition: service_completed_successfully } # P6: Runbook Automation (SaaS) run: @@ -206,6 +247,7 @@ services: depends_on: postgres: { condition: service_healthy } redis: { condition: service_healthy } + db-setup: { condition: service_completed_successfully } # dd0c Console (React SPA) console: