docs(docs/admin/templates/extending-templates): clarify coder_env merge_strategy does not include host environment (#28466)

`merge_strategy` on `coder_env` only combines values across `coder_env`
resources targeting the same name. It does not know about the value
already set by the workspace's image or host, such as the base `PATH`. A
user hit this in #27501: appending to `PATH` with three `coder_env`
resources replaced the host's `PATH` entirely, since none of them
referenced the existing value.

Clarify this in the docs, and update the `PATH` example to show
referencing `$PATH` in one of the resources so the host's original value
is kept.

Refs #27501

<details>
<summary>Investigation notes</summary>

- `coderd/provisionerdserver/provisionerdserver.go` builds the merged
env starting from an empty map (`MergeExtraEnvs`), only combining
`coder_env` resources with each other.
- `agent/agent.go`'s `updateCommandEnv` applies the result with
`os.ExpandEnv(v)`, which expands `$VARNAME` against the agent's real
process environment.
- Confirmed with a standalone repro that `value =
"$PATH:/usr/local/cuda/bin"` preserves the host's real `PATH` and
appends the extra directory, and that this composes correctly across
multiple `coder_env` resources with `merge_strategy = "append"` as long
as one of them references `$PATH`.
- A companion PR updates the `terraform-provider-coder` schema
description and example that feed the registry docs:
https://github.com/coder/terraform-provider-coder (branch
`bpmct/docs-env-merge-host`).

</details>

---
*Opened by Coder Agents on behalf of @bpmct.*

---------

Co-authored-by: Nick Vigilante <nickvigilante@users.noreply.github.com>
This commit is contained in:
Ben Potter
2026-08-24 07:55:23 -05:00
committed by GitHub
co-authored by Nick Vigilante
parent 3c89b09734
commit 3bdd395faa
@@ -39,28 +39,50 @@ When multiple `coder_env` resources define the same variable name, use the
The `append` and `prepend` strategies use `:` as a separator, which matches
the convention for `PATH`-style variables on Unix systems.
### Merges and the host environment
`merge_strategy` only combines values across `coder_env` resources in the same template.
It does not know about the value already set by the workspace's image or host, such as the base `PATH`.
An `append` or `prepend` builds its value from `coder_env` resources alone, and that value replaces whatever the host had set for that variable.
To extend a variable that the host already sets, reference it directly in one of the values (for example, `$PATH`), so the agent expands it against the real environment at startup.
Only one resource in the chain needs the reference; the rest can use plain values.
The next example covers this.
### Example: Appending to PATH
Multiple `coder_env` resources can each add directories to `PATH`:
Multiple `coder_env` resources can each add directories to `PATH`.
Reference `$PATH` in one of them to keep the host's original directories:
```tf
resource "coder_env" "path_tools" {
resource "coder_agent" "dev" {
os = "linux"
arch = "amd64"
}
resource "coder_env" "path_cuda" {
agent_id = coder_agent.dev.id
name = "PATH"
value = "/home/coder/tools/bin"
value = "$PATH:/usr/local/cuda/bin"
merge_strategy = "append"
}
resource "coder_env" "path_go" {
agent_id = coder_agent.dev.id
name = "PATH"
value = "/home/coder/go/bin"
value = "/usr/local/go/bin"
merge_strategy = "append"
}
resource "coder_env" "path_rust_cargo" {
agent_id = coder_agent.dev.id
name = "PATH"
value = "/usr/local/cargo/bin"
merge_strategy = "append"
}
```
This produces `PATH` with the value
`/home/coder/tools/bin:/home/coder/go/bin`.
This produces `PATH` with the host's original value, followed by `/usr/local/cuda/bin:/usr/local/go/bin:/usr/local/cargo/bin`.
### Example: Preventing duplicates
@@ -83,9 +105,8 @@ a clear error message.
When multiple `coder_env` resources append or prepend to the same variable,
they are processed in alphabetical order by their
[Terraform resource address](https://developer.hashicorp.com/terraform/cli/state/resource-addressing).
In the PATH example above, `coder_env.path_go` is processed before
`coder_env.path_tools` because `path_go` sorts before `path_tools`
alphabetically.
In the previous `PATH` example, `coder_env.path_cuda` is processed first, then `coder_env.path_go`, then `coder_env.path_rust_cargo`, because that is their alphabetical order.
This is why only one resource in the chain needs the `$PATH` reference: the merged value is built as one string before it's expanded, so the reference works no matter where in the chain it appears.
## Agent env override