How to Use Environment Variables in Jinja2 Templates¶
TL;DR¶
Register os.getenv as a global in the Jinja2 environment so any template — whether from jinja_render, jinja_render_convert, or a custom fetch module — can resolve environment variables inline with {{ getenv('VAR', 'default') }}. No imports, no extra .render() arguments.
When to use this¶
You have an API base URL that varies per environment and don’t want to hardcode it in the template
You need to inject a tenant-specific value from the environment into a generated field (e.g., an issuer URL, a region code)
You want to keep a single
config.yamlacross dev/staging/prod and resolve differences from the environment
Prerequisites¶
oaa-runner version that includes
jinja_env.globals['getenv'] = os.getenv(post-2026-07-06)Environment variables set before running
oaa app run
How it works¶
One line in src/oaa/utils.py:
jinja_env.globals['getenv'] = os.getenv
This makes os.getenv callable as getenv(...) inside any Jinja2 template rendered by the oaa-runner framework. The second argument to getenv is the fallback default — if the variable is not set, that string is used instead.
Basic usage¶
In a field mapping, reference environment variables directly in the template:
transforms:
- name: jinja_render
options:
template: "{{ getenv('ISSUER_URL', 'https://default.issuer.com') }}/api/v2/users/{{ row.id }}"
If ISSUER_URL is set in the environment → uses that. If not → falls back to https://default.issuer.com.
Using with jinja_render_convert¶
transforms:
- name: jinja_render_convert
options:
template: "{{ getenv('REGION', 'us-east-1') }}:{{ value }}"
Combining with required_env¶
For a hard requirement (fail the run if the var is missing), list it in required_env on the connection. For a soft default (use a fallback if unset), use getenv('VAR', 'default') in the template.
connections:
my_api:
connection_type: api
required_env:
- API_KEY # hard requirement — fails early if missing
params:
base_url: "{{ getenv('BASE_URL') }}" # soft — resolves at render time
In custom fetch modules¶
If you are calling simple_jinja_render from a Python module:
from oaa.utils import simple_jinja_render
path = simple_jinja_render("/api/{{ getenv('TENANT') }}/users")
Security¶
getenvis resolved at render time — values are not stored inconfig.yamlor serialized to diskThe fallback default is the string literal in the template — it is visible in
config.yamlFor sensitive values, prefer
required_envvalidation +connection.paramsinjection, and only usegetenvin templates for non-secret configuration like URLs, regions, or log levels