Secrets & Contracts¶
Source of truth
hns-platform/inventory/group_vars/all/secrets.yml (the vault_* catalog) and each service's .platform.yml (which env var each side consumes). Update this page when those change.
Names only — never values
This page lists secret names and the wires between services. It contains no secret values, and neither should any documentation. Values live in the Nebion UI (or ansible-vault).
How secrets are stored¶
Every credential is an env-driven vault_* variable in secrets.yml, following the same lookup-with-default pattern as the rest of configuration. The Nebion UI env var name is the uppercase of the variable name without the vault_ prefix — e.g. vault_stripe_secret_key ← STRIPE_SECRET_KEY. Dev defaults are placeholders; production must override them in the Nebion UI.
Cross-service shared-secret contracts¶
Some secrets are held identically by two services, sometimes under different env-var names on each side of the wire. Rotation must update all holders in one coordinated change — an out-of-order rollout opens a 401/403 window.
| Contract | Sender side | Receiver side | Wire | Platform var |
|---|---|---|---|---|
| Internal webhook bearer | eventbus NATS_WEBHOOK_SECRET |
backend INTERNAL_WEBHOOK_SECRET |
Authorization: Bearer on /api/v1/internal/webhooks/* |
vault_nats_webhook_secret |
| User-sync webhook | eventbus BACKEND_USER_SYNC_WEBHOOK_SECRET |
backend USER_SYNC_WEBHOOK_SECRET (and KC KC_USER_SYNC_WEBHOOK_SECRET) |
X-Webhook-Secret on /api/v1/internal/users/sync |
vault_user_sync_webhook_secret |
| Mailer API key | eventbus MAILER_API_KEY |
mailer MAILER_API_KEY |
X-API-Key |
vault_mailer_api_key |
| KC backend client secret | admin/quota portals + backend (token-exchange) | Keycloak hns-backend client |
OIDC client secret | vault_kc_backend_client_secret |
Two contracts deliberately do NOT live here
- Stripe webhook signature (
STRIPE_WEBHOOK_SECRET) is verified once, upstream, inhns-stripe-microservice(the router) and never propagated — destinations trust the router and guard the internal hop with the internal-webhook bearer above. It is therefore not in this platform'ssecrets.yml. - Drupal webhook (
DRUPAL_WEBHOOK_SECRET, eventbus → Drupal) belongs to the externally-hosted Drupal webshop, not this cluster.
Backend holds the KC client secret (code vs. orientation)
Per backend's .platform.yml, the backend is a confidential KC client: it sets KEYCLOAK_CLIENT_SECRET (= vault_kc_backend_client_secret) to perform RFC 8693 token-exchange for admin masquerade. This refines the general "backend validates JWTs via JWKS only" description — the code is authoritative.
Platform secret catalog¶
All defined in secrets.yml (Nebion env var = uppercase, vault_-stripped). Values omitted by design.
| Group | Variables (env-var names) |
|---|---|
| Database | DB_USER, DB_PASS, KC_DB_USER, KC_DB_PASS |
| App secrets | APP_SECRET, ADMIN_APP_SECRET, QUOTA_APP_SECRET |
| Keycloak admin | KC_ADMIN_USER, KC_ADMIN_PASS, KC_BACKEND_CLIENT_SECRET |
MAILER_API_KEY, MAILGUN_API_KEY, SMTP_USERNAME, SMTP_PASSWORD, MAILPIT_UI_AUTH |
|
| Push | NTFY_BASIC_AUTH |
| Stripe | STRIPE_PUBLISHABLE_KEY, STRIPE_SECRET_KEY |
| Inter-service webhooks | NATS_WEBHOOK_SECRET, USER_SYNC_WEBHOOK_SECRET |
| Social IdP | GOOGLE_*, FACEBOOK_*, APPLE_* (client IDs/secrets + Apple signer) |
| Waiting-room | WAITING_ROOM_DB_PASS, WAITING_ROOM_JWT_SECRET, WAITING_ROOM_BOOTSTRAP_TOKEN, WAITING_ROOM_SEED_EMAIL, WAITING_ROOM_SEED_PASSWORD, WAITING_ROOM_TENANT_API_KEY |
S3 keys are referenced but not yet defined
Backend's .platform.yml references vault_s3_access_key / vault_s3_secret_key (with empty defaults), but they are not defined in secrets.yml — S3-backed PDF ticket storage is blocked on credentials. Until they exist, S3_ACCESS_KEY / S3_SECRET_KEY resolve to empty in pods.
Rotation¶
To rotate a shared secret: set the new value for every holder in the Nebion UI (both env-var names where they differ), then redeploy the affected services together. Rotating one side first guarantees an auth-failure window until the other catches up.
Last Updated: June 2026