# envsubst — Substitute Environment Variables in Text

> Practical guide to envsubst (GNU gettext): substitute environment variables in templates and text files — safely, without shell expansion.

Source: https://www.jpkc.com/db/en/cheatsheets/files-text/envsubst/

<!-- PROSE:intro -->
envsubst is part of GNU gettext and replaces every `$VAR` and `${VAR}` reference in a text with the value of the matching environment variable. Unlike `eval` or a shell, it performs **no** shell expansion – no command substitution, no globbing, no quoting tricks – it only swaps in variable values. That is exactly what makes it a safe tool for filling templates such as nginx configurations, `.env` files or Kubernetes manifests with values from the environment. Pass an argument like `'$VAR1 $VAR2'` to restrict substitution to specific variables, so other placeholders (for example nginx's own `$uri`) stay untouched. This guide walks you through the invocations you actually reach for, from Docker entrypoints to CI/CD pipelines.
<!-- PROSE:intro:end -->

## Basic Usage

`envsubst < <template> > <output>` — Replace all `$VAR` and `${VAR}` references with their values.

```bash
envsubst < config.template > config.conf
```

`echo '$HOME' | envsubst` — Substitute variables in piped text.

```bash
echo 'Hello $USER, your home is $HOME' | envsubst
```

`envsubst < <template>` — Output substituted content to stdout.

```bash
envsubst < nginx.conf.template
```

`cat <template> | envsubst > <output>` — Pipe template through envsubst.

```bash
cat docker-compose.yml.tmpl | envsubst > docker-compose.yml
```

## Restrict Variables

`envsubst '$VAR1 $VAR2' < <template>` — Only substitute specific variables (leave others as-is).

```bash
envsubst '$DB_HOST $DB_PORT' < config.template > config.conf
```

`envsubst '${VAR1}' < <template>` — Substitute only one specific variable.

```bash
envsubst '${APP_VERSION}' < version.txt.tmpl > version.txt
```

`envsubst --variables '<shell-format>'` — List all variable names referenced in the argument.

```bash
envsubst --variables "$(cat nginx.conf.template)"
```

## Docker & Container Usage

`envsubst < /etc/nginx/conf.d/default.conf.template > /etc/nginx/conf.d/default.conf` — Template an NGINX config in a Docker entrypoint.

```bash
envsubst '${NGINX_HOST} ${NGINX_PORT}' < default.conf.template > /etc/nginx/conf.d/default.conf
```

`envsubst < app.env.template > .env` — Generate a `.env` file from a template during deployment.

```bash
envsubst < app.env.template > .env
```

`envsubst '$VAR' < template` — Substitute only selected variables; all other `${...}` references stay literal.

```bash
echo 'Home: $HOME, keep: ${BUILD_ID}' | envsubst '$HOME'
```

## CI/CD & Scripting

`export VAR=value && envsubst < template > output` — Set a variable and substitute in one command chain.

```bash
export VERSION=1.2.3 && envsubst < manifest.yml.tmpl > manifest.yml
```

`VAR=value envsubst < template` — Inline variable definition for the envsubst call.

```bash
APP_NAME=myapp envsubst < deploy.yaml.tmpl
```

`env $(cat .env | xargs) envsubst < template` — Load variables from a `.env` file and substitute.

```bash
env $(cat .env | xargs) envsubst < config.template > config.conf
```

`envsubst < k8s/deployment.yaml.tmpl | kubectl apply -f -` — Template a Kubernetes manifest and apply it directly.

```bash
export IMAGE_TAG=v2.0 && envsubst < k8s/deployment.yaml.tmpl | kubectl apply -f -
```

## Common Patterns

`for f in *.tmpl; do envsubst < "$f" > "${f%.tmpl}"; done` — Process all template files and drop the `.tmpl` extension.

```bash
for f in conf/*.tmpl; do envsubst < "$f" > "${f%.tmpl}"; done
```

`envsubst --variables "$(cat template)" | sort` — List all variables a template requires.

```bash
envsubst --variables "$(cat nginx.conf.template)" | sort
```

`envsubst < template | diff template -` — Show what was substituted in a template.

```bash
envsubst < config.template | diff config.template -
```

<!-- PROSE:outro -->
## Conclusion

The strength of envsubst is its **safe, tightly scoped substitution**: it only swaps `$VAR`/`${VAR}` and, unlike `eval` or a shell, runs no commands at all – ideal for filling untrusted templates. When you pass a shell-format string such as `'$DB_HOST $DB_PORT'`, envsubst restricts substitution to exactly those variables; every other placeholder (for example nginx's own `$uri`) is left verbatim. Watch out for one pitfall, though: an unset variable is silently replaced with an **empty string** rather than reported as an error – use `envsubst --variables` to check that every required value is present in the environment before you rely on the output. envsubst has no `$$` escape for a literal dollar sign; to keep a reference verbatim, simply leave it out of the list of variables to substitute.

## Further Reading

- [GNU gettext: envsubst Invocation](https://www.gnu.org/software/gettext/manual/html_node/envsubst-Invocation.html) – official reference for invocation and options
- [GNU gettext: The Programmer's View](https://www.gnu.org/software/gettext/manual/html_node/index.html) – manual for the full gettext package that envsubst is part of
<!-- PROSE:outro:end -->

## Related Commands

- [sed](https://www.jpkc.com/db/en/cheatsheets/files-text/sed/) – stream editor for line-by-line search and replace in text streams
- [tr](https://www.jpkc.com/db/en/cheatsheets/files-text/tr/) – translate or delete individual characters in a text stream
- [tee](https://www.jpkc.com/db/en/cheatsheets/files-text/tee/) – write a data stream to a file and stdout at the same time

