Environment Configuration¶
Source of truth
hns-platform/inventory/group_vars/all/main.yml (non-secret config) and secrets.yml (vault vars), each service's .platform.yml (which vars it consumes), and .nebion.yml (Nebion UI override surface). Update this page when those change.
In the cluster, configuration flows through one override chain into each pod. Understanding it answers "where do I change DOMAIN?" and "why is this env var empty in the pod?".
The override chain¶
Every platform value is defined in inventory with an env lookup and a default:
# inventory/group_vars/all/main.yml
domain: "{{ lookup('ansible.builtin.env', 'DOMAIN', default='portal.hnst.dev3.wsagency.io') }}"
At deploy time, Ansible runs on app-01 and resolves each value:
1. Nebion UI env var (or exported shell var) ── highest precedence
│ e.g. DOMAIN=ver2.portal.hnst.dev3.wsagency.io
▼ (read by lookup('ansible.builtin.env', 'DOMAIN', …))
2. group_vars/all/env.yml (gitignored local overrides, e.g. platform_target)
group_vars/{staging,production}.yml (environment-specific definitions)
▼
3. inventory default ── the default='…' in main.yml / secrets.yml
So Nebion UI is the runtime knob: set a variable there and the matching lookup(... 'VAR' ...) picks it up on the next deploy; leave it unset and the inventory default applies. Secrets follow the identical pattern in secrets.yml (env var name = uppercase of the vault_-stripped variable name) — see Secrets & contracts.
How a value reaches a pod¶
main.yml: backend_api_url = http://hns-ticketing-backend:80/api/v1
│
▼ referenced in the service's .platform.yml
.platform.yml: env: { BACKEND_API_URL: "{{ backend_api_url }}" }
│
▼ hns-service role renders deployment.yml.j2
Pod env: BACKEND_API_URL=http://hns-ticketing-backend:80/api/v1
A variable must be declared in .platform.yml to reach the pod
Defining a value in main.yml does nothing on its own — the service's .platform.yml must reference it under a container's env:. This is the same per-mode boundary described on the overview: cluster env comes from .platform.yml, not from .env.example.
Env values are rendered with string | to_json, so a value containing backslashes or quotes (such as cors_allow_origin's anchored regex) is encoded correctly rather than breaking the YAML.
Nebion-overridable knobs (non-secret)¶
| Env var | Default | Purpose |
|---|---|---|
K8S_NAMESPACE |
(none — refuses to deploy) | Target namespace; hns = baseline |
DB_NAME |
hns_ticketing |
Backend database on db-01 (preview ⇒ non-baseline) |
DOMAIN |
portal.hnst.dev3.wsagency.io |
Base domain for all ingress hosts |
<SERVICE>_VERSION |
dev |
Git ref per service (BACKEND_VERSION, ADMIN_VERSION, …) |
REDIS_URL |
redis://hns-backend-redis:6379 |
Backend Redis |
MAILER_MODE |
mailpit |
mailpit (dev) or mailgun (prod) |
MAILGUN_DOMAIN / MAILGUN_BASE_URL |
email.shop.hns.family / EU API |
Mailgun config (prod) |
SMTP_HOST / SMTP_PORT / SMTP_TLS |
localhost / 1025 / starttls |
Mailer SMTP mode |
OTEL_TRACES_EXPORTER |
none |
none or otlp |
DRUPAL_SSO_URL |
https://dev1.hns.dev.wsagency.io |
Webshop links in emails |
K8S_NAMESPACE, DB_NAME, DOMAIN, and the <SERVICE>_VERSION set are the per-composition knobs — see Compositions & environments.
image_delivery selects how images reach the cluster
image_delivery (registry | k3d) is the image-delivery axis. The cluster default is registry (build + push/pull via the internal registry); local k3d sets image_delivery: k3d in inventory/local-k3d.vars.yml to build and k3d image import instead — no registry. See Local development (k3d). (This replaced the former platform_target k3s/minikube switch; minikube support was removed.)
Secrets¶
All credentials are env-driven vault_* variables in secrets.yml, set in the Nebion UI (or, historically, ansible-vault). Their names and the cross-service contracts are documented on Secrets & contracts. No secret values appear in this documentation.
Last Updated: June 2026