envtpl: Render Jinja2 Templates From the Environment
envtpl renders a Jinja2 template using environment variables as the only data source, failing by default on any undefined variable.
envtpl is purpose-built for the Docker/CI pattern of "config from env". Unlike envsubst it is real Jinja2, so you get conditionals, loops, and filters.
What it does
envtpl reads a Jinja2 template and renders it with the current environment. By default an undefined variable is an error, which is the opposite (and safer) default from envsubst. It reads from stdin or a file and writes to stdout or a file whose name it can derive by stripping a .tpl suffix.
Common usage
# stdin to stdout
envtpl < nginx.conf.tpl > nginx.conf
# in-place style: writes nginx.conf, deletes the .tpl
envtpl nginx.conf.tpl
# tolerate missing variables (render them empty)
envtpl --allow-missing < app.conf.tpl > app.confOptions
| Flag | What it does |
|---|---|
| --allow-missing | Render undefined variables as empty instead of erroring |
| -o, --output <path> | Write to a specific output file |
| --keep-template | Do not delete the source .tpl after rendering to a file |
| (file.tpl) | Render file.tpl to file, stripping the .tpl suffix |
In CI
Keep the default strict behavior: envtpl erroring on a missing variable catches a mis-set secret before the container starts with a blank config. Only use --allow-missing for genuinely optional values. Because data comes solely from env, avoid printing the environment in logs where a rendered secret could leak.
Common errors in CI
"jinja2.exceptions.UndefinedError: 'DB_PASSWORD' is undefined" is the default strict failure when the variable is not exported; either export it or pass --allow-missing if it is truly optional. "jinja2.exceptions.TemplateSyntaxError" points at a malformed {% %} block. A template that renders blank fields despite set variables usually means the names differ in case, since env vars are case-sensitive.