Environment variables
Each environment (zone) of a Product has its own environment variables, set under Product → Settings → Instances → the environment → Environment variables. Org admins change them; everyone else in the org sees the plain values and the names of the secret ones.
Plain and secret
| Plain | Secret | |
|---|---|---|
| Where the value lives | The zone's values file in the gitops repo (env:), reviewed and versioned like the rest | A Kubernetes Secret in the cluster, never in git |
| Who can read it | Anyone who can read the gitops repo, and everyone in the org in Infrared | Nobody in Infrared: after you save, Infrared shows only that it's set and when |
| How the app gets it | env on the container | envFrom the Secret <product>-env in the zone's namespace |
Tick Secret on a row to keep its value out of git. A stored secret shows Secret · set · updated … with Replace (type a new value; Keep it cancels) and Remove. Names are letters, digits and _, not starting with a digit, each used once per environment; PORT is set by the chart. A value can be up to 32 KiB, and an environment's secrets 512 KiB in all, up to 100 variables.
Save variables applies the change: the zone's values file gets the plain variables (and, after a change to a secret, a new envVersion), Infrared asks Argo CD to sync at once, and the environment's pods roll to pick the change up. The instance shows the rollout: committed, syncing, live.
Secret variables need the zone to run on the management cluster; on workload clusters they aren't supported yet, while plain ones work everywhere.
Paste a .env
Paste .env takes a whole block of NAME=value lines at once, or Load a .env file reads one from disk. Comments, blank lines and export are fine, and values can be quoted. Names that look secret (ending in SECRET, TOKEN, KEY, PASSPHRASE and the like) are marked Secret; check the list, then Save variables saves them all together. A name already listed takes the pasted value.
Secret values are masked on screen without being password fields, and the inputs tell password managers (1Password, LastPass, Bitwarden, the browser's own) to leave them alone, so they aren't autofilled or cleared.
How it works
The API keeps a zone's secret values in the Secret <product>-<zone>-env in the org's namespace (ir-org-<org>), labelled with the Product and zone, and never returns them. The operator copies it into the zone's namespace as <product>-env, which the chart reads with envFrom (optional, so a zone without secrets runs too). Each change to the secret values sets a new version on that Secret, which Infrared writes into the zone's values file as envVersion; the chart puts it on the pod template, so the pods roll. The version is a timestamp, never derived from the values.
Plain variables are stored in the Product's spec (spec.delivery.zones[].env) and written to the values file; secret ones appear in the spec by name only (secretEnv).
Your own chart
Products Infrared scaffolded get this from their chart. Charts scaffolded earlier are updated through the gitops repo, unless the deployment template was edited where these lines go; the Environment variables section then says so. A chart you wrote, or edited, needs these lines in its Deployment:
spec:
template:
metadata:
{{- with .Values.envVersion }}
annotations:
infrared.darkshift.io/env-version: {{ . | quote }}
{{- end }}
spec:
containers:
- name: web
env:
{{- range .Values.env }}
- name: {{ .name | quote }}
value: {{ .value | quote }}
{{- end }}
envFrom:
- secretRef:
name: {{ .Release.Name }}-env
optional: true
API
# Read: plain values, secret names with when each was set.
curl -H "Authorization: Bearer $INFRARED_TOKEN" https://<host>/api/v1/orgs/<org>/products/<product>/zones/<zone>/env
# Replace: the lists are the whole set; a secret without "value" keeps its stored value, one left out is removed.
curl -X PUT -H "Authorization: Bearer $INFRARED_TOKEN" -H 'Content-Type: application/json' \
https://<host>/api/v1/orgs/<org>/products/<product>/zones/<zone>/env \
-d '{"generation": 7, "env": [{"name": "API_URL", "value": "https://api.example.com"}], "secrets": [{"name": "STRIPE_KEY", "value": "sk_live_…"}]}'
Send the generation you read to get a 409 instead of overwriting someone else's change.