Environment Variables¶
Reference of every environment variable consumed by the HNS Ticketing services, the category each variable belongs to, where its value is defined, and which services read it.
This page is the working reference when adding, changing, or auditing env vars across the platform.
Where values live¶
| Source | Description |
|---|---|
hns-platform/inventory/group_vars/all/main.yml |
Platform-level constants and computed topology (categories A and D) plus settings exposed to the deployment UI (category B) |
hns-platform/inventory/group_vars/all/secrets.yml |
Secret values (category C), referenced as vault_* vars |
<service>/.platform.yml |
Per-service env wiring — pulls platform values into the container and declares service-local literals (category E) |
The Nebion deployment UI exposes any platform setting (B) or secret (C) for override at deploy time. Constants (A), topology (D), and service-local literals (E) are not UI-overridable.
Legend¶
Categories¶
| Category | Where defined | UI-overridable? |
|---|---|---|
| A | Platform constant in main.yml |
no |
| B | Platform setting (env-lookup) in main.yml |
yes |
| C | Secret (env-lookup) in secrets.yml as vault_* |
yes |
| D | Service topology in main.yml (computed) |
no |
| E | Service-local in <service>/.platform.yml (literal/lookup) |
no |
Status¶
| Status | Meaning |
|---|---|
| ✅ | Wired and deployed |
| 🆕 | Added 2026-05-04 (idp wiring) or 2026-05-11 (Phase 0 preview environments) |
| ⏳ | Pending backend wiring |
| ⚠️ | Has a known issue (see notes column) |
Table 1 — Platform settings (B), main.yml lookups¶
These are deployment-time settings exposed to the Nebion UI. Each has a sensible default for development and is overridden per environment.
Table 1a — Composition knobs (Phase 0, 🆕 2026-05-11)¶
These configure WHERE a stack lands and WHICH branches it uses. Required for parallel preview compositions (see the Preview Environments Plan in the workspace dev-docs/). Read by hns-platform itself, not by service repos.
| Var | Env name (UI) | Default | UI required | Notes |
|---|---|---|---|---|
k8s_namespace |
K8S_NAMESPACE |
none | always | Target k8s namespace. hns for baseline, hns-<slug> for previews. Playbooks/Makefile/Nebion-recipe refuse to run without it — guards against accidental baseline overwrite. |
db_name |
DB_NAME |
hns_ticketing |
preview only | Backend Postgres DB name on db-01. Preview compositions MUST set this to a non-baseline value (e.g. hns_ticketing_pr34); a second guard blocks preview-namespace + baseline-DB combinations. |
domain |
DOMAIN |
portal.hnst.dev3.wsagency.io |
recommended | Base domain. All service ingress hosts derive: admin.{{ domain }}, api.{{ domain }}, etc. Previews use a different value to avoid host collisions. |
backend_version |
BACKEND_VERSION |
platform |
no | Git ref of hns-ticketing-backend. |
admin_version |
ADMIN_VERSION |
platform |
no | Git ref of hns-admin-portal. |
quota_version |
QUOTA_VERSION |
platform |
no | Git ref of hns-quota-portal. |
idp_version |
IDP_VERSION |
platform |
no | Git ref of hns_idp. |
mailer_version |
MAILER_VERSION |
platform |
no | Git ref of hns-mailer. |
eventbus_version |
EVENTBUS_VERSION |
dev |
no | Git ref of hns-ticketing-eventbus (deploys from dev by convention). |
Table 1b — Service-facing settings¶
| Var | Env name (UI) | Default | Services | UI required | Notes |
|---|---|---|---|---|---|
cert_issuer |
CERT_ISSUER |
letsencrypt-staging |
infra | yes | Flip to letsencrypt-prod before public release |
otel_traces_exporter |
OTEL_TRACES_EXPORTER |
none |
admin, quota | yes | Set to otlp to enable Tempo tracing |
drupal_sso_url |
DRUPAL_SSO_URL |
https://dev1.hns.dev.wsagency.io |
backend ⏳ | yes | |
drupal_sso_host |
DRUPAL_SSO_HOST |
dev1.hns.dev.wsagency.io |
backend ⏳ | yes | |
drupal_api_prefix |
DRUPAL_API_PREFIX |
/167ef06... |
backend ⏳ | yes | |
mailer_mode |
MAILER_MODE |
mailpit |
mailer | yes | dev=mailpit; staging+ MUST be mailgun |
mailgun_domain |
MAILGUN_DOMAIN |
email.shop.hns.family |
mailer | yes | |
mailgun_base_url |
MAILGUN_BASE_URL |
https://api.eu.mailgun.net |
mailer | yes | |
mailpit_base_url |
MAILPIT_BASE_URL |
http://hns-mailpit:8025 |
mailer | yes | |
smtp_host |
SMTP_HOST |
localhost |
mailer | yes | Only used when MAILER_MODE=smtp |
smtp_port |
SMTP_PORT |
1025 |
mailer | yes | |
smtp_tls |
SMTP_TLS |
starttls |
mailer | yes |
Table 2 — Secrets (C), secrets.yml lookups¶
Secrets are stored under vault_* keys in secrets.yml and are exposed to services with the env name shown below.
Production rotation required
Defaults marked admin, change-me, keycloak, 123456, etc. are development conveniences and must be rotated before any non-dev environment.
| Vault var | Env name (UI) | Default | Services | Notes |
|---|---|---|---|---|
vault_db_user |
DB_USER |
hns |
backend | Composed into database_url |
vault_db_pass |
DB_PASS |
hns |
backend | Composed into database_url |
vault_kc_db_user |
KC_DB_USER |
keycloak |
idp (Postgres + KC) | Both sides read the same var |
vault_kc_db_pass |
KC_DB_PASS |
keycloak |
idp | |
vault_kc_admin_user |
KC_ADMIN_USER |
admin |
idp 🆕 | DX default; must change for prod |
vault_kc_admin_pass |
KC_ADMIN_PASS |
admin |
idp 🆕 | |
vault_kc_backend_client_secret |
KC_BACKEND_CLIENT_SECRET |
'' |
idp 🆕 | OIDC secret for shared hns-backend client |
vault_user_sync_webhook_secret |
USER_SYNC_WEBHOOK_SECRET |
'' |
idp 🆕 | Must equal eventbus KC_USER_SYNC_WEBHOOK_SECRET once 40-user-sync.yml is wired |
vault_app_secret |
APP_SECRET |
change-me |
backend ⏳ | To be renamed vault_backend_app_secret |
vault_admin_app_secret |
ADMIN_APP_SECRET |
change-me |
admin | |
vault_quota_app_secret |
QUOTA_APP_SECRET |
change-me |
quota | |
vault_mailer_api_key |
MAILER_API_KEY |
123456 |
mailer, eventbus, idp | Shared across 3 services |
vault_mailgun_api_key |
MAILGUN_API_KEY |
'' |
mailer | Empty default → mailer fails fast |
vault_smtp_username |
SMTP_USERNAME |
'' |
mailer | Only when MAILER_MODE=smtp |
vault_smtp_password |
SMTP_PASSWORD |
'' |
mailer | |
vault_mailpit_ui_auth |
MAILPIT_UI_AUTH |
'' |
mailer (mailpit) | Format user:bcrypt-hash; empty = open UI |
vault_nats_webhook_secret |
NATS_WEBHOOK_SECRET |
'' |
eventbus | Backend ↔ eventbus auth |
vault_stripe_publishable_key |
STRIPE_PUBLISHABLE_KEY |
'' |
backend ⏳, quota | |
vault_google_client_id |
GOOGLE_CLIENT_ID |
'' |
idp 🆕 | |
vault_google_client_secret |
GOOGLE_CLIENT_SECRET |
'' |
idp 🆕 | |
vault_google_ios_client_id |
GOOGLE_IOS_CLIENT_ID |
'' |
idp 🆕 | |
vault_google_android_client_id |
GOOGLE_ANDROID_CLIENT_ID |
'' |
idp 🆕 | |
vault_facebook_client_id |
FACEBOOK_CLIENT_ID |
'' |
idp 🆕 | |
vault_facebook_client_secret |
FACEBOOK_CLIENT_SECRET |
'' |
idp 🆕 | |
vault_apple_client_id |
APPLE_CLIENT_ID |
'' |
idp 🆕 | |
vault_apple_client_secret |
APPLE_CLIENT_SECRET |
'' |
idp 🆕 | |
vault_apple_team_id |
APPLE_TEAM_ID |
'' |
idp 🆕 (JWT signer) | |
vault_apple_key_id |
APPLE_KEY_ID |
'' |
idp 🆕 (JWT signer) | |
vault_apple_private_key |
APPLE_PRIVATE_KEY |
'' |
idp 🆕 (JWT signer) | Multi-line PEM, escape \n |
Table 3 — Topology (A/D), main.yml, no UI¶
Constants and computed values. Not exposed in the deployment UI.
| Var | Composed value | Services | Notes |
|---|---|---|---|
database_url |
postgresql://.../{{ db_name }} (uses vault_db_* + db_name) |
backend | db_name is per-composition (see Table 1a); baseline → hns_ticketing, preview → hns_ticketing_<slug> |
redis_url |
redis://redis:6379 |
backend | ⚠️ redis service doesn't exist yet; needs an inline hns-ticketing-redis deployment in backend .platform.yml |
nats_url |
nats://nats:4222 |
idp ✅, backend ⏳ | |
mailer_url |
http://hns-mailer:6006 |
idp (+/send), eventbus (+/webhook) |
Inline composition with path |
backend_url |
http://hns-ticketing-backend:80 |
building block | |
backend_api_url |
{{ backend_url }}/api/v1 |
admin, quota, eventbus | |
admin_public_url |
https://admin.{{ domain }} |
admin ✅, backend ⏳ (APP_PORTAL_URL) |
|
quota_public_url |
https://quota.{{ domain }} |
quota ✅, backend ⏳ (APP_QUOTA_PORTAL_URL) |
|
mailer_dsn |
smtp://hns-mailpit:1025 |
backend | ⚠️ Plan calls for null://null (backend publishes via NATS); not yet applied |
social_login_client_id |
mobile-app |
idp 🆕 | Constant; not UI-overridable |
cert_manager_version, cert_email |
literals | infra | |
loki_business_url, loki_ops_url, prometheus_url, tempo_url |
k8s service URLs | observability stack | |
s3_endpoint |
https://nbg1.your-objectstorage.com |
backend ⏳ | Hardcoded literal; planned move to env-lookup |
Table 4 — Service-local (E), brief¶
Not platform-level; live as literals in each service's .platform.yml. Not UI-overridable.
| Service | Local env vars (literals) |
|---|---|
| backend | APP_ENV=prod, MAILER_SENDER, OTEL_* block (8 vars) |
| admin / quota | APP_ENV=prod, OTEL_* block (8 vars), inline REDIS_URL for own redis |
| idp | KC_DB, KC_CACHE=ispn, KC_HEALTH_ENABLED, KC_METRICS_ENABLED, POD_IP, KC_CACHE_EMBEDDED_NETWORK_BIND_ADDRESS, KC_SPI_EMAIL_SENDER_HTTP_EMAIL_TRANSPORT, *_TIMEOUT_MS (×2), TEST_OTP (env lookup), JAVA_OPTS_APPEND |
| mailer | LISTEN_ADDR=0.0.0.0:6006, DATA_DIR=/data, MAX_CONCURRENT_SENDS=50, MAX_RETRIES=5, DEDUP_TTL_SECS=120, RETRY_BACKOFF=5,15,60,300, SHUTDOWN_TIMEOUT_SECS=30, SENT_RETENTION_SECS=86400, RUST_LOG=info |
| eventbus | Only platform-derived URLs/secrets; no service-local literals |
Table 5 — Pending / gaps¶
Variables planned but not yet wired.
| What | Where | Notes |
|---|---|---|
vault_jwt_passphrase + 2 path literals (JWT_SECRET_KEY, JWT_PUBLIC_KEY) |
secrets + backend .platform.yml |
Symfony JWT — currently absent |
vault_stripe_secret_key, vault_stripe_webhook_secret |
secrets | sk_live / whsec |
vault_drupal_webhook_secret |
secrets | Backend ↔ Drupal sync auth |
vault_s3_access_key, vault_s3_secret_key, s3_bucket |
secrets + main | Hetzner Object Storage |
vault_eracuni_* (×3) |
secrets + backend .platform.yml |
Invoicing — client code not yet implemented |
vault_firebase_credentials + init container |
secrets + backend .platform.yml |
JSON-as-env special case |
vault_loki_push_user/password, loki_push_url, prometheus_push_url, nebion_env_identifier |
secrets + main | Grafana Cloud push auth (observability) |
email_driver, mailer_dsn=null://null |
main | Backend publishes via NATS |
push_notification_driver, ntfy_url |
main | |
| 6× user-sync env (3 URL + 3 secret) | secrets + eventbus .platform.yml |
KC, Drupal, backend each as user.updated consumers; wired with 40-user-sync.yml |
hns-mailer ingress |
hns-mailer .platform.yml |
Needed once standalone-eventbus needs a public URL |
Backend redis service |
backend .platform.yml (inline deployment) |
See Table 3 ⚠️ |
mailer_dsn → null://null |
main | Closes the email-driver gap |
Rename vault_app_secret → vault_backend_app_secret |
secrets + backend .platform.yml |
Naming alignment |
Counts¶
Snapshot: 2026-05-11.
main.yml: ~40 vars (16 B-lookups + 9 composition knobs added in Phase 0 + 14 A/D)secrets.yml: 30vault_*vars (16 from earlier steps + 14 added 2026-05-04 — 11 social IdP + 3 KC/user-sync)- Service-local (E): ~50 (mostly OTel block × 3 services + mailer tuning)
- Pending wiring: 15–20 vars (mostly backend step 6 — see
dev-docs/envs/audit/audit-01-backend.md)
Last Updated: 2026-05-11