# Shorashim Secrets — template only # NEVER commit actual secret values to git. # Apply with: kubectl apply -f - after filling in values. # # The DATABASE_URL connects to Exoscale PostgreSQL (temple-council-db) # in ch-gva-2 zone. Retrieve credentials from: # exo dbaas show temple-council-db --zone ch-gva-2 apiVersion: v1 kind: Secret metadata: name: shorashim-secrets namespace: shorashim type: Opaque stringData: # PostgreSQL connection for L3 Oral Tradition — the APPLICATION role. # Format: ecto://user:password@host:port/database?sslmode=require # This is shorashim_app: INSERT and SELECT on the L3 tables, no DDL, # no CREATE on schema public. Append-only is enforced by the grants, # not by the application's good behaviour. DATABASE_URL: "REPLACE_WITH_ACTUAL_DATABASE_URL" --- # ============================================================ # shorashim-migrate-secrets — the DDL role # ============================================================ # # KOHEN.md:184 — "the migration runs as avnadmin; the application runs # as shorashim_app." TWO ROLES, TWO SECRETS. Only the `migrate` init # container reads this one (deployment.yaml overrides DATABASE_URL for # that container alone); every app container keeps shorashim-secrets # above. # # WHY IT IS SEPARATE AND NOT JUST A GRANT: Ecto.Migrator.run/3 calls # ensure_schema_migrations_table! BEFORE checking what is pending, so # it issues CREATE TABLE IF NOT EXISTS schema_migrations on EVERY pod # start, even with migrations current. As shorashim_app that is # ERROR 42501 permission denied for schema public, and the pod never # reaches Running. The alternative — granting shorashim_app CREATE on # schema public — collapses the app/migration boundary the runbook # draws deliberately. Do not take it. # # THIS FILE IS A TEMPLATE. Never commit a real value. Create the secret # from the live database credential instead: # # export KUBECONFIG=~/.kube/exoscale-temple-council.yaml # umask 077 # TMP=$(mktemp) # # exo dbaas user reveal-secrets temple-council-db avnadmin \ # --zone ch-gva-2 -O json \ # | python3 -c ' # import base64, json, subprocess, sys, urllib.parse # avn = json.load(sys.stdin)["password"] # app = subprocess.run( # ["kubectl", "get", "secret", "shorashim-secrets", "-n", "shorashim", # "-o", "jsonpath={.data.DATABASE_URL}"], # capture_output=True, text=True, check=True).stdout # u = urllib.parse.urlsplit(base64.b64decode(app).decode()) # pw = urllib.parse.quote(avn, safe="") # netloc = "avnadmin:%s@%s:%d" % (pw, u.hostname, u.port) # sys.stdout.write( # urllib.parse.urlunsplit((u.scheme, netloc, u.path, u.query, u.fragment))) # ' > "$TMP" # # kubectl create secret generic shorashim-migrate-secrets \ # --namespace shorashim --from-file=DATABASE_URL="$TMP" # # rm -f "$TMP" # # The rewrite is done in Python, not with `sed s|...|...|`, on purpose. # A generated password containing & or | or \ corrupts a sed # replacement silently — & re-inserts the matched text and | ends the # expression early — and the result is a DATABASE_URL that looks # plausible and does not authenticate. quote(safe="") also percent- # encodes any character that is not URL-safe in the userinfo field, # which sed would have passed through raw. The value goes via a # umask-077 temp file rather than --from-literal so the password is # never an argv entry visible to `ps`. # # Absence is meant to be loud: without this secret the pod stops at # CreateContainerConfigError. There is no fallback to the app role. apiVersion: v1 kind: Secret metadata: name: shorashim-migrate-secrets namespace: shorashim type: Opaque stringData: # ecto://avnadmin:PASSWORD@host:port/database?sslmode=require DATABASE_URL: "REPLACE_WITH_AVNADMIN_DATABASE_URL"