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) |
| ⏳ | 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.
| Var | Env name (UI) | Default | Services | UI required | Notes |
|---|---|---|---|---|---|
domain |
DOMAIN |
portal.hnst.dev3.wsagency.io |
all (composes *.{domain}) |
yes | Base domain; all public URLs derive from it |
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 |
|---|---|---|---|
k8s_namespace |
hns |
infra | |
database_url |
postgresql://... (uses vault_db_*) |
backend | |
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-05.
main.yml: ~30 vars (16 B-lookups + 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
Last Updated: May 2026